revision-id: 4cf8bd79c59f23bc2c11804723143423da037738 (mariadb-10.3.5-75-g4cf8bd7)
parent(s): ae6355f56ea1496a2de2ea271f95c89e47705ef0
committer: Alexey Botchkov
timestamp: 2018-04-23 16:43:25 +0400
message:
MDEV-14024 PCRE2.
server code switched to the PCRE2 features.
---
CMakeLists.txt | 2 +-
client/CMakeLists.txt | 2 +-
client/mysqltest.cc | 2 +-
cmake/pcre.cmake | 22 +--
config.h.cmake | 1 +
extra/mariabackup/CMakeLists.txt | 4 +-
extra/mariabackup/xb_regex.h | 2 +-
libmysqld/CMakeLists.txt | 2 +-
libmysqld/examples/CMakeLists.txt | 2 +-
.../sys_vars/r/sysvars_server_notembedded.result | 2 +-
sql/CMakeLists.txt | 2 +-
sql/item_cmpfunc.cc | 168 +++++----------------
sql/item_cmpfunc.h | 29 ++--
sql/item_strfunc.cc | 14 --
sql/item_strfunc.h | 2 -
sql/mysqld.cc | 17 ---
sql/mysqld.h | 2 -
sql/sys_vars.cc | 16 +-
storage/mroonga/CMakeLists.txt | 4 +-
19 files changed, 81 insertions(+), 214 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0813cf2..b59fb23 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -324,7 +324,7 @@ IF(NOT HAVE_CXX_NEW)
ENDIF()
# Find header files from the bundled libraries
-# (yassl, readline, pcre, etc)
+# (yassl, readline, pcre2, etc)
# before the ones installed in the system
SET(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index e0d34b9..02579ca 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -45,7 +45,7 @@ ENDIF(UNIX)
MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test)
SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqltest ${CLIENT_LIB} pcre pcreposix)
+TARGET_LINK_LIBRARIES(mysqltest ${CLIENT_LIB} pcre2-8 pcre2-posix)
SET_TARGET_PROPERTIES(mysqltest PROPERTIES ENABLE_EXPORTS TRUE)
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index efc25f3..bcabcbb 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -45,7 +45,7 @@
#include <stdarg.h>
#include <violite.h>
#define PCRE_STATIC 1 /* Important on Windows */
-#include "pcreposix.h" /* pcreposix regex library */
+#include "pcre2posix.h" /* pcreposix regex library */
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake
index 4c11392..25ecbae 100644
--- a/cmake/pcre.cmake
+++ b/cmake/pcre.cmake
@@ -5,24 +5,16 @@ SET(WITH_PCRE "auto" CACHE STRING
MACRO (CHECK_PCRE)
IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto")
- CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE_STACK_GUARD)
- IF(NOT CMAKE_CROSSCOMPILING)
- SET(CMAKE_REQUIRED_LIBRARIES "pcre")
- CHECK_C_SOURCE_RUNS("
- #include <pcre.h>
- int main() {
- return -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) < 256;
- }" PCRE_STACK_SIZE_OK)
- SET(CMAKE_REQUIRED_LIBRARIES)
- ENDIF()
+ CHECK_LIBRARY_EXISTS(pcre2-8 pcre2_match "" HAVE_PCRE2)
ENDIF()
- IF(NOT HAVE_PCRE_STACK_GUARD OR NOT PCRE_STACK_SIZE_OK OR
- WITH_PCRE STREQUAL "bundled")
+ IF(NOT HAVE_PCRE2 OR WITH_PCRE STREQUAL "bundled")
IF (WITH_PCRE STREQUAL "system")
- MESSAGE(FATAL_ERROR "system pcre is not found or unusable")
+ MESSAGE(FATAL_ERROR "system pcre2-8 library is not found or unusable")
ENDIF()
- SET(PCRE_INCLUDES ${CMAKE_BINARY_DIR}/pcre ${CMAKE_SOURCE_DIR}/pcre)
- ADD_SUBDIRECTORY(pcre)
+ SET(PCRE_INCLUDES ${CMAKE_BINARY_DIR}/pcre2 ${CMAKE_SOURCE_DIR}/pcre2
+ ${CMAKE_BINARY_DIR}/pcre2/src ${CMAKE_SOURCE_DIR}/pcre2/src)
+ SET(PCRE_BUILD_TESTS OFF CACHE BOOL "Build the test")
+ ADD_SUBDIRECTORY(pcre2)
ENDIF()
ENDMACRO()
diff --git a/config.h.cmake b/config.h.cmake
index 4d14b62..b039e39 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -552,6 +552,7 @@
#define PACKAGE_VERSION "@VERSION@"
#define VERSION "@VERSION@"
#define PROTOCOL_VERSION 10
+#define PCRE2_CODE_UNIT_WIDTH 8
#define MALLOC_LIBRARY "@MALLOC_LIBRARY@"
diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt
index f92da3f..a787251 100644
--- a/extra/mariabackup/CMakeLists.txt
+++ b/extra/mariabackup/CMakeLists.txt
@@ -37,7 +37,7 @@ INCLUDE_DIRECTORIES(
)
IF(NOT HAVE_SYSTEM_REGEX)
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre2 ${CMAKE_SOURCE_DIR}/pcre2/src)
ENDIF()
IF(WITH_WSREP)
@@ -92,7 +92,7 @@ ADD_SUBDIRECTORY(crc)
TARGET_LINK_LIBRARIES(mariabackup sql crc)
IF(NOT HAVE_SYSTEM_REGEX)
- TARGET_LINK_LIBRARIES(mariabackup pcreposix)
+ TARGET_LINK_LIBRARIES(mariabackup pcre2-posix)
ENDIF()
diff --git a/extra/mariabackup/xb_regex.h b/extra/mariabackup/xb_regex.h
index 2e07e43..6277d04 100644
--- a/extra/mariabackup/xb_regex.h
+++ b/extra/mariabackup/xb_regex.h
@@ -25,7 +25,7 @@ my_regex is used on Windows and native calls are used on POSIX platforms. */
#ifdef HAVE_SYSTEM_REGEX
#include <regex.h>
#else
-#include <pcreposix.h>
+#include <pcre2posix.h>
#endif
typedef regex_t* xb_regex_t;
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 718e832..29ddc2a 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -145,7 +145,7 @@ ENDIF()
SET(LIBS
- dbug strings mysys mysys_ssl pcre vio
+ dbug strings mysys mysys_ssl pcre2-8 vio
${ZLIB_LIBRARY} ${SSL_LIBRARIES}
${LIBWRAP} ${LIBCRYPT} ${LIBDL}
${MYSQLD_STATIC_PLUGIN_LIBS}
diff --git a/libmysqld/examples/CMakeLists.txt b/libmysqld/examples/CMakeLists.txt
index d47638a..c2f7766 100644
--- a/libmysqld/examples/CMakeLists.txt
+++ b/libmysqld/examples/CMakeLists.txt
@@ -34,7 +34,7 @@ ENDIF(UNIX)
MYSQL_ADD_EXECUTABLE(mysqltest_embedded ../../client/mysqltest.cc
COMPONENT Test)
-TARGET_LINK_LIBRARIES(mysqltest_embedded mysqlserver pcre pcreposix)
+TARGET_LINK_LIBRARIES(mysqltest_embedded mysqlserver pcre2-8 pcre2-posix)
IF(CMAKE_GENERATOR MATCHES "Xcode")
# It does not seem possible to tell Xcode the resulting target might need
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 67786cc..4d1d677 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -695,7 +695,7 @@ VARIABLE_COMMENT Default flags for the regex library
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST DOTALL,DUPNAMES,EXTENDED,EXTRA,MULTILINE,UNGREEDY
+ENUM_VALUE_LIST DOTALL,DUPNAMES,EXTENDED,EXTENDED_MORE,EXTRA,MULTILINE,UNGREEDY
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME DEFAULT_STORAGE_ENGINE
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index c7c4df2..6c461a7 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -177,7 +177,7 @@ ADD_LIBRARY(sql STATIC ${SQL_SOURCE})
ADD_DEPENDENCIES(sql GenServerSource)
DTRACE_INSTRUMENT(sql)
TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS}
- mysys mysys_ssl dbug strings vio pcre
+ mysys mysys_ssl dbug strings vio pcre2-8
${LIBWRAP} ${LIBCRYPT} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT}
${WSREP_LIB}
${SSL_LIBRARIES}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 89aa307..2b3afed 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5481,15 +5481,6 @@ int Regexp_processor_pcre::default_regex_flags()
return default_regex_flags_pcre(current_thd);
}
-void Regexp_processor_pcre::set_recursion_limit(THD *thd)
-{
- long stack_used;
- DBUG_ASSERT(thd == current_thd);
- stack_used= available_stack_size(thd->thread_stack, &stack_used);
- m_pcre_extra.match_limit_recursion=
- (ulong)((my_thread_stack_size - STACK_MIN_SIZE - stack_used)/my_pcre_frame_size);
-}
-
/**
Convert string to lib_charset, if needed.
@@ -5523,8 +5514,8 @@ String *Regexp_processor_pcre::convert_if_needed(String *str, String *converter)
bool Regexp_processor_pcre::compile(String *pattern, bool send_error)
{
- const char *pcreErrorStr;
- int pcreErrorOffset;
+ int pcreErrorNumber;
+ PCRE2_SIZE pcreErrorOffset;
if (is_compiled())
{
@@ -5537,19 +5528,32 @@ bool Regexp_processor_pcre::compile(String *pattern, bool send_error)
if (!(pattern= convert_if_needed(pattern, &pattern_converter)))
return true;
- m_pcre= pcre_compile(pattern->c_ptr_safe(), m_library_flags,
- &pcreErrorStr, &pcreErrorOffset, NULL);
+ m_pcre= pcre2_compile((PCRE2_SPTR8) pattern->ptr(), pattern->length(),
+ m_library_flags,
+ &pcreErrorNumber, &pcreErrorOffset, NULL);
if (m_pcre == NULL)
{
if (send_error)
{
char buff[MAX_FIELD_WIDTH];
- my_snprintf(buff, sizeof(buff), "%s at offset %d", pcreErrorStr, pcreErrorOffset);
+ int lmsg= pcre2_get_error_message(pcreErrorNumber,
+ (PCRE2_UCHAR8 *)buff, sizeof(buff));
+ if (lmsg >= 0)
+ my_snprintf(buff+lmsg, sizeof(buff)-lmsg,
+ " at offset %d", pcreErrorOffset);
my_error(ER_REGEXP_ERROR, MYF(0), buff);
}
return true;
}
+
+ m_pcre_match_data= pcre2_match_data_create_from_pattern(m_pcre, NULL);
+ if (m_pcre_match_data == NULL)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+
return false;
}
@@ -5570,124 +5574,43 @@ bool Regexp_processor_pcre::compile(Item *item, bool send_error)
*/
void Regexp_processor_pcre::pcre_exec_warn(int rc) const
{
- char buf[64];
- const char *errmsg= NULL;
+ PCRE2_UCHAR8 buf[128];
THD *thd= current_thd;
-
- /*
- Make a descriptive message only for those pcre_exec() error codes
- that can actually happen in MariaDB.
- */
- switch (rc)
- {
- case PCRE_ERROR_NULL:
- errmsg= "pcre_exec: null argument passed";
- break;
- case PCRE_ERROR_BADOPTION:
- errmsg= "pcre_exec: bad option";
- break;
- case PCRE_ERROR_BADMAGIC:
- errmsg= "pcre_exec: bad magic - not a compiled regex";
- break;
- case PCRE_ERROR_UNKNOWN_OPCODE:
- errmsg= "pcre_exec: error in compiled regex";
- break;
- case PCRE_ERROR_NOMEMORY:
- errmsg= "pcre_exec: Out of memory";
- break;
- case PCRE_ERROR_NOSUBSTRING:
- errmsg= "pcre_exec: no substring";
- break;
- case PCRE_ERROR_MATCHLIMIT:
- errmsg= "pcre_exec: match limit exceeded";
- break;
- case PCRE_ERROR_CALLOUT:
- errmsg= "pcre_exec: callout error";
- break;
- case PCRE_ERROR_BADUTF8:
- errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string";
- break;
- case PCRE_ERROR_BADUTF8_OFFSET:
- errmsg= "pcre_exec: Started at invalid location within utf8 byte sequence";
- break;
- case PCRE_ERROR_PARTIAL:
- errmsg= "pcre_exec: partial match";
- break;
- case PCRE_ERROR_INTERNAL:
- errmsg= "pcre_exec: internal error";
- break;
- case PCRE_ERROR_BADCOUNT:
- errmsg= "pcre_exec: ovesize is negative";
- break;
- case PCRE_ERROR_RECURSIONLIMIT:
- my_snprintf(buf, sizeof(buf), "pcre_exec: recursion limit of %ld exceeded",
- m_pcre_extra.match_limit_recursion);
- errmsg= buf;
- break;
- case PCRE_ERROR_BADNEWLINE:
- errmsg= "pcre_exec: bad newline options";
- break;
- case PCRE_ERROR_BADOFFSET:
- errmsg= "pcre_exec: start offset negative or greater than string length";
- break;
- case PCRE_ERROR_SHORTUTF8:
- errmsg= "pcre_exec: ended in middle of utf8 sequence";
- break;
- case PCRE_ERROR_JIT_STACKLIMIT:
- errmsg= "pcre_exec: insufficient stack memory for JIT compile";
- break;
- case PCRE_ERROR_RECURSELOOP:
- errmsg= "pcre_exec: Recursion loop detected";
- break;
- case PCRE_ERROR_BADMODE:
- errmsg= "pcre_exec: compiled pattern passed to wrong bit library function";
- break;
- case PCRE_ERROR_BADENDIANNESS:
- errmsg= "pcre_exec: compiled pattern passed to wrong endianness processor";
- break;
- case PCRE_ERROR_JIT_BADOPTION:
- errmsg= "pcre_exec: bad jit option";
- break;
- case PCRE_ERROR_BADLENGTH:
- errmsg= "pcre_exec: negative length";
- break;
- default:
- /*
- As other error codes should normally not happen,
- we just report the error code without textual description
- of the code.
- */
- my_snprintf(buf, sizeof(buf), "pcre_exec: Internal error (%d)", rc);
- errmsg= buf;
- }
+ int errlen= pcre2_get_error_message(rc, buf, sizeof(buf));
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_REGEXP_ERROR, ER_THD(thd, ER_REGEXP_ERROR), errmsg);
+ ER_REGEXP_ERROR, ER_THD(thd, ER_REGEXP_ERROR),
+ (errlen > 0) ? (const char *) buf : "Unknown PCRE error.");
}
/**
Call pcre_exec() and send a warning if pcre_exec() returned with an error.
*/
-int Regexp_processor_pcre::pcre_exec_with_warn(const pcre *code,
- const pcre_extra *extra,
+int Regexp_processor_pcre::pcre_exec_with_warn(const pcre2_code *code,
+ pcre2_match_data *data,
const char *subject,
int length, int startoffset,
- int options, int *ovector,
- int ovecsize)
+ uint options)
{
- int rc= pcre_exec(code, extra, subject, length,
- startoffset, options, ovector, ovecsize);
+ int rc= pcre2_match(code, (PCRE2_SPTR8) subject, (PCRE2_SIZE) length,
+ (PCRE2_SIZE) startoffset, options, data, NULL);
DBUG_EXECUTE_IF("pcre_exec_error_123", rc= -123;);
- if (rc < PCRE_ERROR_NOMATCH)
+ if (rc < PCRE2_ERROR_NOMATCH)
+ {
pcre_exec_warn(rc);
+ m_SubStrVec= NULL;
+ }
+ else
+ m_SubStrVec= pcre2_get_ovector_pointer(data);
+
return rc;
}
bool Regexp_processor_pcre::exec(const char *str, size_t length, size_t offset)
{
- m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str, (int)length, (int)offset, 0,
- m_SubStrVec, array_elements(m_SubStrVec));
+ m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, m_pcre_match_data,
+ str, (int)length, (int)offset, 0);
return false;
}
@@ -5697,10 +5620,8 @@ bool Regexp_processor_pcre::exec(String *str, int offset,
{
if (!(str= convert_if_needed(str, &subject_converter)))
return true;
- m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra,
- str->c_ptr_safe(), str->length(),
- offset, 0,
- m_SubStrVec, array_elements(m_SubStrVec));
+ m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, m_pcre_match_data,
+ str->ptr(), str->length(), offset, 0);
if (m_pcre_exec_rc > 0)
{
uint i;
@@ -5750,12 +5671,6 @@ void Regexp_processor_pcre::fix_owner(Item_func *owner,
}
-bool Item_func_regex::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_bool_func::fix_fields(thd, ref);
-}
-
void
Item_func_regex::fix_length_and_dec()
{
@@ -5782,13 +5697,6 @@ longlong Item_func_regex::val_int()
}
-bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_int_func::fix_fields(thd, ref);
-}
-
-
void
Item_func_regexp_instr::fix_length_and_dec()
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 3d11a22..797c54a 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -25,7 +25,7 @@
#include "item_func.h" /* Item_int_func, Item_bool_func */
#define PCRE_STATIC 1 /* Important on Windows */
-#include "pcre.h" /* pcre header file */
+#include "pcre2.h" /* pcre header file */
#include "item.h"
extern Item_result item_cmp_type(Item_result a,Item_result b);
@@ -2728,8 +2728,8 @@ class Item_func_like :public Item_bool_func2
class Regexp_processor_pcre
{
- pcre *m_pcre;
- pcre_extra m_pcre_extra;
+ pcre2_code *m_pcre;
+ pcre2_match_data *m_pcre_match_data;
bool m_conversion_is_needed;
bool m_is_const;
int m_library_flags;
@@ -2737,34 +2737,33 @@ class Regexp_processor_pcre
CHARSET_INFO *m_library_charset;
String m_prev_pattern;
int m_pcre_exec_rc;
- int m_SubStrVec[30];
+ PCRE2_SIZE *m_SubStrVec;
void pcre_exec_warn(int rc) const;
- int pcre_exec_with_warn(const pcre *code, const pcre_extra *extra,
+ int pcre_exec_with_warn(const pcre2_code *code,
+ pcre2_match_data *data,
const char *subject, int length, int startoffset,
- int options, int *ovector, int ovecsize);
+ uint options);
public:
String *convert_if_needed(String *src, String *converter);
String subject_converter;
String pattern_converter;
String replace_converter;
Regexp_processor_pcre() :
- m_pcre(NULL), m_conversion_is_needed(true), m_is_const(0),
+ m_pcre(NULL), m_pcre_match_data(NULL),
+ m_conversion_is_needed(true), m_is_const(0),
m_library_flags(0),
m_data_charset(&my_charset_utf8_general_ci),
m_library_charset(&my_charset_utf8_general_ci)
{
- m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
- m_pcre_extra.match_limit_recursion= 100L;
}
int default_regex_flags();
- void set_recursion_limit(THD *);
void init(CHARSET_INFO *data_charset, int extra_flags)
{
m_library_flags= default_regex_flags() | extra_flags |
(data_charset != &my_charset_bin ?
- (PCRE_UTF8 | PCRE_UCP) : 0) |
+ (PCRE2_UTF | PCRE2_UCP) : 0) |
((data_charset->state &
- (MY_CS_BINSORT | MY_CS_CSSORT)) ? 0 : PCRE_CASELESS);
+ (MY_CS_BINSORT | MY_CS_CSSORT)) ? 0 : PCRE2_CASELESS);
// Convert text data to utf-8.
m_library_charset= data_charset == &my_charset_bin ?
@@ -2800,11 +2799,13 @@ class Regexp_processor_pcre
void reset()
{
m_pcre= NULL;
+ m_pcre_match_data= NULL;
m_prev_pattern.length(0);
}
void cleanup()
{
- pcre_free(m_pcre);
+ pcre2_match_data_free(m_pcre_match_data);
+ pcre2_code_free(m_pcre);
reset();
}
bool is_compiled() const { return m_pcre != NULL; }
@@ -2829,7 +2830,6 @@ class Item_func_regex :public Item_bool_func
DBUG_VOID_RETURN;
}
longlong val_int();
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
@@ -2879,7 +2879,6 @@ class Item_func_regexp_instr :public Item_long_func
DBUG_VOID_RETURN;
}
longlong val_int();
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_instr"; }
Item *get_copy(THD *thd)
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index c6b0ae7..0a1480e 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1276,13 +1276,6 @@ void Item_func_replace::fix_length_and_dec()
/*********************************************************************/
-bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_str_func::fix_fields(thd, ref);
-}
-
-
void Item_func_regexp_replace::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3))
@@ -1418,13 +1411,6 @@ String *Item_func_regexp_replace::val_str(String *str)
}
-bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_str_func::fix_fields(thd, ref);
-}
-
-
void Item_func_regexp_substr::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2))
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 4e1514c..3606151 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -376,7 +376,6 @@ class Item_func_regexp_replace :public Item_str_func
DBUG_VOID_RETURN;
}
String *val_str(String *str);
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_replace"; }
Item *get_copy(THD *thd) { return 0;}
@@ -398,7 +397,6 @@ class Item_func_regexp_substr :public Item_str_func
DBUG_VOID_RETURN;
}
String *val_str(String *str);
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_substr"; }
Item *get_copy(THD *thd) { return 0; }
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index fe2b9c8..b735123 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -111,7 +111,6 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "sql_reload.h" // reload_acl_and_cache
-#include "pcre.h"
#ifdef HAVE_POLL_H
#include <poll.h>
@@ -3758,21 +3757,6 @@ static void init_libstrings()
#endif
}
-ulonglong my_pcre_frame_size;
-
-static void init_pcre()
-{
- pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld;
- pcre_free= pcre_stack_free= my_free;
- pcre_stack_guard= check_enough_stack_size_slow;
- /* See http://pcre.org/original/doc/html/pcrestack.html */
- my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0);
- // pcre can underestimate its stack usage. Use a safe value, as in the manual
- set_if_bigger(my_pcre_frame_size, 500);
- my_pcre_frame_size += 16; // Again, safety margin, see the manual
-}
-
-
/**
Initialize one of the global date/time format variables.
@@ -4560,7 +4544,6 @@ static int init_common_variables()
if (item_create_init())
return 1;
item_init();
- init_pcre();
/*
Process a comma-separated character set list and choose
the first available character set. This is mostly for
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 670e136..183757b 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -574,8 +574,6 @@ extern pthread_t signal_thread;
extern struct st_VioSSLFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
-extern ulonglong my_pcre_frame_size;
-
/*
The following variables were under INNODB_COMPABILITY_HOOKS
*/
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 524ce97..f2c9205 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5672,19 +5672,21 @@ static const char *default_regex_flags_names[]=
"DOTALL", // (?s) . matches anything including NL
"DUPNAMES", // (?J) Allow duplicate names for subpatterns
"EXTENDED", // (?x) Ignore white space and # comments
- "EXTRA", // (?X) extra features (e.g. error on unknown escape character)
+ "EXTENDED_MORE",//(?xx) Ignore white space and # comments inside cheracter
+ "EXTRA", // means nothing since PCRE2
"MULTILINE", // (?m) ^ and $ match newlines within data
"UNGREEDY", // (?U) Invert greediness of quantifiers
0
};
static const int default_regex_flags_to_pcre[]=
{
- PCRE_DOTALL,
- PCRE_DUPNAMES,
- PCRE_EXTENDED,
- PCRE_EXTRA,
- PCRE_MULTILINE,
- PCRE_UNGREEDY,
+ PCRE2_DOTALL,
+ PCRE2_DUPNAMES,
+ PCRE2_EXTENDED,
+ PCRE2_EXTENDED_MORE,
+ 0, /* EXTRA flag not available since PCRE2 */
+ PCRE2_MULTILINE,
+ PCRE2_UNGREEDY,
0
};
int default_regex_flags_pcre(const THD *thd)
diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt
index 5d8e8c1..57d12a1 100644
--- a/storage/mroonga/CMakeLists.txt
+++ b/storage/mroonga/CMakeLists.txt
@@ -189,8 +189,8 @@ else()
set(MYSQL_VARIANT "MySQL")
endif()
-if(EXISTS "${MYSQL_SOURCE_DIR}/pcre")
- set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/pcre")
+if(EXISTS "${MYSQL_SOURCE_DIR}/pcre2")
+ set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/pcre2/src")
else()
set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/regex")
endif()
1
0
revision-id: 4cf8bd79c59f23bc2c11804723143423da037738 (mariadb-10.3.5-75-g4cf8bd7)
parent(s): ae6355f56ea1496a2de2ea271f95c89e47705ef0
committer: Alexey Botchkov
timestamp: 2018-04-23 16:43:25 +0400
message:
MDEV-14024 PCRE2.
server code switched to the PCRE2 features.
---
CMakeLists.txt | 2 +-
client/CMakeLists.txt | 2 +-
client/mysqltest.cc | 2 +-
cmake/pcre.cmake | 22 +--
config.h.cmake | 1 +
extra/mariabackup/CMakeLists.txt | 4 +-
extra/mariabackup/xb_regex.h | 2 +-
libmysqld/CMakeLists.txt | 2 +-
libmysqld/examples/CMakeLists.txt | 2 +-
.../sys_vars/r/sysvars_server_notembedded.result | 2 +-
sql/CMakeLists.txt | 2 +-
sql/item_cmpfunc.cc | 168 +++++----------------
sql/item_cmpfunc.h | 29 ++--
sql/item_strfunc.cc | 14 --
sql/item_strfunc.h | 2 -
sql/mysqld.cc | 17 ---
sql/mysqld.h | 2 -
sql/sys_vars.cc | 16 +-
storage/mroonga/CMakeLists.txt | 4 +-
19 files changed, 81 insertions(+), 214 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0813cf2..b59fb23 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -324,7 +324,7 @@ IF(NOT HAVE_CXX_NEW)
ENDIF()
# Find header files from the bundled libraries
-# (yassl, readline, pcre, etc)
+# (yassl, readline, pcre2, etc)
# before the ones installed in the system
SET(CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE ON)
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index e0d34b9..02579ca 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -45,7 +45,7 @@ ENDIF(UNIX)
MYSQL_ADD_EXECUTABLE(mysqltest mysqltest.cc COMPONENT Test)
SET_SOURCE_FILES_PROPERTIES(mysqltest.cc PROPERTIES COMPILE_FLAGS "-DTHREADS")
-TARGET_LINK_LIBRARIES(mysqltest ${CLIENT_LIB} pcre pcreposix)
+TARGET_LINK_LIBRARIES(mysqltest ${CLIENT_LIB} pcre2-8 pcre2-posix)
SET_TARGET_PROPERTIES(mysqltest PROPERTIES ENABLE_EXPORTS TRUE)
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index efc25f3..bcabcbb 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -45,7 +45,7 @@
#include <stdarg.h>
#include <violite.h>
#define PCRE_STATIC 1 /* Important on Windows */
-#include "pcreposix.h" /* pcreposix regex library */
+#include "pcre2posix.h" /* pcreposix regex library */
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
diff --git a/cmake/pcre.cmake b/cmake/pcre.cmake
index 4c11392..25ecbae 100644
--- a/cmake/pcre.cmake
+++ b/cmake/pcre.cmake
@@ -5,24 +5,16 @@ SET(WITH_PCRE "auto" CACHE STRING
MACRO (CHECK_PCRE)
IF(WITH_PCRE STREQUAL "system" OR WITH_PCRE STREQUAL "auto")
- CHECK_LIBRARY_EXISTS(pcre pcre_stack_guard "" HAVE_PCRE_STACK_GUARD)
- IF(NOT CMAKE_CROSSCOMPILING)
- SET(CMAKE_REQUIRED_LIBRARIES "pcre")
- CHECK_C_SOURCE_RUNS("
- #include <pcre.h>
- int main() {
- return -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0) < 256;
- }" PCRE_STACK_SIZE_OK)
- SET(CMAKE_REQUIRED_LIBRARIES)
- ENDIF()
+ CHECK_LIBRARY_EXISTS(pcre2-8 pcre2_match "" HAVE_PCRE2)
ENDIF()
- IF(NOT HAVE_PCRE_STACK_GUARD OR NOT PCRE_STACK_SIZE_OK OR
- WITH_PCRE STREQUAL "bundled")
+ IF(NOT HAVE_PCRE2 OR WITH_PCRE STREQUAL "bundled")
IF (WITH_PCRE STREQUAL "system")
- MESSAGE(FATAL_ERROR "system pcre is not found or unusable")
+ MESSAGE(FATAL_ERROR "system pcre2-8 library is not found or unusable")
ENDIF()
- SET(PCRE_INCLUDES ${CMAKE_BINARY_DIR}/pcre ${CMAKE_SOURCE_DIR}/pcre)
- ADD_SUBDIRECTORY(pcre)
+ SET(PCRE_INCLUDES ${CMAKE_BINARY_DIR}/pcre2 ${CMAKE_SOURCE_DIR}/pcre2
+ ${CMAKE_BINARY_DIR}/pcre2/src ${CMAKE_SOURCE_DIR}/pcre2/src)
+ SET(PCRE_BUILD_TESTS OFF CACHE BOOL "Build the test")
+ ADD_SUBDIRECTORY(pcre2)
ENDIF()
ENDMACRO()
diff --git a/config.h.cmake b/config.h.cmake
index 4d14b62..b039e39 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -552,6 +552,7 @@
#define PACKAGE_VERSION "@VERSION@"
#define VERSION "@VERSION@"
#define PROTOCOL_VERSION 10
+#define PCRE2_CODE_UNIT_WIDTH 8
#define MALLOC_LIBRARY "@MALLOC_LIBRARY@"
diff --git a/extra/mariabackup/CMakeLists.txt b/extra/mariabackup/CMakeLists.txt
index f92da3f..a787251 100644
--- a/extra/mariabackup/CMakeLists.txt
+++ b/extra/mariabackup/CMakeLists.txt
@@ -37,7 +37,7 @@ INCLUDE_DIRECTORIES(
)
IF(NOT HAVE_SYSTEM_REGEX)
- INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre)
+ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pcre2 ${CMAKE_SOURCE_DIR}/pcre2/src)
ENDIF()
IF(WITH_WSREP)
@@ -92,7 +92,7 @@ ADD_SUBDIRECTORY(crc)
TARGET_LINK_LIBRARIES(mariabackup sql crc)
IF(NOT HAVE_SYSTEM_REGEX)
- TARGET_LINK_LIBRARIES(mariabackup pcreposix)
+ TARGET_LINK_LIBRARIES(mariabackup pcre2-posix)
ENDIF()
diff --git a/extra/mariabackup/xb_regex.h b/extra/mariabackup/xb_regex.h
index 2e07e43..6277d04 100644
--- a/extra/mariabackup/xb_regex.h
+++ b/extra/mariabackup/xb_regex.h
@@ -25,7 +25,7 @@ my_regex is used on Windows and native calls are used on POSIX platforms. */
#ifdef HAVE_SYSTEM_REGEX
#include <regex.h>
#else
-#include <pcreposix.h>
+#include <pcre2posix.h>
#endif
typedef regex_t* xb_regex_t;
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 718e832..29ddc2a 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -145,7 +145,7 @@ ENDIF()
SET(LIBS
- dbug strings mysys mysys_ssl pcre vio
+ dbug strings mysys mysys_ssl pcre2-8 vio
${ZLIB_LIBRARY} ${SSL_LIBRARIES}
${LIBWRAP} ${LIBCRYPT} ${LIBDL}
${MYSQLD_STATIC_PLUGIN_LIBS}
diff --git a/libmysqld/examples/CMakeLists.txt b/libmysqld/examples/CMakeLists.txt
index d47638a..c2f7766 100644
--- a/libmysqld/examples/CMakeLists.txt
+++ b/libmysqld/examples/CMakeLists.txt
@@ -34,7 +34,7 @@ ENDIF(UNIX)
MYSQL_ADD_EXECUTABLE(mysqltest_embedded ../../client/mysqltest.cc
COMPONENT Test)
-TARGET_LINK_LIBRARIES(mysqltest_embedded mysqlserver pcre pcreposix)
+TARGET_LINK_LIBRARIES(mysqltest_embedded mysqlserver pcre2-8 pcre2-posix)
IF(CMAKE_GENERATOR MATCHES "Xcode")
# It does not seem possible to tell Xcode the resulting target might need
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index 67786cc..4d1d677 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -695,7 +695,7 @@ VARIABLE_COMMENT Default flags for the regex library
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST DOTALL,DUPNAMES,EXTENDED,EXTRA,MULTILINE,UNGREEDY
+ENUM_VALUE_LIST DOTALL,DUPNAMES,EXTENDED,EXTENDED_MORE,EXTRA,MULTILINE,UNGREEDY
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME DEFAULT_STORAGE_ENGINE
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index c7c4df2..6c461a7 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -177,7 +177,7 @@ ADD_LIBRARY(sql STATIC ${SQL_SOURCE})
ADD_DEPENDENCIES(sql GenServerSource)
DTRACE_INSTRUMENT(sql)
TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS}
- mysys mysys_ssl dbug strings vio pcre
+ mysys mysys_ssl dbug strings vio pcre2-8
${LIBWRAP} ${LIBCRYPT} ${LIBDL} ${CMAKE_THREAD_LIBS_INIT}
${WSREP_LIB}
${SSL_LIBRARIES}
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 89aa307..2b3afed 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5481,15 +5481,6 @@ int Regexp_processor_pcre::default_regex_flags()
return default_regex_flags_pcre(current_thd);
}
-void Regexp_processor_pcre::set_recursion_limit(THD *thd)
-{
- long stack_used;
- DBUG_ASSERT(thd == current_thd);
- stack_used= available_stack_size(thd->thread_stack, &stack_used);
- m_pcre_extra.match_limit_recursion=
- (ulong)((my_thread_stack_size - STACK_MIN_SIZE - stack_used)/my_pcre_frame_size);
-}
-
/**
Convert string to lib_charset, if needed.
@@ -5523,8 +5514,8 @@ String *Regexp_processor_pcre::convert_if_needed(String *str, String *converter)
bool Regexp_processor_pcre::compile(String *pattern, bool send_error)
{
- const char *pcreErrorStr;
- int pcreErrorOffset;
+ int pcreErrorNumber;
+ PCRE2_SIZE pcreErrorOffset;
if (is_compiled())
{
@@ -5537,19 +5528,32 @@ bool Regexp_processor_pcre::compile(String *pattern, bool send_error)
if (!(pattern= convert_if_needed(pattern, &pattern_converter)))
return true;
- m_pcre= pcre_compile(pattern->c_ptr_safe(), m_library_flags,
- &pcreErrorStr, &pcreErrorOffset, NULL);
+ m_pcre= pcre2_compile((PCRE2_SPTR8) pattern->ptr(), pattern->length(),
+ m_library_flags,
+ &pcreErrorNumber, &pcreErrorOffset, NULL);
if (m_pcre == NULL)
{
if (send_error)
{
char buff[MAX_FIELD_WIDTH];
- my_snprintf(buff, sizeof(buff), "%s at offset %d", pcreErrorStr, pcreErrorOffset);
+ int lmsg= pcre2_get_error_message(pcreErrorNumber,
+ (PCRE2_UCHAR8 *)buff, sizeof(buff));
+ if (lmsg >= 0)
+ my_snprintf(buff+lmsg, sizeof(buff)-lmsg,
+ " at offset %d", pcreErrorOffset);
my_error(ER_REGEXP_ERROR, MYF(0), buff);
}
return true;
}
+
+ m_pcre_match_data= pcre2_match_data_create_from_pattern(m_pcre, NULL);
+ if (m_pcre_match_data == NULL)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ return true;
+ }
+
return false;
}
@@ -5570,124 +5574,43 @@ bool Regexp_processor_pcre::compile(Item *item, bool send_error)
*/
void Regexp_processor_pcre::pcre_exec_warn(int rc) const
{
- char buf[64];
- const char *errmsg= NULL;
+ PCRE2_UCHAR8 buf[128];
THD *thd= current_thd;
-
- /*
- Make a descriptive message only for those pcre_exec() error codes
- that can actually happen in MariaDB.
- */
- switch (rc)
- {
- case PCRE_ERROR_NULL:
- errmsg= "pcre_exec: null argument passed";
- break;
- case PCRE_ERROR_BADOPTION:
- errmsg= "pcre_exec: bad option";
- break;
- case PCRE_ERROR_BADMAGIC:
- errmsg= "pcre_exec: bad magic - not a compiled regex";
- break;
- case PCRE_ERROR_UNKNOWN_OPCODE:
- errmsg= "pcre_exec: error in compiled regex";
- break;
- case PCRE_ERROR_NOMEMORY:
- errmsg= "pcre_exec: Out of memory";
- break;
- case PCRE_ERROR_NOSUBSTRING:
- errmsg= "pcre_exec: no substring";
- break;
- case PCRE_ERROR_MATCHLIMIT:
- errmsg= "pcre_exec: match limit exceeded";
- break;
- case PCRE_ERROR_CALLOUT:
- errmsg= "pcre_exec: callout error";
- break;
- case PCRE_ERROR_BADUTF8:
- errmsg= "pcre_exec: Invalid utf8 byte sequence in the subject string";
- break;
- case PCRE_ERROR_BADUTF8_OFFSET:
- errmsg= "pcre_exec: Started at invalid location within utf8 byte sequence";
- break;
- case PCRE_ERROR_PARTIAL:
- errmsg= "pcre_exec: partial match";
- break;
- case PCRE_ERROR_INTERNAL:
- errmsg= "pcre_exec: internal error";
- break;
- case PCRE_ERROR_BADCOUNT:
- errmsg= "pcre_exec: ovesize is negative";
- break;
- case PCRE_ERROR_RECURSIONLIMIT:
- my_snprintf(buf, sizeof(buf), "pcre_exec: recursion limit of %ld exceeded",
- m_pcre_extra.match_limit_recursion);
- errmsg= buf;
- break;
- case PCRE_ERROR_BADNEWLINE:
- errmsg= "pcre_exec: bad newline options";
- break;
- case PCRE_ERROR_BADOFFSET:
- errmsg= "pcre_exec: start offset negative or greater than string length";
- break;
- case PCRE_ERROR_SHORTUTF8:
- errmsg= "pcre_exec: ended in middle of utf8 sequence";
- break;
- case PCRE_ERROR_JIT_STACKLIMIT:
- errmsg= "pcre_exec: insufficient stack memory for JIT compile";
- break;
- case PCRE_ERROR_RECURSELOOP:
- errmsg= "pcre_exec: Recursion loop detected";
- break;
- case PCRE_ERROR_BADMODE:
- errmsg= "pcre_exec: compiled pattern passed to wrong bit library function";
- break;
- case PCRE_ERROR_BADENDIANNESS:
- errmsg= "pcre_exec: compiled pattern passed to wrong endianness processor";
- break;
- case PCRE_ERROR_JIT_BADOPTION:
- errmsg= "pcre_exec: bad jit option";
- break;
- case PCRE_ERROR_BADLENGTH:
- errmsg= "pcre_exec: negative length";
- break;
- default:
- /*
- As other error codes should normally not happen,
- we just report the error code without textual description
- of the code.
- */
- my_snprintf(buf, sizeof(buf), "pcre_exec: Internal error (%d)", rc);
- errmsg= buf;
- }
+ int errlen= pcre2_get_error_message(rc, buf, sizeof(buf));
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_REGEXP_ERROR, ER_THD(thd, ER_REGEXP_ERROR), errmsg);
+ ER_REGEXP_ERROR, ER_THD(thd, ER_REGEXP_ERROR),
+ (errlen > 0) ? (const char *) buf : "Unknown PCRE error.");
}
/**
Call pcre_exec() and send a warning if pcre_exec() returned with an error.
*/
-int Regexp_processor_pcre::pcre_exec_with_warn(const pcre *code,
- const pcre_extra *extra,
+int Regexp_processor_pcre::pcre_exec_with_warn(const pcre2_code *code,
+ pcre2_match_data *data,
const char *subject,
int length, int startoffset,
- int options, int *ovector,
- int ovecsize)
+ uint options)
{
- int rc= pcre_exec(code, extra, subject, length,
- startoffset, options, ovector, ovecsize);
+ int rc= pcre2_match(code, (PCRE2_SPTR8) subject, (PCRE2_SIZE) length,
+ (PCRE2_SIZE) startoffset, options, data, NULL);
DBUG_EXECUTE_IF("pcre_exec_error_123", rc= -123;);
- if (rc < PCRE_ERROR_NOMATCH)
+ if (rc < PCRE2_ERROR_NOMATCH)
+ {
pcre_exec_warn(rc);
+ m_SubStrVec= NULL;
+ }
+ else
+ m_SubStrVec= pcre2_get_ovector_pointer(data);
+
return rc;
}
bool Regexp_processor_pcre::exec(const char *str, size_t length, size_t offset)
{
- m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra, str, (int)length, (int)offset, 0,
- m_SubStrVec, array_elements(m_SubStrVec));
+ m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, m_pcre_match_data,
+ str, (int)length, (int)offset, 0);
return false;
}
@@ -5697,10 +5620,8 @@ bool Regexp_processor_pcre::exec(String *str, int offset,
{
if (!(str= convert_if_needed(str, &subject_converter)))
return true;
- m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, &m_pcre_extra,
- str->c_ptr_safe(), str->length(),
- offset, 0,
- m_SubStrVec, array_elements(m_SubStrVec));
+ m_pcre_exec_rc= pcre_exec_with_warn(m_pcre, m_pcre_match_data,
+ str->ptr(), str->length(), offset, 0);
if (m_pcre_exec_rc > 0)
{
uint i;
@@ -5750,12 +5671,6 @@ void Regexp_processor_pcre::fix_owner(Item_func *owner,
}
-bool Item_func_regex::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_bool_func::fix_fields(thd, ref);
-}
-
void
Item_func_regex::fix_length_and_dec()
{
@@ -5782,13 +5697,6 @@ longlong Item_func_regex::val_int()
}
-bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_int_func::fix_fields(thd, ref);
-}
-
-
void
Item_func_regexp_instr::fix_length_and_dec()
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 3d11a22..797c54a 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -25,7 +25,7 @@
#include "item_func.h" /* Item_int_func, Item_bool_func */
#define PCRE_STATIC 1 /* Important on Windows */
-#include "pcre.h" /* pcre header file */
+#include "pcre2.h" /* pcre header file */
#include "item.h"
extern Item_result item_cmp_type(Item_result a,Item_result b);
@@ -2728,8 +2728,8 @@ class Item_func_like :public Item_bool_func2
class Regexp_processor_pcre
{
- pcre *m_pcre;
- pcre_extra m_pcre_extra;
+ pcre2_code *m_pcre;
+ pcre2_match_data *m_pcre_match_data;
bool m_conversion_is_needed;
bool m_is_const;
int m_library_flags;
@@ -2737,34 +2737,33 @@ class Regexp_processor_pcre
CHARSET_INFO *m_library_charset;
String m_prev_pattern;
int m_pcre_exec_rc;
- int m_SubStrVec[30];
+ PCRE2_SIZE *m_SubStrVec;
void pcre_exec_warn(int rc) const;
- int pcre_exec_with_warn(const pcre *code, const pcre_extra *extra,
+ int pcre_exec_with_warn(const pcre2_code *code,
+ pcre2_match_data *data,
const char *subject, int length, int startoffset,
- int options, int *ovector, int ovecsize);
+ uint options);
public:
String *convert_if_needed(String *src, String *converter);
String subject_converter;
String pattern_converter;
String replace_converter;
Regexp_processor_pcre() :
- m_pcre(NULL), m_conversion_is_needed(true), m_is_const(0),
+ m_pcre(NULL), m_pcre_match_data(NULL),
+ m_conversion_is_needed(true), m_is_const(0),
m_library_flags(0),
m_data_charset(&my_charset_utf8_general_ci),
m_library_charset(&my_charset_utf8_general_ci)
{
- m_pcre_extra.flags= PCRE_EXTRA_MATCH_LIMIT_RECURSION;
- m_pcre_extra.match_limit_recursion= 100L;
}
int default_regex_flags();
- void set_recursion_limit(THD *);
void init(CHARSET_INFO *data_charset, int extra_flags)
{
m_library_flags= default_regex_flags() | extra_flags |
(data_charset != &my_charset_bin ?
- (PCRE_UTF8 | PCRE_UCP) : 0) |
+ (PCRE2_UTF | PCRE2_UCP) : 0) |
((data_charset->state &
- (MY_CS_BINSORT | MY_CS_CSSORT)) ? 0 : PCRE_CASELESS);
+ (MY_CS_BINSORT | MY_CS_CSSORT)) ? 0 : PCRE2_CASELESS);
// Convert text data to utf-8.
m_library_charset= data_charset == &my_charset_bin ?
@@ -2800,11 +2799,13 @@ class Regexp_processor_pcre
void reset()
{
m_pcre= NULL;
+ m_pcre_match_data= NULL;
m_prev_pattern.length(0);
}
void cleanup()
{
- pcre_free(m_pcre);
+ pcre2_match_data_free(m_pcre_match_data);
+ pcre2_code_free(m_pcre);
reset();
}
bool is_compiled() const { return m_pcre != NULL; }
@@ -2829,7 +2830,6 @@ class Item_func_regex :public Item_bool_func
DBUG_VOID_RETURN;
}
longlong val_int();
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
@@ -2879,7 +2879,6 @@ class Item_func_regexp_instr :public Item_long_func
DBUG_VOID_RETURN;
}
longlong val_int();
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_instr"; }
Item *get_copy(THD *thd)
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index c6b0ae7..0a1480e 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1276,13 +1276,6 @@ void Item_func_replace::fix_length_and_dec()
/*********************************************************************/
-bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_str_func::fix_fields(thd, ref);
-}
-
-
void Item_func_regexp_replace::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3))
@@ -1418,13 +1411,6 @@ String *Item_func_regexp_replace::val_str(String *str)
}
-bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref)
-{
- re.set_recursion_limit(thd);
- return Item_str_func::fix_fields(thd, ref);
-}
-
-
void Item_func_regexp_substr::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2))
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 4e1514c..3606151 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -376,7 +376,6 @@ class Item_func_regexp_replace :public Item_str_func
DBUG_VOID_RETURN;
}
String *val_str(String *str);
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_replace"; }
Item *get_copy(THD *thd) { return 0;}
@@ -398,7 +397,6 @@ class Item_func_regexp_substr :public Item_str_func
DBUG_VOID_RETURN;
}
String *val_str(String *str);
- bool fix_fields(THD *thd, Item **ref);
void fix_length_and_dec();
const char *func_name() const { return "regexp_substr"; }
Item *get_copy(THD *thd) { return 0; }
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index fe2b9c8..b735123 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -111,7 +111,6 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
#include "sql_reload.h" // reload_acl_and_cache
-#include "pcre.h"
#ifdef HAVE_POLL_H
#include <poll.h>
@@ -3758,21 +3757,6 @@ static void init_libstrings()
#endif
}
-ulonglong my_pcre_frame_size;
-
-static void init_pcre()
-{
- pcre_malloc= pcre_stack_malloc= my_str_malloc_mysqld;
- pcre_free= pcre_stack_free= my_free;
- pcre_stack_guard= check_enough_stack_size_slow;
- /* See http://pcre.org/original/doc/html/pcrestack.html */
- my_pcre_frame_size= -pcre_exec(NULL, NULL, NULL, -999, -999, 0, NULL, 0);
- // pcre can underestimate its stack usage. Use a safe value, as in the manual
- set_if_bigger(my_pcre_frame_size, 500);
- my_pcre_frame_size += 16; // Again, safety margin, see the manual
-}
-
-
/**
Initialize one of the global date/time format variables.
@@ -4560,7 +4544,6 @@ static int init_common_variables()
if (item_create_init())
return 1;
item_init();
- init_pcre();
/*
Process a comma-separated character set list and choose
the first available character set. This is mostly for
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 670e136..183757b 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -574,8 +574,6 @@ extern pthread_t signal_thread;
extern struct st_VioSSLFd * ssl_acceptor_fd;
#endif /* HAVE_OPENSSL */
-extern ulonglong my_pcre_frame_size;
-
/*
The following variables were under INNODB_COMPABILITY_HOOKS
*/
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 524ce97..f2c9205 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5672,19 +5672,21 @@ static const char *default_regex_flags_names[]=
"DOTALL", // (?s) . matches anything including NL
"DUPNAMES", // (?J) Allow duplicate names for subpatterns
"EXTENDED", // (?x) Ignore white space and # comments
- "EXTRA", // (?X) extra features (e.g. error on unknown escape character)
+ "EXTENDED_MORE",//(?xx) Ignore white space and # comments inside cheracter
+ "EXTRA", // means nothing since PCRE2
"MULTILINE", // (?m) ^ and $ match newlines within data
"UNGREEDY", // (?U) Invert greediness of quantifiers
0
};
static const int default_regex_flags_to_pcre[]=
{
- PCRE_DOTALL,
- PCRE_DUPNAMES,
- PCRE_EXTENDED,
- PCRE_EXTRA,
- PCRE_MULTILINE,
- PCRE_UNGREEDY,
+ PCRE2_DOTALL,
+ PCRE2_DUPNAMES,
+ PCRE2_EXTENDED,
+ PCRE2_EXTENDED_MORE,
+ 0, /* EXTRA flag not available since PCRE2 */
+ PCRE2_MULTILINE,
+ PCRE2_UNGREEDY,
0
};
int default_regex_flags_pcre(const THD *thd)
diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt
index 5d8e8c1..57d12a1 100644
--- a/storage/mroonga/CMakeLists.txt
+++ b/storage/mroonga/CMakeLists.txt
@@ -189,8 +189,8 @@ else()
set(MYSQL_VARIANT "MySQL")
endif()
-if(EXISTS "${MYSQL_SOURCE_DIR}/pcre")
- set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/pcre")
+if(EXISTS "${MYSQL_SOURCE_DIR}/pcre2")
+ set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/pcre2/src")
else()
set(MYSQL_REGEX_INCLUDE_DIR "${MYSQL_SOURCE_DIR}/regex")
endif()
1
0

[Commits] bf34851c549: MDEV-15079: Parameter array operation inserts wrong values in autoincrement field if indicator was specified
by Oleksandr Byelkin 23 Apr '18
by Oleksandr Byelkin 23 Apr '18
23 Apr '18
revision-id: bf34851c549859551549baee2e3e93abef3c39fb (mariadb-10.3.6-36-gbf34851c549)
parent(s): c6ba758d1d41c11466b8f9b61b4546efc95aa689
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-04-23 12:09:10 +0200
message:
MDEV-15079: Parameter array operation inserts wrong values in autoincrement field if indicator was specified
test added (bug is fixed)
---
tests/mysql_client_test.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index 5a275c8fcbf..3188ea882bb 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -20227,6 +20227,59 @@ static void test_proxy_header_ignore()
}
+static void test_bulk_autoinc()
+{
+ int rc;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[1];
+ MYSQL_ROW row;
+ char indicator[]= {0, STMT_INDICATOR_NULL, 0/*STMT_INDICATOR_IGNORE*/};
+ my_bool error[1];
+ int i, id[]= {2, 3, 777}, count= sizeof(id)/sizeof(id[0]);
+ MYSQL_RES *result;
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS ai_field_value");
+ myquery(rc);
+ rc= mysql_query(mysql, "CREATE TABLE ai_field_value (id int not null primary key auto_increment)");
+ myquery(rc);
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_prepare(stmt, "INSERT INTO ai_field_value(id) values(?)", -1);
+ check_execute(stmt, rc);
+
+ memset(bind, 0, sizeof(bind));
+ bind[0].buffer_type = MYSQL_TYPE_LONG;
+ bind[0].buffer = (void *)id;
+ bind[0].buffer_length = 0;
+ bind[0].is_null = NULL;
+ bind[0].length = NULL;
+ bind[0].error = error;
+ bind[0].u.indicator= indicator;
+
+ mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count);
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "SELECT id FROM ai_field_value");
+ myquery(rc);
+
+ result= mysql_store_result(mysql);
+ mytest(result);
+
+ i= 0;
+ while ((row= mysql_fetch_row(result)))
+ {
+ DIE_IF(atoi(row[0]) != id[i++]);
+ }
+ rc= mysql_query(mysql, "DROP TABLE ai_field_value");
+ myquery(rc);
+}
+
+
static void test_proxy_header()
{
test_proxy_header_tcp("192.0.2.1",3333);
@@ -20524,6 +20577,7 @@ static struct my_tests_st my_tests[]= {
#ifndef EMBEDDED_LIBRARY
{ "test_proxy_header", test_proxy_header},
#endif
+ { "test_bulk_autoinc", test_bulk_autoinc},
{ 0, 0 }
};
1
0

[Commits] a20e1ce85ec: MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 && pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->thread)' failed in _ma_state_info_write
by Oleksandr Byelkin 23 Apr '18
by Oleksandr Byelkin 23 Apr '18
23 Apr '18
revision-id: a20e1ce85ec56616fa048e9ba39c25c65b098fce (mariadb-10.3.6-36-ga20e1ce85ec)
parent(s): c6ba758d1d41c11466b8f9b61b4546efc95aa689
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-04-23 10:35:33 +0200
message:
MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 && pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->thread)' failed in _ma_state_info_write
Limit length of result of "negative" operation to something reasonable
---
mysql-test/main/union.result | 14 ++++++++++++++
mysql-test/main/union.test | 15 +++++++++++++++
sql/item_func.cc | 3 +++
3 files changed, 32 insertions(+)
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index 4e5f9312e03..39cd68ae851 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -2500,5 +2500,19 @@ t2 CREATE TABLE `t2` (
DROP TABLE t2;
DROP TABLE t1;
#
+# MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 &&
+# pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->
+# thread)' failed in _ma_state_info_write
+#
+CREATE TABLE t1 (c1 CHAR(8));
+INSERT INTO t1 VALUES ('10'),('-10');
+CREATE TABLE t2 (c2 CHAR);
+SET @a= CAST('10' AS CHAR);
+SELECT c1 FROM t1 UNION SELECT - @a FROM t2;
+c1
+10
+-10
+drop table t1,t2;
+#
# End of 10.3 tests
#
diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test
index f86cae87524..b9b38271f83 100644
--- a/mysql-test/main/union.test
+++ b/mysql-test/main/union.test
@@ -1745,6 +1745,21 @@ SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
+--echo #
+--echo # MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 &&
+--echo # pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->
+--echo # thread)' failed in _ma_state_info_write
+--echo #
+
+CREATE TABLE t1 (c1 CHAR(8));
+INSERT INTO t1 VALUES ('10'),('-10');
+
+CREATE TABLE t2 (c2 CHAR);
+SET @a= CAST('10' AS CHAR);
+
+SELECT c1 FROM t1 UNION SELECT - @a FROM t2;
+
+drop table t1,t2;
--echo #
--echo # End of 10.3 tests
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e2740272385..ae6c61e83f4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1935,6 +1935,9 @@ void Item_func_neg::fix_length_and_dec_double()
set_handler(&type_handler_double);
decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
max_length= args[0]->max_length + 1;
+ // Limit length with something reasonable
+ uint32 mlen= type_handler()->max_display_length(this);
+ set_if_smaller(max_length, mlen);
unsigned_flag= false;
}
2
1

[Commits] a20e1ce85ec: MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 && pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->thread)' failed in _ma_state_info_write
by Oleksandr Byelkin 23 Apr '18
by Oleksandr Byelkin 23 Apr '18
23 Apr '18
revision-id: a20e1ce85ec56616fa048e9ba39c25c65b098fce (mariadb-10.3.6-36-ga20e1ce85ec)
parent(s): c6ba758d1d41c11466b8f9b61b4546efc95aa689
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-04-23 10:35:33 +0200
message:
MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 && pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->thread)' failed in _ma_state_info_write
Limit length of result of "negative" operation to something reasonable
---
mysql-test/main/union.result | 14 ++++++++++++++
mysql-test/main/union.test | 15 +++++++++++++++
sql/item_func.cc | 3 +++
3 files changed, 32 insertions(+)
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index 4e5f9312e03..39cd68ae851 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -2500,5 +2500,19 @@ t2 CREATE TABLE `t2` (
DROP TABLE t2;
DROP TABLE t1;
#
+# MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 &&
+# pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->
+# thread)' failed in _ma_state_info_write
+#
+CREATE TABLE t1 (c1 CHAR(8));
+INSERT INTO t1 VALUES ('10'),('-10');
+CREATE TABLE t2 (c2 CHAR);
+SET @a= CAST('10' AS CHAR);
+SELECT c1 FROM t1 UNION SELECT - @a FROM t2;
+c1
+10
+-10
+drop table t1,t2;
+#
# End of 10.3 tests
#
diff --git a/mysql-test/main/union.test b/mysql-test/main/union.test
index f86cae87524..b9b38271f83 100644
--- a/mysql-test/main/union.test
+++ b/mysql-test/main/union.test
@@ -1745,6 +1745,21 @@ SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
+--echo #
+--echo # MDEV-13232: Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 &&
+--echo # pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->
+--echo # thread)' failed in _ma_state_info_write
+--echo #
+
+CREATE TABLE t1 (c1 CHAR(8));
+INSERT INTO t1 VALUES ('10'),('-10');
+
+CREATE TABLE t2 (c2 CHAR);
+SET @a= CAST('10' AS CHAR);
+
+SELECT c1 FROM t1 UNION SELECT - @a FROM t2;
+
+drop table t1,t2;
--echo #
--echo # End of 10.3 tests
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e2740272385..ae6c61e83f4 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1935,6 +1935,9 @@ void Item_func_neg::fix_length_and_dec_double()
set_handler(&type_handler_double);
decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
max_length= args[0]->max_length + 1;
+ // Limit length with something reasonable
+ uint32 mlen= type_handler()->max_display_length(this);
+ set_if_smaller(max_length, mlen);
unsigned_flag= false;
}
1
0

[Commits] ce222a7: MDEV-15915 Add Feature_json status variable.
by holyfootï¼ askmonty.org 22 Apr '18
by holyfootï¼ askmonty.org 22 Apr '18
22 Apr '18
revision-id: ce222a71bf75b2125cc588371a3debb3e4a22d7f (mariadb-10.3.6-34-gce222a7)
parent(s): 9f84451d87ba1924539b7d2ab69619b71d0155b9
committer: Alexey Botchkov
timestamp: 2018-04-22 16:01:18 +0400
message:
MDEV-15915 Add Feature_json status variable.
---
mysql-test/main/status.test | 7 +++++++
sql/item_create.cc | 26 ++++++++++++++++++++++++++
sql/mysqld.cc | 1 +
sql/sql_class.h | 1 +
4 files changed, 35 insertions(+)
diff --git a/mysql-test/main/status.test b/mysql-test/main/status.test
index 92fba9a..221a24a 100644
--- a/mysql-test/main/status.test
+++ b/mysql-test/main/status.test
@@ -430,6 +430,13 @@ FLUSH STATUS;
SHOW STATUS LIKE 'Threads_running';
SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_STATUS WHERE VARIABLE_NAME='THREADS_RUNNING';
+--echo #
+--echo # MDEV-15915 Add Feature_json status variable.
+--echo #
+SHOW STATUS LIKE 'Feature_json';
+select json_valid('123');
+SHOW STATUS LIKE 'Feature_json';
+
# Restore global concurrent_insert value. Keep in the end of the test file.
--connection default
set @@global.concurrent_insert= @old_concurrent_insert;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 901dfa0..8b8476b 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -5118,6 +5118,7 @@ Create_func_json_exists Create_func_json_exists::s_singleton;
Item*
Create_func_json_exists::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_exists(thd, arg1, arg2);
}
@@ -5143,6 +5144,7 @@ Create_func_json_detailed::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_format(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5152,6 +5154,7 @@ Create_func_json_loose Create_func_json_loose::s_singleton;
Item*
Create_func_json_loose::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_format(thd, arg1,
Item_func_json_format::LOOSE);
}
@@ -5162,6 +5165,7 @@ Create_func_json_compact Create_func_json_compact::s_singleton;
Item*
Create_func_json_compact::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_format(thd, arg1,
Item_func_json_format::COMPACT);
}
@@ -5172,6 +5176,7 @@ Create_func_json_valid Create_func_json_valid::s_singleton;
Item*
Create_func_json_valid::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_valid(thd, arg1);
}
@@ -5181,6 +5186,7 @@ Create_func_json_type Create_func_json_type::s_singleton;
Item*
Create_func_json_type::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_type(thd, arg1);
}
@@ -5190,6 +5196,7 @@ Create_func_json_depth Create_func_json_depth::s_singleton;
Item*
Create_func_json_depth::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_depth(thd, arg1);
}
@@ -5199,6 +5206,7 @@ Create_func_json_value Create_func_json_value::s_singleton;
Item*
Create_func_json_value::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_value(thd, arg1, arg2);
}
@@ -5208,6 +5216,7 @@ Create_func_json_query Create_func_json_query::s_singleton;
Item*
Create_func_json_query::create_2_arg(THD *thd, Item *arg1, Item *arg2)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_query(thd, arg1, arg2);
}
@@ -5217,6 +5226,7 @@ Create_func_json_quote Create_func_json_quote::s_singleton;
Item*
Create_func_json_quote::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_quote(thd, arg1);
}
@@ -5226,6 +5236,7 @@ Create_func_json_unquote Create_func_json_unquote::s_singleton;
Item*
Create_func_json_unquote::create_1_arg(THD *thd, Item *arg1)
{
+ status_var_increment(current_thd->status_var.feature_json);
return new (thd->mem_root) Item_func_json_unquote(thd, arg1);
}
@@ -5256,6 +5267,7 @@ Create_func_json_array::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_array(thd);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5281,6 +5293,7 @@ Create_func_json_array_append::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_array_append(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5306,6 +5319,7 @@ Create_func_json_array_insert::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_array_insert(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5332,6 +5346,7 @@ Create_func_json_insert::create_native(THD *thd, LEX_CSTRING *name,
thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5358,6 +5373,7 @@ Create_func_json_set::create_native(THD *thd, LEX_CSTRING *name,
thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5384,6 +5400,7 @@ Create_func_json_replace::create_native(THD *thd, LEX_CSTRING *name,
thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5409,6 +5426,7 @@ Create_func_json_remove::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_remove(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5441,6 +5459,7 @@ Create_func_json_object::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_object(thd);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5465,6 +5484,7 @@ Create_func_json_length::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_length(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5489,6 +5509,7 @@ Create_func_json_merge::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_merge(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5514,6 +5535,7 @@ Create_func_json_contains::create_native(THD *thd, LEX_CSTRING *name,
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5539,6 +5561,7 @@ Create_func_json_keys::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_keys(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5564,6 +5587,7 @@ Create_func_json_contains_path::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_contains_path(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5589,6 +5613,7 @@ Create_func_json_extract::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_extract(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
@@ -5614,6 +5639,7 @@ Create_func_json_search::create_native(THD *thd, LEX_CSTRING *name,
func= new (thd->mem_root) Item_func_json_search(thd, *item_list);
}
+ status_var_increment(current_thd->status_var.feature_json);
return func;
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6e1a599..ae14c80 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -8553,6 +8553,7 @@ SHOW_VAR status_vars[]= {
{"Feature_fulltext", (char*) offsetof(STATUS_VAR, feature_fulltext), SHOW_LONG_STATUS},
{"Feature_gis", (char*) offsetof(STATUS_VAR, feature_gis), SHOW_LONG_STATUS},
{"Feature_invisible_columns", (char*) offsetof(STATUS_VAR, feature_invisible_columns), SHOW_LONG_STATUS},
+ {"Feature_json", (char*) offsetof(STATUS_VAR, feature_json), SHOW_LONG_STATUS},
{"Feature_locale", (char*) offsetof(STATUS_VAR, feature_locale), SHOW_LONG_STATUS},
{"Feature_subquery", (char*) offsetof(STATUS_VAR, feature_subquery), SHOW_LONG_STATUS},
{"Feature_timezone", (char*) offsetof(STATUS_VAR, feature_timezone), SHOW_LONG_STATUS},
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a7c33cb..56d63f3 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -820,6 +820,7 @@ typedef struct system_status_var
ulong feature_fulltext; /* +1 when MATCH is used */
ulong feature_gis; /* +1 opening a table with GIS features */
ulong feature_invisible_columns; /* +1 opening a table with invisible column */
+ ulong feature_json; /* +1 when JSON function appears in the statement */
ulong feature_locale; /* +1 when LOCALE is set */
ulong feature_subquery; /* +1 when subqueries are used */
ulong feature_timezone; /* +1 when XPATH is used */
1
0

22 Apr '18
revision-id: 65169418c5128fb8398ac356d93262ae9549a98c (mariadb-10.3.6-29-g6516941)
parent(s): c058117c6c857ecb41960bd705104adc42348645
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-04-21 17:20:20 -0700
message:
MDEV-15940 Crash when using CURSOR with VALUES()
The function st_select_lex_unit::get_column_types() should
take into account that a unit may contain only a table
value constructor and nothing more.
---
mysql-test/main/table_value_constr.result | 21 +++++++++++++++++++++
mysql-test/main/table_value_constr.test | 24 ++++++++++++++++++++++++
sql/sql_union.cc | 2 +-
3 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/mysql-test/main/table_value_constr.result b/mysql-test/main/table_value_constr.result
index 39caba3..5a904cb 100644
--- a/mysql-test/main/table_value_constr.result
+++ b/mysql-test/main/table_value_constr.result
@@ -2071,3 +2071,24 @@ ERROR HY000: Field reference 'b' can't be used in table value constructor
select * from (values (1), (t1.b), (2)) as new_tvc;
ERROR HY000: Field reference 't1.b' can't be used in table value constructor
drop table t1;
+#
+# MDEV-MDEV-15940: cursor over TVC
+#
+BEGIN NOT ATOMIC
+DECLARE v INT;
+DECLARE cur CURSOR FOR VALUES(7);
+OPEN cur;
+FETCH cur INTO v;
+SELECT v;
+END;
+|
+v
+7
+BEGIN NOT ATOMIC
+DECLARE v INT DEFAULT 0;
+FOR a IN (VALUES (7)) DO SET v = v + 1; END FOR;
+SELECT v;
+END;
+|
+v
+1
diff --git a/mysql-test/main/table_value_constr.test b/mysql-test/main/table_value_constr.test
index 578f894..84f196b 100644
--- a/mysql-test/main/table_value_constr.test
+++ b/mysql-test/main/table_value_constr.test
@@ -1044,3 +1044,27 @@ select * from (values (1), (b), (2)) as new_tvc;
select * from (values (1), (t1.b), (2)) as new_tvc;
drop table t1;
+
+--echo #
+--echo # MDEV-MDEV-15940: cursor over TVC
+--echo #
+
+DELIMITER |;
+
+BEGIN NOT ATOMIC
+ DECLARE v INT;
+ DECLARE cur CURSOR FOR VALUES(7);
+ OPEN cur;
+ FETCH cur INTO v;
+ SELECT v;
+END;
+|
+
+BEGIN NOT ATOMIC
+DECLARE v INT DEFAULT 0;
+FOR a IN (VALUES (7)) DO SET v = v + 1; END FOR;
+SELECT v;
+END;
+|
+
+DELIMITER ;|
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 4cc7de8..432ad85 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -1874,7 +1874,7 @@ bool st_select_lex_unit::change_result(select_result_interceptor *new_result,
List<Item> *st_select_lex_unit::get_column_types(bool for_cursor)
{
SELECT_LEX *sl= first_select();
- bool is_procedure= MY_TEST(sl->join->procedure);
+ bool is_procedure= !sl->tvc && sl->join->procedure ;
if (is_procedure)
{
1
0

[Commits] 4d22371: MDEV-15035 Wrong results when calling a stored procedure
by IgorBabaev 21 Apr '18
by IgorBabaev 21 Apr '18
21 Apr '18
revision-id: 4d223712c3f49e9b9f5dfb9d65b72bbd19132ad3 (mariadb-5.5.59-59-g4d22371)
parent(s): 5e61e1716e763315009318081fba5994b8910242
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-04-20 23:11:11 -0700
message:
MDEV-15035 Wrong results when calling a stored procedure
multiple times with different arguments.
If the ON expression of an outer join is an OR formula with one
of the disjunct being a constant formula then the expression
cannot be null-rejected if the constant formula is true. Otherwise
it can be null-rejected and if so the outer join can be converted
into inner join. This optimization was added in the patch for
mdev-4817. Yet the code had a defect: if the query was used in
a stored procedure with parameters and the constant item contained
some of them then the value of this constant item depended on the
values of the parameters. With some parameters it may be true,
for others not. The validity of conversion to inner join is checked
only once and it happens only for the first call of procedure.
So if the parameters in the first call allowed the conversion it
was done and next calls used the transformed query though there
could be calls whose parameters made the conversion invalid.
Fixed by cheking whether the constant disjunct in the ON expression
originally contained an SP parameter. If so the expression is not
considered as null-rejected. For this check a new item's attribute
was intruduced: Item::with_param. It is calculated for each item
by fix fields() functions.
---
mysql-test/r/sp-innodb.result | 34 ++++++++++++++++++++++++++++++++++
mysql-test/t/sp-innodb.test | 42 ++++++++++++++++++++++++++++++++++++++++++
sql/item.cc | 7 +++++++
sql/item.h | 1 +
sql/item_cmpfunc.cc | 12 +++++++++---
sql/item_func.cc | 1 +
sql/item_func.h | 7 +++++++
sql/item_row.cc | 1 +
sql/item_sum.cc | 3 +++
9 files changed, 105 insertions(+), 3 deletions(-)
diff --git a/mysql-test/r/sp-innodb.result b/mysql-test/r/sp-innodb.result
index b5fe920..9daf2c4 100644
--- a/mysql-test/r/sp-innodb.result
+++ b/mysql-test/r/sp-innodb.result
@@ -138,3 +138,37 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
#
# BUG 16041903: End of test case
#
+#
+# MDEV-15035: SP using query with outer join and a parameter
+# in ON expression
+#
+CREATE TABLE t1 (
+id int NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1), (2);
+CREATE TABLE t2 (
+id int NOT NULL,
+id_foo int NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1, 1);
+DROP PROCEDURE IF EXISTS test_proc;
+CREATE PROCEDURE test_proc(IN param int)
+LANGUAGE SQL
+READS SQL DATA
+BEGIN
+SELECT DISTINCT f.id
+FROM t1 f
+LEFT OUTER JOIN t2 b ON b.id_foo = f.id
+WHERE (param <> 0 OR b.id IS NOT NULL);
+END|
+CALL test_proc(0);
+id
+1
+CALL test_proc(1);
+id
+1
+2
+DROP PROCEDURE IF EXISTS test_proc;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/sp-innodb.test b/mysql-test/t/sp-innodb.test
index 2371516..e44a853 100644
--- a/mysql-test/t/sp-innodb.test
+++ b/mysql-test/t/sp-innodb.test
@@ -158,5 +158,47 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
--echo # BUG 16041903: End of test case
--echo #
+--echo #
+--echo # MDEV-15035: SP using query with outer join and a parameter
+--echo # in ON expression
+--echo #
+
+CREATE TABLE t1 (
+ id int NOT NULL,
+ PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (1), (2);
+
+CREATE TABLE t2 (
+ id int NOT NULL,
+ id_foo int NOT NULL,
+ PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES (1, 1);
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS test_proc;
+--enable_warnings
+
+DELIMITER |;
+CREATE PROCEDURE test_proc(IN param int)
+LANGUAGE SQL
+READS SQL DATA
+BEGIN
+ SELECT DISTINCT f.id
+ FROM t1 f
+ LEFT OUTER JOIN t2 b ON b.id_foo = f.id
+ WHERE (param <> 0 OR b.id IS NOT NULL);
+END|
+DELIMITER ;|
+
+CALL test_proc(0);
+CALL test_proc(1);
+
+DROP PROCEDURE IF EXISTS test_proc;
+DROP TABLE t1, t2;
+
# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
diff --git a/sql/item.cc b/sql/item.cc
index 08a0061..c5c6df0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -504,6 +504,7 @@ Item::Item():
in_rollup= 0;
decimals= 0; max_length= 0;
with_subselect= 0;
+ with_param= 0;
cmp_context= IMPOSSIBLE_RESULT;
/* Initially this item is not attached to any JOIN_TAB. */
join_tab_idx= MAX_TABLES;
@@ -550,6 +551,7 @@ Item::Item(THD *thd, Item *item):
null_value(item->null_value),
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
+ with_param(item->with_param),
with_field(item->with_field),
fixed(item->fixed),
is_autogenerated_name(item->is_autogenerated_name),
@@ -1486,6 +1488,9 @@ bool Item_sp_variable::fix_fields(THD *thd, Item **)
max_length= it->max_length;
decimals= it->decimals;
unsigned_flag= it->unsigned_flag;
+ with_param= 1;
+ if (thd->lex->current_select->master_unit()->item)
+ thd->lex->current_select->master_unit()->item->with_param= 1;
fixed= 1;
collation.set(it->collation.collation, it->collation.derivation);
@@ -7234,6 +7239,7 @@ void Item_ref::set_properties()
split_sum_func() doesn't try to change the reference.
*/
with_sum_func= (*ref)->with_sum_func;
+ with_param= (*ref)->with_param;
with_field= (*ref)->with_field;
unsigned_flag= (*ref)->unsigned_flag;
fixed= 1;
@@ -7681,6 +7687,7 @@ Item_cache_wrapper::Item_cache_wrapper(Item *item_arg)
decimals= orig_item->decimals;
collation.set(orig_item->collation);
with_sum_func= orig_item->with_sum_func;
+ with_param= orig_item->with_param;
with_field= orig_item->with_field;
unsigned_flag= orig_item->unsigned_flag;
name= item_arg->name;
diff --git a/sql/item.h b/sql/item.h
index 830f8bf..d756cf8 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -644,6 +644,7 @@ class Item {
bool null_value; /* if item is null */
bool unsigned_flag;
bool with_sum_func; /* True if item contains a sum func */
+ bool with_param; /* True if contains an SP parameter */
/**
True if any item except Item_sum_func contains a field. Set during parsing.
*/
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 39f497e..db811a7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1546,6 +1546,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
}
eval_not_null_tables(NULL);
with_sum_func= args[0]->with_sum_func;
+ with_param= args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field;
if ((const_item_cache= args[0]->const_item()))
{
@@ -1587,6 +1588,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
with_subselect= 1;
with_sum_func= with_sum_func || args[1]->with_sum_func;
with_field= with_field || args[1]->with_field;
+ with_param= args[0]->with_param || args[1]->with_param;
used_tables_cache|= args[1]->used_tables();
const_item_cache&= args[1]->const_item();
fixed= 1;
@@ -2108,6 +2110,7 @@ void Item_func_interval::fix_length_and_dec()
used_tables_cache|= row->used_tables();
not_null_tables_cache= row->not_null_tables();
with_sum_func= with_sum_func || row->with_sum_func;
+ with_param= with_param || row->with_param;
with_field= with_field || row->with_field;
const_item_cache&= row->const_item();
}
@@ -4427,6 +4430,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
}
with_sum_func= with_sum_func || item->with_sum_func;
+ with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
with_subselect|= item->has_subquery();
if (item->maybe_null)
@@ -4449,14 +4453,15 @@ Item_cond::eval_not_null_tables(uchar *opt_arg)
while ((item=li++))
{
table_map tmp_table_map;
- if (item->const_item())
+ if (item->const_item() && !item->with_param)
{
if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
item->val_int() == 0)
{
/*
- This is "... OR false_cond OR ..."
- In this case, false_cond has no effect on cond_or->not_null_tables()
+ This is "... OR false_cond/null_cond OR ..."
+ In this case, false_cond/null_cond has no effect on
+ cond_or->not_null_tables()
*/
}
else
@@ -5118,6 +5123,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref)
args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1))
return TRUE; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
+ with_param=args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field || args[1]->with_field;
with_subselect= args[0]->has_subquery() || args[1]->has_subquery();
max_length= 1;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 9e4edfc..8b3c72dd3 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -222,6 +222,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
maybe_null=1;
with_sum_func= with_sum_func || item->with_sum_func;
+ with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
used_tables_cache|= item->used_tables();
const_item_cache&= item->const_item();
diff --git a/sql/item_func.h b/sql/item_func.h
index 5781822..3a609fc 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -83,6 +83,7 @@ class Item_func :public Item_result_field
args= tmp_arg;
args[0]= a;
with_sum_func= a->with_sum_func;
+ with_param= a->with_param;
with_field= a->with_field;
}
Item_func(Item *a,Item *b):
@@ -91,6 +92,7 @@ class Item_func :public Item_result_field
args= tmp_arg;
args[0]= a; args[1]= b;
with_sum_func= a->with_sum_func || b->with_sum_func;
+ with_param= a->with_param || b->with_param;
with_field= a->with_field || b->with_field;
}
Item_func(Item *a,Item *b,Item *c):
@@ -102,6 +104,7 @@ class Item_func :public Item_result_field
arg_count= 3;
args[0]= a; args[1]= b; args[2]= c;
with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
+ with_param= a->with_param || b->with_param || c->with_param;
with_field= a->with_field || b->with_field || c->with_field;
}
}
@@ -115,6 +118,8 @@ class Item_func :public Item_result_field
args[0]= a; args[1]= b; args[2]= c; args[3]= d;
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func;
+ with_param= a->with_param || b->with_param ||
+ c->with_param || d->with_param;
with_field= a->with_field || b->with_field ||
c->with_field || d->with_field;
}
@@ -128,6 +133,8 @@ class Item_func :public Item_result_field
args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func || e->with_sum_func ;
+ with_param= a->with_param || b->with_param ||
+ c->with_param || d->with_param || e->with_param;
with_field= a->with_field || b->with_field ||
c->with_field || d->with_field || e->with_field;
}
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 9e81c05..9fe34dd 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -125,6 +125,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
with_sum_func= with_sum_func || item->with_sum_func;
with_field= with_field || item->with_field;
with_subselect|= item->with_subselect;
+ with_param|= item->with_param;
}
fixed= 1;
return FALSE;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 709c2b6..16334cd 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1164,6 +1164,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
return TRUE;
set_if_bigger(decimals, args[i]->decimals);
with_subselect|= args[i]->with_subselect;
+ with_param|= args[i]->with_param;
}
result_field=0;
max_length=float_length(decimals);
@@ -1195,6 +1196,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
return TRUE;
decimals=item->decimals;
with_subselect= args[0]->with_subselect;
+ with_param= args[0]->with_param;
switch (hybrid_type= item->result_type()) {
case INT_RESULT:
@@ -3430,6 +3432,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
args[i]->check_cols(1))
return TRUE;
with_subselect|= args[i]->with_subselect;
+ with_param|= args[i]->with_param;
}
/* skip charset aggregation for order columns */
1
0

[Commits] fcebc77: MDEV-15035 Wrong results when calling a stored procedure
by IgorBabaev 21 Apr '18
by IgorBabaev 21 Apr '18
21 Apr '18
revision-id: fcebc778dbf865c8dab5f0f0800e4eab5018d76f (mariadb-5.5.59-59-gfcebc77)
parent(s): 5e61e1716e763315009318081fba5994b8910242
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-04-20 23:03:40 -0700
message:
MDEV-15035 Wrong results when calling a stored procedure
multiple times with different arguments.
If the ON expression of an outer join is an OR formula with one
of the disjunct being a constant formula then the expression
cannot be null-rejected if the constant formula is true. Otherwise
it can be null-rejected and if so the outer join can be converted
into inner join. This optimization was added in the patch for
mdev-4817. Yet the code had a defect: if the query was used in
a stored procedure with parameters and the constant item contained
some of them then the value of this constant item depended on the
values of the parameters. With some parameters it may be true,
for others not. The validity of conversion to inner join is checked
only once and it happens only for the first call of procedure.
So if the parameters in the first call allowed the conversion it
was done and next calls used the transformed query though there
could be calls whose parameters made the conversion invalid.
Fixed by cheking whether the constant disjunct in the ON expression
originally contained an SP parameter. If so the expression is not
considered as null-rejected. For this check a new item's attribute
was intruduced: Item::with_param. It is calculated for each item
by fix fields() functions.
---
mysql-test/r/sp-innodb.result | 34 ++++++++++++++++++++++++++++++++++
mysql-test/t/sp-innodb.test | 42 ++++++++++++++++++++++++++++++++++++++++++
sql/item.cc | 7 +++++++
sql/item.h | 1 +
sql/item_cmpfunc.cc | 12 +++++++++---
sql/item_func.cc | 1 +
sql/item_func.h | 7 +++++++
sql/item_sum.cc | 3 +++
8 files changed, 104 insertions(+), 3 deletions(-)
diff --git a/mysql-test/r/sp-innodb.result b/mysql-test/r/sp-innodb.result
index b5fe920..9daf2c4 100644
--- a/mysql-test/r/sp-innodb.result
+++ b/mysql-test/r/sp-innodb.result
@@ -138,3 +138,37 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
#
# BUG 16041903: End of test case
#
+#
+# MDEV-15035: SP using query with outer join and a parameter
+# in ON expression
+#
+CREATE TABLE t1 (
+id int NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1), (2);
+CREATE TABLE t2 (
+id int NOT NULL,
+id_foo int NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1, 1);
+DROP PROCEDURE IF EXISTS test_proc;
+CREATE PROCEDURE test_proc(IN param int)
+LANGUAGE SQL
+READS SQL DATA
+BEGIN
+SELECT DISTINCT f.id
+FROM t1 f
+LEFT OUTER JOIN t2 b ON b.id_foo = f.id
+WHERE (param <> 0 OR b.id IS NOT NULL);
+END|
+CALL test_proc(0);
+id
+1
+CALL test_proc(1);
+id
+1
+2
+DROP PROCEDURE IF EXISTS test_proc;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/sp-innodb.test b/mysql-test/t/sp-innodb.test
index 2371516..e44a853 100644
--- a/mysql-test/t/sp-innodb.test
+++ b/mysql-test/t/sp-innodb.test
@@ -158,5 +158,47 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
--echo # BUG 16041903: End of test case
--echo #
+--echo #
+--echo # MDEV-15035: SP using query with outer join and a parameter
+--echo # in ON expression
+--echo #
+
+CREATE TABLE t1 (
+ id int NOT NULL,
+ PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (1), (2);
+
+CREATE TABLE t2 (
+ id int NOT NULL,
+ id_foo int NOT NULL,
+ PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES (1, 1);
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS test_proc;
+--enable_warnings
+
+DELIMITER |;
+CREATE PROCEDURE test_proc(IN param int)
+LANGUAGE SQL
+READS SQL DATA
+BEGIN
+ SELECT DISTINCT f.id
+ FROM t1 f
+ LEFT OUTER JOIN t2 b ON b.id_foo = f.id
+ WHERE (param <> 0 OR b.id IS NOT NULL);
+END|
+DELIMITER ;|
+
+CALL test_proc(0);
+CALL test_proc(1);
+
+DROP PROCEDURE IF EXISTS test_proc;
+DROP TABLE t1, t2;
+
# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
diff --git a/sql/item.cc b/sql/item.cc
index 08a0061..c5c6df0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -504,6 +504,7 @@ Item::Item():
in_rollup= 0;
decimals= 0; max_length= 0;
with_subselect= 0;
+ with_param= 0;
cmp_context= IMPOSSIBLE_RESULT;
/* Initially this item is not attached to any JOIN_TAB. */
join_tab_idx= MAX_TABLES;
@@ -550,6 +551,7 @@ Item::Item(THD *thd, Item *item):
null_value(item->null_value),
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
+ with_param(item->with_param),
with_field(item->with_field),
fixed(item->fixed),
is_autogenerated_name(item->is_autogenerated_name),
@@ -1486,6 +1488,9 @@ bool Item_sp_variable::fix_fields(THD *thd, Item **)
max_length= it->max_length;
decimals= it->decimals;
unsigned_flag= it->unsigned_flag;
+ with_param= 1;
+ if (thd->lex->current_select->master_unit()->item)
+ thd->lex->current_select->master_unit()->item->with_param= 1;
fixed= 1;
collation.set(it->collation.collation, it->collation.derivation);
@@ -7234,6 +7239,7 @@ void Item_ref::set_properties()
split_sum_func() doesn't try to change the reference.
*/
with_sum_func= (*ref)->with_sum_func;
+ with_param= (*ref)->with_param;
with_field= (*ref)->with_field;
unsigned_flag= (*ref)->unsigned_flag;
fixed= 1;
@@ -7681,6 +7687,7 @@ Item_cache_wrapper::Item_cache_wrapper(Item *item_arg)
decimals= orig_item->decimals;
collation.set(orig_item->collation);
with_sum_func= orig_item->with_sum_func;
+ with_param= orig_item->with_param;
with_field= orig_item->with_field;
unsigned_flag= orig_item->unsigned_flag;
name= item_arg->name;
diff --git a/sql/item.h b/sql/item.h
index 830f8bf..d756cf8 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -644,6 +644,7 @@ class Item {
bool null_value; /* if item is null */
bool unsigned_flag;
bool with_sum_func; /* True if item contains a sum func */
+ bool with_param; /* True if contains an SP parameter */
/**
True if any item except Item_sum_func contains a field. Set during parsing.
*/
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 39f497e..db811a7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1546,6 +1546,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
}
eval_not_null_tables(NULL);
with_sum_func= args[0]->with_sum_func;
+ with_param= args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field;
if ((const_item_cache= args[0]->const_item()))
{
@@ -1587,6 +1588,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
with_subselect= 1;
with_sum_func= with_sum_func || args[1]->with_sum_func;
with_field= with_field || args[1]->with_field;
+ with_param= args[0]->with_param || args[1]->with_param;
used_tables_cache|= args[1]->used_tables();
const_item_cache&= args[1]->const_item();
fixed= 1;
@@ -2108,6 +2110,7 @@ void Item_func_interval::fix_length_and_dec()
used_tables_cache|= row->used_tables();
not_null_tables_cache= row->not_null_tables();
with_sum_func= with_sum_func || row->with_sum_func;
+ with_param= with_param || row->with_param;
with_field= with_field || row->with_field;
const_item_cache&= row->const_item();
}
@@ -4427,6 +4430,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
}
with_sum_func= with_sum_func || item->with_sum_func;
+ with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
with_subselect|= item->has_subquery();
if (item->maybe_null)
@@ -4449,14 +4453,15 @@ Item_cond::eval_not_null_tables(uchar *opt_arg)
while ((item=li++))
{
table_map tmp_table_map;
- if (item->const_item())
+ if (item->const_item() && !item->with_param)
{
if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
item->val_int() == 0)
{
/*
- This is "... OR false_cond OR ..."
- In this case, false_cond has no effect on cond_or->not_null_tables()
+ This is "... OR false_cond/null_cond OR ..."
+ In this case, false_cond/null_cond has no effect on
+ cond_or->not_null_tables()
*/
}
else
@@ -5118,6 +5123,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref)
args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1))
return TRUE; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
+ with_param=args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field || args[1]->with_field;
with_subselect= args[0]->has_subquery() || args[1]->has_subquery();
max_length= 1;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 9e4edfc..8b3c72dd3 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -222,6 +222,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
maybe_null=1;
with_sum_func= with_sum_func || item->with_sum_func;
+ with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
used_tables_cache|= item->used_tables();
const_item_cache&= item->const_item();
diff --git a/sql/item_func.h b/sql/item_func.h
index 5781822..3a609fc 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -83,6 +83,7 @@ class Item_func :public Item_result_field
args= tmp_arg;
args[0]= a;
with_sum_func= a->with_sum_func;
+ with_param= a->with_param;
with_field= a->with_field;
}
Item_func(Item *a,Item *b):
@@ -91,6 +92,7 @@ class Item_func :public Item_result_field
args= tmp_arg;
args[0]= a; args[1]= b;
with_sum_func= a->with_sum_func || b->with_sum_func;
+ with_param= a->with_param || b->with_param;
with_field= a->with_field || b->with_field;
}
Item_func(Item *a,Item *b,Item *c):
@@ -102,6 +104,7 @@ class Item_func :public Item_result_field
arg_count= 3;
args[0]= a; args[1]= b; args[2]= c;
with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
+ with_param= a->with_param || b->with_param || c->with_param;
with_field= a->with_field || b->with_field || c->with_field;
}
}
@@ -115,6 +118,8 @@ class Item_func :public Item_result_field
args[0]= a; args[1]= b; args[2]= c; args[3]= d;
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func;
+ with_param= a->with_param || b->with_param ||
+ c->with_param || d->with_param;
with_field= a->with_field || b->with_field ||
c->with_field || d->with_field;
}
@@ -128,6 +133,8 @@ class Item_func :public Item_result_field
args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func || e->with_sum_func ;
+ with_param= a->with_param || b->with_param ||
+ c->with_param || d->with_param || e->with_param;
with_field= a->with_field || b->with_field ||
c->with_field || d->with_field || e->with_field;
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 709c2b6..16334cd 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1164,6 +1164,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
return TRUE;
set_if_bigger(decimals, args[i]->decimals);
with_subselect|= args[i]->with_subselect;
+ with_param|= args[i]->with_param;
}
result_field=0;
max_length=float_length(decimals);
@@ -1195,6 +1196,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
return TRUE;
decimals=item->decimals;
with_subselect= args[0]->with_subselect;
+ with_param= args[0]->with_param;
switch (hybrid_type= item->result_type()) {
case INT_RESULT:
@@ -3430,6 +3432,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
args[i]->check_cols(1))
return TRUE;
with_subselect|= args[i]->with_subselect;
+ with_param|= args[i]->with_param;
}
/* skip charset aggregation for order columns */
1
0

[Commits] e86fbf3: MDEV-15035 Wrong results when calling a stored procedure
by IgorBabaev 21 Apr '18
by IgorBabaev 21 Apr '18
21 Apr '18
revision-id: e86fbf3d9c679d19ab824e150fe2ccdea89e0021 (mariadb-5.5.59-59-ge86fbf3)
parent(s): 5e61e1716e763315009318081fba5994b8910242
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-04-20 22:57:06 -0700
message:
MDEV-15035 Wrong results when calling a stored procedure
multiple times with different arguments.
If the ON expression of an outer join is an OR formula with one
of the disjunct being a constant formula then the expression
cannot be null-rejected if the constant formula is true. Otherwise
it can be null-rejected and if so the outer join can be converted
into inner join. This optimization was added in the patch for
mdev-4817. Yet the code had a defect: if the query was used in
a stored procedure with parameters and the constant item contained
some of them then the value of this constant item depended on the
values of the parameters. With some parameters it may be true,
for others not. The validity of conversion to inner join is checked
only once and it happens only for the first call of procedure.
So if the parameters in the first call allowed the conversion it
was done and next calls used the transformed query though there
could be calls whose parameters made the conversion invalid.
Fixed by cheking whether the constant disjunct in the ON expression
originally contained an SP parameter. If so the expression is not
considered as null-rejected. For this check a new item's attribute
was intruduced: Item::with_param. It is calculated for each item
by fix fields() functions.
---
mysql-test/r/sp-innodb.result | 34 ++++++++++++++++++++++++++++++++++
mysql-test/t/sp-innodb.test | 42 ++++++++++++++++++++++++++++++++++++++++++
sql/item.cc | 7 +++++++
sql/item.h | 1 +
sql/item_cmpfunc.cc | 12 +++++++++---
sql/item_func.cc | 1 +
sql/item_func.h | 7 +++++++
sql/item_sum.cc | 3 +++
8 files changed, 104 insertions(+), 3 deletions(-)
diff --git a/mysql-test/r/sp-innodb.result b/mysql-test/r/sp-innodb.result
index b5fe920..2ca0a04 100644
--- a/mysql-test/r/sp-innodb.result
+++ b/mysql-test/r/sp-innodb.result
@@ -138,3 +138,37 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
#
# BUG 16041903: End of test case
#
+#
+# MDEV-15035: SP using query with outer join and a parameter
+# in WHERE clause
+#
+CREATE TABLE t1 (
+id int NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (1), (2);
+CREATE TABLE t2 (
+id int NOT NULL,
+id_foo int NOT NULL,
+PRIMARY KEY (id)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1, 1);
+DROP PROCEDURE IF EXISTS test_proc;
+CREATE PROCEDURE test_proc(IN param int)
+LANGUAGE SQL
+READS SQL DATA
+BEGIN
+SELECT DISTINCT f.id
+FROM t1 f
+LEFT OUTER JOIN t2 b ON b.id_foo = f.id
+WHERE (param <> 0 OR b.id IS NOT NULL);
+END|
+CALL test_proc(0);
+id
+1
+CALL test_proc(1);
+id
+1
+2
+DROP PROCEDURE IF EXISTS test_proc;
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/sp-innodb.test b/mysql-test/t/sp-innodb.test
index 2371516..7a2929e 100644
--- a/mysql-test/t/sp-innodb.test
+++ b/mysql-test/t/sp-innodb.test
@@ -158,5 +158,47 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
--echo # BUG 16041903: End of test case
--echo #
+--echo #
+--echo # MDEV-15035: SP using query with outer join and a parameter
+--echo # in WHERE clause
+--echo #
+
+CREATE TABLE t1 (
+ id int NOT NULL,
+ PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t1 VALUES (1), (2);
+
+CREATE TABLE t2 (
+ id int NOT NULL,
+ id_foo int NOT NULL,
+ PRIMARY KEY (id)
+) ENGINE=InnoDB;
+
+INSERT INTO t2 VALUES (1, 1);
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS test_proc;
+--enable_warnings
+
+DELIMITER |;
+CREATE PROCEDURE test_proc(IN param int)
+LANGUAGE SQL
+READS SQL DATA
+BEGIN
+ SELECT DISTINCT f.id
+ FROM t1 f
+ LEFT OUTER JOIN t2 b ON b.id_foo = f.id
+ WHERE (param <> 0 OR b.id IS NOT NULL);
+END|
+DELIMITER ;|
+
+CALL test_proc(0);
+CALL test_proc(1);
+
+DROP PROCEDURE IF EXISTS test_proc;
+DROP TABLE t1, t2;
+
# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
diff --git a/sql/item.cc b/sql/item.cc
index 08a0061..c5c6df0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -504,6 +504,7 @@ Item::Item():
in_rollup= 0;
decimals= 0; max_length= 0;
with_subselect= 0;
+ with_param= 0;
cmp_context= IMPOSSIBLE_RESULT;
/* Initially this item is not attached to any JOIN_TAB. */
join_tab_idx= MAX_TABLES;
@@ -550,6 +551,7 @@ Item::Item(THD *thd, Item *item):
null_value(item->null_value),
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
+ with_param(item->with_param),
with_field(item->with_field),
fixed(item->fixed),
is_autogenerated_name(item->is_autogenerated_name),
@@ -1486,6 +1488,9 @@ bool Item_sp_variable::fix_fields(THD *thd, Item **)
max_length= it->max_length;
decimals= it->decimals;
unsigned_flag= it->unsigned_flag;
+ with_param= 1;
+ if (thd->lex->current_select->master_unit()->item)
+ thd->lex->current_select->master_unit()->item->with_param= 1;
fixed= 1;
collation.set(it->collation.collation, it->collation.derivation);
@@ -7234,6 +7239,7 @@ void Item_ref::set_properties()
split_sum_func() doesn't try to change the reference.
*/
with_sum_func= (*ref)->with_sum_func;
+ with_param= (*ref)->with_param;
with_field= (*ref)->with_field;
unsigned_flag= (*ref)->unsigned_flag;
fixed= 1;
@@ -7681,6 +7687,7 @@ Item_cache_wrapper::Item_cache_wrapper(Item *item_arg)
decimals= orig_item->decimals;
collation.set(orig_item->collation);
with_sum_func= orig_item->with_sum_func;
+ with_param= orig_item->with_param;
with_field= orig_item->with_field;
unsigned_flag= orig_item->unsigned_flag;
name= item_arg->name;
diff --git a/sql/item.h b/sql/item.h
index 830f8bf..d756cf8 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -644,6 +644,7 @@ class Item {
bool null_value; /* if item is null */
bool unsigned_flag;
bool with_sum_func; /* True if item contains a sum func */
+ bool with_param; /* True if contains an SP parameter */
/**
True if any item except Item_sum_func contains a field. Set during parsing.
*/
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 39f497e..db811a7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1546,6 +1546,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
}
eval_not_null_tables(NULL);
with_sum_func= args[0]->with_sum_func;
+ with_param= args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field;
if ((const_item_cache= args[0]->const_item()))
{
@@ -1587,6 +1588,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
with_subselect= 1;
with_sum_func= with_sum_func || args[1]->with_sum_func;
with_field= with_field || args[1]->with_field;
+ with_param= args[0]->with_param || args[1]->with_param;
used_tables_cache|= args[1]->used_tables();
const_item_cache&= args[1]->const_item();
fixed= 1;
@@ -2108,6 +2110,7 @@ void Item_func_interval::fix_length_and_dec()
used_tables_cache|= row->used_tables();
not_null_tables_cache= row->not_null_tables();
with_sum_func= with_sum_func || row->with_sum_func;
+ with_param= with_param || row->with_param;
with_field= with_field || row->with_field;
const_item_cache&= row->const_item();
}
@@ -4427,6 +4430,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
}
with_sum_func= with_sum_func || item->with_sum_func;
+ with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
with_subselect|= item->has_subquery();
if (item->maybe_null)
@@ -4449,14 +4453,15 @@ Item_cond::eval_not_null_tables(uchar *opt_arg)
while ((item=li++))
{
table_map tmp_table_map;
- if (item->const_item())
+ if (item->const_item() && !item->with_param)
{
if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
item->val_int() == 0)
{
/*
- This is "... OR false_cond OR ..."
- In this case, false_cond has no effect on cond_or->not_null_tables()
+ This is "... OR false_cond/null_cond OR ..."
+ In this case, false_cond/null_cond has no effect on
+ cond_or->not_null_tables()
*/
}
else
@@ -5118,6 +5123,7 @@ Item_func_regex::fix_fields(THD *thd, Item **ref)
args[1]->fix_fields(thd, args + 1)) || args[1]->check_cols(1))
return TRUE; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
+ with_param=args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field || args[1]->with_field;
with_subselect= args[0]->has_subquery() || args[1]->has_subquery();
max_length= 1;
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 9e4edfc..8b3c72dd3 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -222,6 +222,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
maybe_null=1;
with_sum_func= with_sum_func || item->with_sum_func;
+ with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
used_tables_cache|= item->used_tables();
const_item_cache&= item->const_item();
diff --git a/sql/item_func.h b/sql/item_func.h
index 5781822..3a609fc 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -83,6 +83,7 @@ class Item_func :public Item_result_field
args= tmp_arg;
args[0]= a;
with_sum_func= a->with_sum_func;
+ with_param= a->with_param;
with_field= a->with_field;
}
Item_func(Item *a,Item *b):
@@ -91,6 +92,7 @@ class Item_func :public Item_result_field
args= tmp_arg;
args[0]= a; args[1]= b;
with_sum_func= a->with_sum_func || b->with_sum_func;
+ with_param= a->with_param || b->with_param;
with_field= a->with_field || b->with_field;
}
Item_func(Item *a,Item *b,Item *c):
@@ -102,6 +104,7 @@ class Item_func :public Item_result_field
arg_count= 3;
args[0]= a; args[1]= b; args[2]= c;
with_sum_func= a->with_sum_func || b->with_sum_func || c->with_sum_func;
+ with_param= a->with_param || b->with_param || c->with_param;
with_field= a->with_field || b->with_field || c->with_field;
}
}
@@ -115,6 +118,8 @@ class Item_func :public Item_result_field
args[0]= a; args[1]= b; args[2]= c; args[3]= d;
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func;
+ with_param= a->with_param || b->with_param ||
+ c->with_param || d->with_param;
with_field= a->with_field || b->with_field ||
c->with_field || d->with_field;
}
@@ -128,6 +133,8 @@ class Item_func :public Item_result_field
args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
with_sum_func= a->with_sum_func || b->with_sum_func ||
c->with_sum_func || d->with_sum_func || e->with_sum_func ;
+ with_param= a->with_param || b->with_param ||
+ c->with_param || d->with_param || e->with_param;
with_field= a->with_field || b->with_field ||
c->with_field || d->with_field || e->with_field;
}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 709c2b6..16334cd 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -1164,6 +1164,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
return TRUE;
set_if_bigger(decimals, args[i]->decimals);
with_subselect|= args[i]->with_subselect;
+ with_param|= args[i]->with_param;
}
result_field=0;
max_length=float_length(decimals);
@@ -1195,6 +1196,7 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
return TRUE;
decimals=item->decimals;
with_subselect= args[0]->with_subselect;
+ with_param= args[0]->with_param;
switch (hybrid_type= item->result_type()) {
case INT_RESULT:
@@ -3430,6 +3432,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
args[i]->check_cols(1))
return TRUE;
with_subselect|= args[i]->with_subselect;
+ with_param|= args[i]->with_param;
}
/* skip charset aggregation for order columns */
1
0