summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2018-07-03 14:02:05 +0400
committerAlexander Barkov <bar@mariadb.com>2018-07-03 14:02:05 +0400
commite61568ee9305c6c93c1a9f298a7fe04532881f24 (patch)
treec80b0967460f7c4f8743831690f7369e11c73722 /sql
parent4b0cedf82d8d8ba582648dcb4a2620c146862a43 (diff)
parentc3289d27eef39a47fed2ce1ff239013ed6870f39 (diff)
downloadmariadb-git-e61568ee9305c6c93c1a9f298a7fe04532881f24.tar.gz
Merge remote-tracking branch 'origin/10.3' into 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/CMakeLists.txt89
-rw-r--r--sql/events.cc8
-rw-r--r--sql/field.cc43
-rw-r--r--sql/field.h39
-rw-r--r--sql/gen_lex_token.cc2
-rw-r--r--sql/ha_partition.cc3
-rw-r--r--sql/handler.cc13
-rw-r--r--sql/handler.h10
-rw-r--r--sql/item.cc25
-rw-r--r--sql/item.h10
-rw-r--r--sql/item_cmpfunc.cc98
-rw-r--r--sql/item_cmpfunc.h80
-rw-r--r--sql/item_func.cc143
-rw-r--r--sql/item_func.h159
-rw-r--r--sql/item_geofunc.cc9
-rw-r--r--sql/item_geofunc.h77
-rw-r--r--sql/item_inetfunc.h12
-rw-r--r--sql/item_jsonfunc.cc140
-rw-r--r--sql/item_jsonfunc.h40
-rw-r--r--sql/item_strfunc.cc164
-rw-r--r--sql/item_strfunc.h192
-rw-r--r--sql/item_subselect.cc71
-rw-r--r--sql/item_subselect.h22
-rw-r--r--sql/item_sum.cc54
-rw-r--r--sql/item_sum.h34
-rw-r--r--sql/item_timefunc.cc38
-rw-r--r--sql/item_timefunc.h146
-rw-r--r--sql/item_vers.h8
-rw-r--r--sql/item_windowfunc.cc14
-rw-r--r--sql/item_windowfunc.h15
-rw-r--r--sql/item_xmlfunc.cc13
-rw-r--r--sql/item_xmlfunc.h2
-rw-r--r--sql/log.cc13
-rw-r--r--sql/log_event.cc37
-rw-r--r--sql/mysql_install_db.cc2
-rw-r--r--sql/mysql_upgrade_service.cc20
-rw-r--r--sql/net_serv.cc6
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/opt_subselect.cc3
-rw-r--r--sql/set_var.cc48
-rw-r--r--sql/set_var.h12
-rw-r--r--sql/slave.cc2
-rw-r--r--sql/sp_head.cc18
-rw-r--r--sql/sp_head.h22
-rw-r--r--sql/sp_rcontext.cc73
-rw-r--r--sql/sp_rcontext.h121
-rw-r--r--sql/sql_acl.cc18
-rw-r--r--sql/sql_alter.cc31
-rw-r--r--sql/sql_alter.h9
-rw-r--r--sql/sql_analyze_stmt.cc2
-rw-r--r--sql/sql_base.cc9
-rw-r--r--sql/sql_class.cc112
-rw-r--r--sql/sql_class.h159
-rw-r--r--sql/sql_digest.cc2
-rw-r--r--sql/sql_explain.cc3
-rw-r--r--sql/sql_handler.cc1
-rw-r--r--sql/sql_insert.cc39
-rw-r--r--sql/sql_lex.cc25
-rw-r--r--sql/sql_lex.h14
-rw-r--r--sql/sql_load.cc7
-rw-r--r--sql/sql_parse.cc11
-rw-r--r--sql/sql_plugin.cc3
-rw-r--r--sql/sql_repl.cc1
-rw-r--r--sql/sql_select.cc80
-rw-r--r--sql/sql_show.cc85
-rw-r--r--sql/sql_statistics.cc6
-rw-r--r--sql/sql_table.cc52
-rw-r--r--sql/sql_trigger.cc2
-rw-r--r--sql/sql_union.cc6
-rw-r--r--sql/sql_view.cc10
-rw-r--r--sql/sql_yacc.yy10
-rw-r--r--sql/sql_yacc_ora.yy11
-rw-r--r--sql/structs.h4
-rw-r--r--sql/sys_vars.cc15
-rw-r--r--sql/sys_vars.ic136
-rw-r--r--sql/sys_vars_shared.h1
-rw-r--r--sql/table.cc134
-rw-r--r--sql/table.h9
-rw-r--r--sql/wsrep_hton.cc36
-rw-r--r--sql/wsrep_mysqld.cc67
-rw-r--r--sql/wsrep_mysqld.h14
-rw-r--r--sql/wsrep_priv.h2
-rw-r--r--sql/wsrep_sst.cc73
-rw-r--r--sql/wsrep_var.cc6
84 files changed, 2040 insertions, 1317 deletions
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index 7253f7ba447..0037ff23153 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -45,23 +45,10 @@ ${CMAKE_BINARY_DIR}/sql
${WSREP_INCLUDES}
)
-SET(GEN_SOURCES
-${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h
-${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
-${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.h
-${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
-${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
-${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
-)
-SET_SOURCE_FILES_PROPERTIES(${GEN_SOURCES}
- PROPERTIES GENERATED 1)
-IF(NOT CMAKE_CROSSCOMPILING)
- ADD_EXECUTABLE(gen_lex_token gen_lex_token.cc
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h)
-ENDIF()
+
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
@@ -151,7 +138,10 @@ SET (SQL_SOURCE
table_cache.cc encryption.cc temporary_tables.cc
proxy_protocol.cc
${CMAKE_CURRENT_BINARY_DIR}/sql_builtin.cc
- ${GEN_SOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
+ ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
+ ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
${MYSYS_LIBWRAP_SOURCE}
)
@@ -173,7 +163,6 @@ MYSQL_ADD_PLUGIN(sql_sequence ha_sequence.cc STORAGE_ENGINE MANDATORY STATIC_ONL
RECOMPILE_FOR_EMBEDDED)
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
@@ -339,40 +328,48 @@ IF(WITH_MYSQLD_LDFLAGS)
"${MYSQLD_LINK_FLAGS} ${WITH_MYSQLD_LDFLAGS}")
ENDIF()
-INCLUDE(${CMAKE_SOURCE_DIR}/cmake/bison.cmake)
+
+FIND_PACKAGE(BISON 2.0)
+
# Handle out-of-source build from source package with possibly broken
# bison. Copy bison output to from source to build directory, if not already
# there
-IF (NOT BISON_USABLE)
-IF (NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
- IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.cc)
- IF(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc)
- CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.cc
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc COPYONLY)
- CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.h
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h COPYONLY)
+IF (NOT BISON_FOUND)
+ IF (NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR})
+ FOREACH(file sql_yacc.cc sql_yacc.hh sql_yacc_ora.cc sql_yacc_ora.hh)
+ IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file} AND (NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${file}))
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${file}
+ ${CMAKE_CURRENT_BINARY_DIR}/${file} COPYONLY)
ENDIF()
+ ENDFOREACH()
ENDIF()
-ENDIF()
-ENDIF()
-RUN_BISON(
- ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.h
- MYSQL
-)
+ IF(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc)
+ # Output files are missing, bail out.
+ SET(ERRMSG
+ "Bison (GNU parser generator) is required to build MySQL."
+ "Please install bison."
+ )
+ IF(WIN32)
+ SET(ERRMSG ${ERRMSG}
+ "You can download bison from http://gnuwin32.sourceforge.net/packages/bison.htm "
+ "Choose 'Complete package, except sources' installation. We recommend to "
+ "install bison into a directory without spaces, e.g C:\\GnuWin32.")
+ ENDIF()
+ MESSAGE(FATAL_ERROR ${ERRMSG})
+ ENDIF()
+ELSE()
+ BISON_TARGET(gen_sql_yacc ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc.yy ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.cc
+ COMPILE_FLAGS "-p MYSQL")
-RUN_BISON(
- ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc_ora.yy
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
- ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.h
- ORA
-)
+ BISON_TARGET(gen_sql_yacc_ora ${CMAKE_CURRENT_SOURCE_DIR}/sql_yacc_ora.yy ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
+ COMPILE_FLAGS "-p ORA")
+ENDIF()
-# Gen_lex_hash
IF(NOT CMAKE_CROSSCOMPILING)
+ ADD_EXECUTABLE(gen_lex_token gen_lex_token.cc
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc.hh)
ADD_EXECUTABLE(gen_lex_hash gen_lex_hash.cc)
ENDIF()
@@ -388,12 +385,12 @@ TARGET_LINK_LIBRARIES(mysql_tzinfo_to_sql mysys mysys_ssl)
ADD_CUSTOM_TARGET(
GenServerSource
- DEPENDS ${GEN_SOURCES}
+ DEPENDS
+ ${CMAKE_CURRENT_BINARY_DIR}/lex_hash.h
+ ${CMAKE_CURRENT_BINARY_DIR}/lex_token.h
+ ${CMAKE_CURRENT_BINARY_DIR}/sql_yacc_ora.cc
)
-#Need this only for embedded
-SET_TARGET_PROPERTIES(GenServerSource PROPERTIES EXCLUDE_FROM_ALL TRUE)
-
IF(WIN32 OR HAVE_DLOPEN AND NOT DISABLE_SHARED)
ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def)
SET_TARGET_PROPERTIES(udf_example PROPERTIES PREFIX "")
@@ -406,8 +403,8 @@ CONFIGURE_FILE(
ADD_CUSTOM_TARGET(dist
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/make_dist.cmake
- DEPENDS ${CMAKE_BINARY_DIR}/sql/sql_yacc.cc ${CMAKE_BINARY_DIR}/sql/sql_yacc.h
- DEPENDS ${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.cc ${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.h
+ DEPENDS ${CMAKE_BINARY_DIR}/sql/sql_yacc.cc ${CMAKE_BINARY_DIR}/sql/sql_yacc.hh
+ DEPENDS ${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.cc ${CMAKE_BINARY_DIR}/sql/sql_yacc_ora.hh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)
diff --git a/sql/events.cc b/sql/events.cc
index 49ac4b71100..c13582e634c 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -463,8 +463,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
if (check_access(thd, EVENT_ACL, parse_data->dbname.str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
if (lock_object_name(thd, MDL_key::EVENT,
parse_data->dbname.str, parse_data->name.str))
@@ -594,8 +593,7 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
if (check_access(thd, EVENT_ACL, dbname->str, NULL, NULL, 0, 0))
DBUG_RETURN(TRUE);
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/*
Turn off row binlogging of this statement and use statement-based so
@@ -621,7 +619,7 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname,
#ifdef WITH_WSREP
error:
DBUG_RETURN(TRUE);
-#endif
+#endif /* WITH_WSREP */
}
diff --git a/sql/field.cc b/sql/field.cc
index dc854826ed6..2b8bd0a3fb3 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -3093,6 +3093,23 @@ void Field_decimal::sql_type(String &res) const
}
+Field *Field_decimal::make_new_field(MEM_ROOT *root, TABLE *new_table,
+ bool keep_type)
+{
+ if (keep_type)
+ return Field_real::make_new_field(root, new_table, keep_type);
+
+ Field *field= new (root) Field_new_decimal(NULL, field_length,
+ maybe_null() ? (uchar*) "" : 0, 0,
+ NONE, &field_name,
+ dec, flags & ZEROFILL_FLAG,
+ unsigned_flag);
+ if (field)
+ field->init_for_make_new_field(new_table, orig_table);
+ return field;
+}
+
+
/****************************************************************************
** Field_new_decimal
****************************************************************************/
@@ -3386,6 +3403,16 @@ longlong Field_new_decimal::val_int(void)
}
+ulonglong Field_new_decimal::val_uint(void)
+{
+ ASSERT_COLUMN_MARKED_FOR_READ;
+ longlong i;
+ my_decimal decimal_value;
+ my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), true, &i);
+ return i;
+}
+
+
my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
{
ASSERT_COLUMN_MARKED_FOR_READ;
@@ -7503,15 +7530,7 @@ Field *Field_string::make_new_field(MEM_ROOT *root, TABLE *new_table,
This is done to ensure that ALTER TABLE will convert old VARCHAR fields
to now VARCHAR fields.
*/
- field->init(new_table);
- /*
- Normally orig_table is different from table only if field was
- created via ::make_new_field. Here we alter the type of field,
- so ::make_new_field is not applicable. But we still need to
- preserve the original field metadata for the client-server
- protocol.
- */
- field->orig_table= orig_table;
+ field->init_for_make_new_field(new_table, orig_table);
}
return field;
}
@@ -10931,6 +10950,7 @@ uint32 Field_blob::max_display_length() const
@param level - level of message (Note/Warning/Error)
@param code - error code of message to be produced
@param cut_increment - whenever we should increase cut fields count
+ @current_row - current row number
@note
This function won't produce warning or notes or increase cut fields counter
@@ -10948,7 +10968,7 @@ uint32 Field_blob::max_display_length() const
bool
Field::set_warning(Sql_condition::enum_warning_level level, uint code,
- int cut_increment) const
+ int cut_increment, ulong current_row) const
{
/*
If this field was created only for type conversion purposes it
@@ -10959,7 +10979,8 @@ Field::set_warning(Sql_condition::enum_warning_level level, uint code,
{
thd->cuted_fields+= cut_increment;
push_warning_printf(thd, level, code, ER_THD(thd, code), field_name.str,
- thd->get_stmt_da()->current_row_for_warning());
+ current_row ? current_row
+ : thd->get_stmt_da()->current_row_for_warning());
return 0;
}
return level >= Sql_condition::WARN_LEVEL_WARN;
diff --git a/sql/field.h b/sql/field.h
index b6f28808e2e..a7335d3f018 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -800,9 +800,14 @@ public:
}
virtual double val_real(void)=0;
virtual longlong val_int(void)=0;
+ /*
+ Get ulonglong representation.
+ Negative values are truncated to 0.
+ */
virtual ulonglong val_uint(void)
{
- return (ulonglong) val_int();
+ longlong nr= val_int();
+ return nr < 0 ? 0 : (ulonglong) nr;
}
virtual bool val_bool(void)= 0;
virtual my_decimal *val_decimal(my_decimal *);
@@ -1343,7 +1348,7 @@ public:
virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
virtual int set_time() { return 1; }
bool set_warning(Sql_condition::enum_warning_level, unsigned int code,
- int cuted_increment) const;
+ int cuted_increment, ulong current_row=0) const;
protected:
bool set_warning(unsigned int code, int cuted_increment) const
{
@@ -1393,6 +1398,19 @@ public:
org_field->type() == MYSQL_TYPE_VARCHAR)
new_table->s->db_create_options|= HA_OPTION_PACK_RECORD;
}
+ void init_for_make_new_field(TABLE *new_table_arg, TABLE *orig_table_arg)
+ {
+ init(new_table_arg);
+ /*
+ Normally orig_table is different from table only if field was
+ created via ::make_new_field. Here we alter the type of field,
+ so ::make_new_field is not applicable. But we still need to
+ preserve the original field metadata for the client-server
+ protocol.
+ */
+ orig_table= orig_table_arg;
+ }
+
/* maximum possible display length */
virtual uint32 max_display_length() const= 0;
/**
@@ -1663,6 +1681,8 @@ public:
bool eq_def(const Field *field) const;
Copy_func *get_copy_func(const Field *from) const
{
+ if (unsigned_flag && from->cmp_type() == DECIMAL_RESULT)
+ return do_field_decimal;
return do_field_int;
}
int save_in_field(Field *to)
@@ -1877,6 +1897,7 @@ public:
unireg_check_arg, field_name_arg,
dec_arg, zero_arg, unsigned_arg)
{}
+ Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
const Type_handler *type_handler() const { return &type_handler_olddecimal; }
enum ha_base_keytype key_type() const
{ return zerofill ? HA_KEYTYPE_BINARY : HA_KEYTYPE_NUM; }
@@ -1957,6 +1978,7 @@ public:
int store_decimal(const my_decimal *);
double val_real(void);
longlong val_int(void);
+ ulonglong val_uint(void);
my_decimal *val_decimal(my_decimal *);
String *val_str(String*, String *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
@@ -2003,6 +2025,11 @@ public:
int store_decimal(const my_decimal *);
my_decimal *val_decimal(my_decimal *);
bool val_bool() { return val_int() != 0; }
+ ulonglong val_uint()
+ {
+ longlong nr= val_int();
+ return nr < 0 && !unsigned_flag ? 0 : (ulonglong) nr;
+ }
int store_time_dec(const MYSQL_TIME *ltime, uint dec);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
virtual const Type_limits_int *type_limits_int() const= 0;
@@ -3747,6 +3774,10 @@ public:
uint32 char_length() const;
uint32 octet_length() const;
uint is_equal(Create_field *new_field);
+
+ friend void TABLE::remember_blob_values(String *blob_storage);
+ friend void TABLE::restore_blob_values(String *blob_storage);
+
private:
int save_field_metadata(uchar *first_byte);
};
@@ -4044,6 +4075,8 @@ public:
}
Copy_func *get_copy_func(const Field *from) const
{
+ if (from->cmp_type() == DECIMAL_RESULT)
+ return do_field_decimal;
return do_field_int;
}
int save_in_field(Field *to) { return to->store(val_int(), true); }
@@ -4344,7 +4377,7 @@ public:
length*= charset->mbmaxlen;
if (real_field_type() == MYSQL_TYPE_VARCHAR && compression_method())
length++;
- DBUG_ASSERT(length <= UINT_MAX32);
+ set_if_smaller(length, UINT_MAX32);
key_length= (uint) length;
pack_length= type_handler()->calc_pack_length((uint32) length);
}
diff --git a/sql/gen_lex_token.cc b/sql/gen_lex_token.cc
index b36df5e94be..c03bfe66f47 100644
--- a/sql/gen_lex_token.cc
+++ b/sql/gen_lex_token.cc
@@ -19,7 +19,7 @@
/* We only need the tokens here */
#define YYSTYPE_IS_DECLARED
-#include <sql_yacc.h>
+#include <sql_yacc.hh>
#include <lex.h>
#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 58247234eec..18a6a15c766 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5201,7 +5201,8 @@ int ha_partition::rnd_pos_by_record(uchar *record)
if (unlikely(get_part_for_buf(record, m_rec0, m_part_info, &m_last_part)))
DBUG_RETURN(1);
- DBUG_RETURN(handler::rnd_pos_by_record(record));
+ int err= m_file[m_last_part]->rnd_pos_by_record(record);
+ DBUG_RETURN(err);
}
diff --git a/sql/handler.cc b/sql/handler.cc
index b77b2a3fa2c..b3481c7e429 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3597,8 +3597,8 @@ void handler::print_error(int error, myf errflag)
break;
case HA_ERR_ABORTED_BY_USER:
{
- DBUG_ASSERT(table->in_use->killed);
- table->in_use->send_kill_message();
+ DBUG_ASSERT(ha_thd()->killed);
+ ha_thd()->send_kill_message();
DBUG_VOID_RETURN;
}
case HA_ERR_WRONG_MRG_TABLE_DEF:
@@ -3839,7 +3839,7 @@ void handler::print_error(int error, myf errflag)
*/
errflag|= ME_ERROR_LOG;
}
- }
+ }
/* if we got an OS error from a file-based engine, specify a path of error */
if (error < HA_ERR_FIRST && bas_ext()[0])
@@ -4579,6 +4579,7 @@ handler::ha_create_partitioning_metadata(const char *name,
DBUG_ASSERT(m_lock_type == F_UNLCK ||
(!old_name && strcmp(name, table_share->path.str)));
+
return create_partitioning_metadata(name, old_name, action_flag);
}
@@ -6505,6 +6506,12 @@ void ha_fake_trx_id(THD *thd)
DBUG_VOID_RETURN;
}
+ if (thd->wsrep_ws_handle.trx_id != WSREP_UNDEFINED_TRX_ID)
+ {
+ WSREP_DEBUG("fake trx id skipped: %lu", thd->wsrep_ws_handle.trx_id);
+ DBUG_VOID_RETURN;
+ }
+
/* Try statement transaction if standard one is not set. */
THD_TRANS *trans= (thd->transaction.all.ha_list) ? &thd->transaction.all :
&thd->transaction.stmt;
diff --git a/sql/handler.h b/sql/handler.h
index 3d1b764bd14..54df7941526 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -3556,9 +3556,17 @@ public:
*/
virtual int rnd_pos_by_record(uchar *record)
{
+ int error;
DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION);
+
+ error = ha_rnd_init(false);
+ if (error != 0)
+ return error;
+
position(record);
- return rnd_pos(record, ref);
+ error = ha_rnd_pos(record, ref);
+ ha_rnd_end();
+ return error;
}
virtual int read_first_row(uchar *buf, uint primary_key);
public:
diff --git a/sql/item.cc b/sql/item.cc
index 68aed25a580..878b4c91439 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -202,6 +202,19 @@ String *Item::val_str_ascii(String *str)
}
+String *Item::val_str_ascii_revert_empty_string_is_null(THD *thd, String *str)
+{
+ String *res= val_str_ascii(str);
+ if (!res && (thd->variables.sql_mode & MODE_EMPTY_STRING_IS_NULL))
+ {
+ null_value= false;
+ str->set("", 0, &my_charset_latin1);
+ return str;
+ }
+ return res;
+}
+
+
String *Item::val_str(String *str, String *converter, CHARSET_INFO *cs)
{
String *res= val_str(str);
@@ -2253,6 +2266,7 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref)
collation.set(value_item->collation.collation, DERIVATION_IMPLICIT);
max_length= value_item->max_length;
decimals= value_item->decimals;
+ unsigned_flag= value_item->unsigned_flag;
fixed= 1;
return FALSE;
}
@@ -5515,9 +5529,11 @@ static Item** find_field_in_group_list(Item *find_item, ORDER *group_list)
in the SELECT clause of Q.
- Search for a column named col_ref_i [in table T_j]
in the GROUP BY clause of Q.
- - If found different columns with the same name in GROUP BY and SELECT
- - issue a warning and return the GROUP BY column,
- - otherwise
+ - If found different columns with the same name in GROUP BY and SELECT:
+ - if the condition that uses this column name is pushed down into
+ the HAVING clause return the SELECT column
+ - else issue a warning and return the GROUP BY column.
+ - Otherwise
- if the MODE_ONLY_FULL_GROUP_BY mode is enabled return error
- else return the found SELECT column.
@@ -5556,7 +5572,8 @@ resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
/* Check if the fields found in SELECT and GROUP BY are the same field. */
if (group_by_ref && (select_ref != not_found_item) &&
- !((*group_by_ref)->eq(*select_ref, 0)))
+ !((*group_by_ref)->eq(*select_ref, 0)) &&
+ (!select->having_fix_field_for_pushed_cond))
{
ambiguous_fields= TRUE;
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
diff --git a/sql/item.h b/sql/item.h
index f6f4684f643..29e5b6455cc 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1320,7 +1320,13 @@ public:
Similar to val_str()
*/
virtual String *val_str_ascii(String *str);
-
+
+ /*
+ Returns the result of val_str_ascii(), translating NULLs back
+ to empty strings (if MODE_EMPTY_STRING_IS_NULL is set).
+ */
+ String *val_str_ascii_revert_empty_string_is_null(THD *thd, String *str);
+
/*
Returns the val_str() value converted to the given character set.
*/
@@ -4993,7 +4999,7 @@ public:
also to make printing of items inherited from Item_sum uniform.
*/
virtual const char *func_name() const= 0;
- virtual void fix_length_and_dec()= 0;
+ virtual bool fix_length_and_dec()= 0;
bool const_item() const { return const_item_cache; }
table_map used_tables() const { return used_tables_cache; }
Item* build_clone(THD *thd);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 4fa3cdce618..afe05445f38 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -426,7 +426,7 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
}
-void Item_bool_rowready_func2::fix_length_and_dec()
+bool Item_bool_rowready_func2::fix_length_and_dec()
{
max_length= 1; // Function returns 0 or 1
@@ -435,8 +435,8 @@ void Item_bool_rowready_func2::fix_length_and_dec()
we have to check for out of memory conditions here
*/
if (!args[0] || !args[1])
- return;
- setup_args_and_comparator(current_thd, &cmp);
+ return FALSE;
+ return setup_args_and_comparator(current_thd, &cmp);
}
@@ -1084,12 +1084,13 @@ int Arg_comparator::compare_e_str_json()
}
-void Item_func_truth::fix_length_and_dec()
+bool Item_func_truth::fix_length_and_dec()
{
maybe_null= 0;
null_value= 0;
decimals= 0;
max_length= 1;
+ return FALSE;
}
@@ -1708,10 +1709,11 @@ longlong Item_func_eq::val_int()
/** Same as Item_func_eq, but NULL = NULL. */
-void Item_func_equal::fix_length_and_dec()
+bool Item_func_equal::fix_length_and_dec()
{
- Item_bool_rowready_func2::fix_length_and_dec();
+ bool rc= Item_bool_rowready_func2::fix_length_and_dec();
maybe_null=null_value=0;
+ return rc;
}
longlong Item_func_equal::val_int()
@@ -1808,7 +1810,7 @@ bool Item_func_interval::fix_fields(THD *thd, Item **ref)
}
-void Item_func_interval::fix_length_and_dec()
+bool Item_func_interval::fix_length_and_dec()
{
uint rows= row->cols();
@@ -1826,10 +1828,13 @@ void Item_func_interval::fix_length_and_dec()
not_null_consts&= el->const_item() && !el->is_null();
}
- if (not_null_consts &&
- (intervals= (interval_range*) current_thd->alloc(sizeof(interval_range) *
- (rows - 1))))
+ if (not_null_consts)
{
+ intervals= (interval_range*) current_thd->alloc(sizeof(interval_range) *
+ (rows - 1));
+ if (!intervals)
+ return TRUE;
+
if (use_decimal_comparison)
{
for (uint i= 1; i < rows; i++)
@@ -1870,6 +1875,7 @@ void Item_func_interval::fix_length_and_dec()
join_with_sum_func(row);
with_param= with_param || row->with_param;
with_field= with_field || row->with_field;
+ return FALSE;
}
@@ -2030,7 +2036,7 @@ void Item_func_between::fix_after_pullout(st_select_lex *new_parent,
eval_not_null_tables(NULL);
}
-void Item_func_between::fix_length_and_dec()
+bool Item_func_between::fix_length_and_dec()
{
max_length= 1;
@@ -2039,15 +2045,16 @@ void Item_func_between::fix_length_and_dec()
we have to check for out of memory conditions here
*/
if (!args[0] || !args[1] || !args[2])
- return;
+ return TRUE;
if (m_comparator.aggregate_for_comparison(Item_func_between::func_name(),
args, 3, true))
{
DBUG_ASSERT(current_thd->is_error());
- return;
+ return TRUE;
}
- m_comparator.type_handler()->Item_func_between_fix_length_and_dec(this);
+ return m_comparator.type_handler()->
+ Item_func_between_fix_length_and_dec(this);
}
@@ -2070,7 +2077,7 @@ bool Item_func_between::fix_length_and_dec_numeric(THD *thd)
}
}
}
- return false;
+ return FALSE;
}
@@ -2438,7 +2445,7 @@ void Item_func_nullif::update_used_tables()
-void
+bool
Item_func_nullif::fix_length_and_dec()
{
/*
@@ -2588,6 +2595,8 @@ Item_func_nullif::fix_length_and_dec()
m_cache= args[0]->cmp_type() == STRING_RESULT ?
new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) :
args[0]->get_cache(thd);
+ if (!m_cache)
+ return TRUE;
m_cache->setup(thd, args[0]);
m_cache->store(args[0]);
m_cache->set_used_tables(args[0]->used_tables());
@@ -2601,7 +2610,8 @@ Item_func_nullif::fix_length_and_dec()
fix_char_length(args[2]->max_char_length());
maybe_null=1;
m_arg0= args[0];
- setup_args_and_comparator(thd, &cmp);
+ if (setup_args_and_comparator(thd, &cmp))
+ return TRUE;
/*
A special code for EXECUTE..PREPARE.
@@ -2641,6 +2651,7 @@ Item_func_nullif::fix_length_and_dec()
*/
if (args[0] == m_arg0)
m_arg0= NULL;
+ return FALSE;
}
@@ -3036,26 +3047,26 @@ bool Item_func_case_simple::prepare_predicant_and_values(THD *thd,
}
-void Item_func_case_searched::fix_length_and_dec()
+bool Item_func_case_searched::fix_length_and_dec()
{
THD *thd= current_thd;
- aggregate_then_and_else_arguments(thd, when_count());
+ return aggregate_then_and_else_arguments(thd, when_count());
}
-void Item_func_case_simple::fix_length_and_dec()
+bool Item_func_case_simple::fix_length_and_dec()
{
THD *thd= current_thd;
- if (!aggregate_then_and_else_arguments(thd, when_count() + 1))
- aggregate_switch_and_when_arguments(thd, false);
+ return (aggregate_then_and_else_arguments(thd, when_count() + 1) ||
+ aggregate_switch_and_when_arguments(thd, false));
}
-void Item_func_decode_oracle::fix_length_and_dec()
+bool Item_func_decode_oracle::fix_length_and_dec()
{
THD *thd= current_thd;
- if (!aggregate_then_and_else_arguments(thd, when_count() + 1))
- aggregate_switch_and_when_arguments(thd, true);
+ return (aggregate_then_and_else_arguments(thd, when_count() + 1) ||
+ aggregate_switch_and_when_arguments(thd, true));
}
@@ -4138,7 +4149,7 @@ bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types)
}
-void Item_func_in::fix_length_and_dec()
+bool Item_func_in::fix_length_and_dec()
{
THD *thd= current_thd;
uint found_types;
@@ -4148,18 +4159,20 @@ void Item_func_in::fix_length_and_dec()
if (prepare_predicant_and_values(thd, &found_types))
{
DBUG_ASSERT(thd->is_error()); // Must set error
- return;
+ return TRUE;
}
if (arg_types_compatible) // Bisection condition #1
{
- m_comparator.type_handler()->
- Item_func_in_fix_comparator_compatible_types(thd, this);
+ if (m_comparator.type_handler()->
+ Item_func_in_fix_comparator_compatible_types(thd, this))
+ return TRUE;
}
else
{
DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
- fix_for_scalar_comparison_using_cmp_items(thd, found_types);
+ if ( fix_for_scalar_comparison_using_cmp_items(thd, found_types))
+ return TRUE;
}
DBUG_EXECUTE_IF("Item_func_in",
@@ -4167,6 +4180,7 @@ void Item_func_in::fix_length_and_dec()
ER_UNKNOWN_ERROR, "DBUG: types_compatible=%s bisect=%s",
arg_types_compatible ? "yes" : "no",
array != NULL ? "yes" : "no"););
+ return FALSE;
}
@@ -4643,7 +4657,8 @@ Item_cond::fix_fields(THD *thd, Item **ref)
with_window_func|= item->with_window_func;
maybe_null|= item->maybe_null;
}
- fix_length_and_dec();
+ if (fix_length_and_dec())
+ return TRUE;
fixed= 1;
return FALSE;
}
@@ -5678,16 +5693,16 @@ bool Item_func_regex::fix_fields(THD *thd, Item **ref)
return Item_bool_func::fix_fields(thd, ref);
}
-void
+bool
Item_func_regex::fix_length_and_dec()
{
- Item_bool_func::fix_length_and_dec();
-
- if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
- return;
+ if (Item_bool_func::fix_length_and_dec() ||
+ agg_arg_charsets_for_comparison(cmp_collation, args, 2))
+ return TRUE;
re.init(cmp_collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
+ return FALSE;
}
@@ -5711,15 +5726,16 @@ bool Item_func_regexp_instr::fix_fields(THD *thd, Item **ref)
}
-void
+bool
Item_func_regexp_instr::fix_length_and_dec()
{
if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
- return;
+ return TRUE;
re.init(cmp_collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate
+ return FALSE;
}
@@ -6639,7 +6655,8 @@ bool Item_equal::fix_fields(THD *thd, Item **ref)
}
if (prev_equal_field && last_equal_field != first_equal_field)
last_equal_field->next_equal_field= first_equal_field;
- fix_length_and_dec();
+ if (fix_length_and_dec())
+ return TRUE;
fixed= 1;
return FALSE;
}
@@ -6725,11 +6742,12 @@ longlong Item_equal::val_int()
}
-void Item_equal::fix_length_and_dec()
+bool Item_equal::fix_length_and_dec()
{
Item *item= get_first(NO_PARTICULAR_TAB, NULL);
const Type_handler *handler= item->type_handler();
eval_item= handler->make_cmp_item(current_thd, item->collation.collation);
+ return eval_item == NULL;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 08a462b0903..3b2e58dab89 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -219,7 +219,7 @@ public:
const Type_handler *type_handler() const { return &type_handler_bool; }
const Type_handler *fixed_type_handler() const { return &type_handler_bool; }
CHARSET_INFO *compare_collation() const { return NULL; }
- void fix_length_and_dec() { decimals=0; max_length=1; }
+ bool fix_length_and_dec() { decimals=0; max_length=1; return FALSE; }
uint decimal_precision() const { return 1; }
bool need_parentheses_in_default() { return true; }
};
@@ -235,7 +235,7 @@ class Item_func_truth : public Item_bool_func
public:
virtual bool val_bool();
virtual longlong val_int();
- virtual void fix_length_and_dec();
+ virtual bool fix_length_and_dec();
virtual void print(String *str, enum_query_type query_type);
enum precedence precedence() const { return CMP_PRECEDENCE; }
@@ -522,7 +522,7 @@ public:
cond);
return this;
}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
int set_cmp_func()
{
return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
@@ -735,7 +735,7 @@ public:
Item_func_equal(THD *thd, Item *a, Item *b):
Item_bool_rowready_func2(thd, a, b) {}
longlong val_int();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
table_map not_null_tables() const { return 0; }
enum Functype functype() const { return EQUAL_FUNC; }
enum Functype rev_functype() const { return EQUAL_FUNC; }
@@ -905,7 +905,7 @@ public:
enum Functype functype() const { return BETWEEN; }
const char *func_name() const { return "between"; }
enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool fix_length_and_dec_string(THD *)
{
return agg_arg_charsets_for_comparison(cmp_collation, args, 3);
@@ -953,10 +953,12 @@ public:
longlong val_int();
uint decimal_precision() const { return 1; }
const char *func_name() const { return "strcmp"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
+ return TRUE;
fix_char_length(2); // returns "1" or "0" or "-1"
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_strcmp>(thd, this); }
@@ -985,7 +987,7 @@ public:
{ }
bool fix_fields(THD *, Item **);
longlong val_int();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "interval"; }
uint decimal_precision() const { return 2; }
void print(String *str, enum_query_type query_type)
@@ -1011,10 +1013,12 @@ public:
my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool time_op(MYSQL_TIME *ltime);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- if (!aggregate_for_result(func_name(), args, arg_count, true))
- fix_attributes(args, arg_count);
+ if (aggregate_for_result(func_name(), args, arg_count, true))
+ return TRUE;
+ fix_attributes(args, arg_count);
+ return FALSE;
}
const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; }
@@ -1032,10 +1036,12 @@ public:
class Item_func_case_abbreviation2 :public Item_func_case_expression
{
protected:
- void fix_length_and_dec2(Item **items)
+ bool fix_length_and_dec2(Item **items)
{
- if (!aggregate_for_result(func_name(), items, 2, true))
- fix_attributes(items, 2);
+ if (aggregate_for_result(func_name(), items, 2, true))
+ return TRUE;
+ fix_attributes(items, 2);
+ return FALSE;
}
void cache_type_info(const Item *source, bool maybe_null_arg)
@@ -1045,7 +1051,7 @@ protected:
maybe_null= maybe_null_arg;
}
- void fix_length_and_dec2_eliminate_null(Item **items)
+ bool fix_length_and_dec2_eliminate_null(Item **items)
{
// Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
if (items[0]->type() == NULL_ITEM)
@@ -1061,8 +1067,10 @@ protected:
}
else
{
- fix_length_and_dec2(items);
+ if (fix_length_and_dec2(items))
+ return TRUE;
}
+ return FALSE;
}
public:
@@ -1084,10 +1092,12 @@ public:
my_decimal *decimal_op(my_decimal *);
bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool time_op(MYSQL_TIME *ltime);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_case_abbreviation2::fix_length_and_dec2(args);
+ if (Item_func_case_abbreviation2::fix_length_and_dec2(args))
+ return TRUE;
maybe_null= args[1]->maybe_null;
+ return FALSE;
}
const char *func_name() const { return "ifnull"; }
@@ -1153,9 +1163,9 @@ public:
Item_func_case_abbreviation2_switch(thd, a, b, c)
{}
bool fix_fields(THD *, Item **);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- fix_length_and_dec2_eliminate_null(args + 1);
+ return fix_length_and_dec2_eliminate_null(args + 1);
}
const char *func_name() const { return "if"; }
bool eval_not_null_tables(void *opt_arg);
@@ -1177,9 +1187,9 @@ public:
Item_func_case_abbreviation2_switch(thd, a, b, c)
{}
const char *func_name() const { return "nvl2"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- fix_length_and_dec2_eliminate_null(args + 1);
+ return fix_length_and_dec2_eliminate_null(args + 1);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_nvl2>(thd, this); }
@@ -1239,7 +1249,7 @@ public:
longlong int_op();
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool walk(Item_processor processor, bool walk_subquery, void *arg);
const char *func_name() const { return "nullif"; }
void print(String *str, enum_query_type query_type);
@@ -2151,7 +2161,7 @@ public:
reorder_args(0);
}
void print(String *str, enum_query_type query_type);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
// None of the arguments are in a comparison context
@@ -2203,7 +2213,7 @@ public:
DBUG_VOID_RETURN;
}
void print(String *str, enum_query_type query_type);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
Item *find_item();
Item *build_clone(THD *thd)
@@ -2228,7 +2238,7 @@ public:
{ }
const char *func_name() const { return "decode_oracle"; }
void print(String *str, enum_query_type query_type);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *find_item();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_decode_oracle>(thd, this); }
@@ -2316,7 +2326,7 @@ public:
{ }
longlong val_int();
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool compatible_types_scalar_bisection_possible()
{
DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
@@ -2482,7 +2492,11 @@ public:
}
CHARSET_INFO *compare_collation() const
{ return args[0]->collation.collation; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=0; }
+ bool fix_length_and_dec()
+ {
+ decimals=0; max_length=1; maybe_null=0;
+ return FALSE;
+ }
bool count_sargable_conds(void *arg);
};
@@ -2706,10 +2720,10 @@ public:
const char *func_name() const { return "like"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= 1;
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ return agg_arg_charsets_for_comparison(cmp_collation, args, 2);
}
void cleanup();
@@ -2830,7 +2844,7 @@ public:
}
longlong val_int();
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
Item *get_copy(THD *thd)
@@ -2880,7 +2894,7 @@ public:
}
longlong val_int();
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp_instr"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_regexp_instr>(thd, this); }
@@ -3115,7 +3129,7 @@ public:
longlong val_int();
const char *func_name() const { return "multiple equal"; }
void sort(Item_field_cmpfunc compare, void *arg);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
void cleanup()
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index ca616566f51..d904af7c56b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -377,8 +377,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
}
if (check_arguments())
return true;
- fix_length_and_dec();
- if (unlikely(thd->is_error())) // An error inside fix_length_and_dec occurred
+ if (fix_length_and_dec())
return TRUE;
fixed= 1;
return FALSE;
@@ -762,10 +761,12 @@ String *Item_int_func::val_str(String *str)
}
-void Item_func_connection_id::fix_length_and_dec()
+bool Item_func_connection_id::fix_length_and_dec()
{
- Item_long_func::fix_length_and_dec();
+ if (Item_long_func::fix_length_and_dec())
+ return TRUE;
max_length= 10;
+ return FALSE;
}
@@ -792,19 +793,19 @@ bool Item_num_op::fix_type_handler(const Type_aggregator *aggregator)
}
-void Item_func_plus::fix_length_and_dec(void)
+bool Item_func_plus::fix_length_and_dec(void)
{
DBUG_ENTER("Item_func_plus::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_plus;
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
DBUG_ASSERT(aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_plus::type_handler()->Item_func_plus_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
+ if (fix_type_handler(aggregator))
+ DBUG_RETURN(TRUE);
+ if (Item_func_plus::type_handler()->Item_func_plus_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@ -1319,19 +1320,19 @@ void Item_func_minus::fix_unsigned_flag()
}
-void Item_func_minus::fix_length_and_dec()
+bool Item_func_minus::fix_length_and_dec()
{
DBUG_ENTER("Item_func_minus::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_minus;
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
DBUG_ASSERT(!aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
+ if (fix_type_handler(aggregator))
+ DBUG_RETURN(TRUE);
+ if (Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@ -1551,19 +1552,19 @@ void Item_func_mul::result_precision()
}
-void Item_func_mul::fix_length_and_dec(void)
+bool Item_func_mul::fix_length_and_dec(void)
{
DBUG_ENTER("Item_func_mul::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mul;
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
DBUG_ASSERT(aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_mul::type_handler()->Item_func_mul_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
+ if (fix_type_handler(aggregator))
+ DBUG_RETURN(TRUE);
+ if (Item_func_mul::type_handler()->Item_func_mul_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@ -1658,7 +1659,7 @@ void Item_func_div::fix_length_and_dec_int(void)
}
-void Item_func_div::fix_length_and_dec(void)
+bool Item_func_div::fix_length_and_dec()
{
DBUG_ENTER("Item_func_div::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
@@ -1668,12 +1669,12 @@ void Item_func_div::fix_length_and_dec(void)
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_div;
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
DBUG_ASSERT(!aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_div::type_handler()->Item_func_div_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
+ if (fix_type_handler(aggregator))
+ DBUG_RETURN(TRUE);
+ if (Item_func_div::type_handler()->Item_func_div_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@ -1749,7 +1750,7 @@ longlong Item_func_int_div::val_int()
}
-void Item_func_int_div::fix_length_and_dec()
+bool Item_func_int_div::fix_length_and_dec()
{
Item_result argtype= args[0]->result_type();
/* use precision ony for the data type it is applicable for and valid */
@@ -1760,6 +1761,7 @@ void Item_func_int_div::fix_length_and_dec()
MY_INT64_NUM_DECIMAL_DIGITS : char_length);
maybe_null=1;
unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
+ return false;
}
@@ -1843,7 +1845,7 @@ void Item_func_mod::result_precision()
}
-void Item_func_mod::fix_length_and_dec()
+bool Item_func_mod::fix_length_and_dec()
{
DBUG_ENTER("Item_func_mod::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
@@ -1851,12 +1853,12 @@ void Item_func_mod::fix_length_and_dec()
const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mod;
DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
DBUG_ASSERT(!aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_mod::type_handler()->Item_func_mod_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
+ if (fix_type_handler(aggregator))
+ DBUG_RETURN(TRUE);
+ if (Item_func_mod::type_handler()->Item_func_mod_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@ -1954,13 +1956,15 @@ void Item_func_neg::fix_length_and_dec_decimal()
}
-void Item_func_neg::fix_length_and_dec()
+bool Item_func_neg::fix_length_and_dec()
{
DBUG_ENTER("Item_func_neg::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- args[0]->cast_to_int_type_handler()->Item_func_neg_fix_length_and_dec(this);
+ if (args[0]->cast_to_int_type_handler()->
+ Item_func_neg_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -1999,7 +2003,6 @@ my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
return 0;
}
-
void Item_func_abs::fix_length_and_dec_int()
{
max_length= args[0]->max_length;
@@ -2026,13 +2029,15 @@ void Item_func_abs::fix_length_and_dec_decimal()
}
-void Item_func_abs::fix_length_and_dec()
+bool Item_func_abs::fix_length_and_dec()
{
DBUG_ENTER("Item_func_abs::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- args[0]->cast_to_int_type_handler()->Item_func_abs_fix_length_and_dec(this);
+ if (args[0]->cast_to_int_type_handler()->
+ Item_func_abs_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -2298,14 +2303,15 @@ void Item_func_int_val::fix_length_and_dec_double()
}
-void Item_func_int_val::fix_length_and_dec()
+bool Item_func_int_val::fix_length_and_dec()
{
DBUG_ENTER("Item_func_int_val::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- args[0]->cast_to_int_type_handler()->
- Item_func_int_val_fix_length_and_dec(this);
+ if (args[0]->cast_to_int_type_handler()->
+ Item_func_int_val_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -2485,7 +2491,6 @@ void Item_func_round::fix_arg_int()
}
else
fix_length_and_dec_double(args[0]->decimals);
-
}
@@ -3042,14 +3047,15 @@ longlong Item_func_field::val_int()
}
-void Item_func_field::fix_length_and_dec()
+bool Item_func_field::fix_length_and_dec()
{
maybe_null=0; max_length=3;
cmp_type= args[0]->result_type();
for (uint i=1; i < arg_count ; i++)
cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
if (cmp_type == STRING_RESULT)
- agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
+ return agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
+ return FALSE;
}
@@ -3096,7 +3102,7 @@ longlong Item_func_ord::val_int()
/* Returns number of found type >= 1 or 0 if not found */
/* This optimizes searching in enums to bit testing! */
-void Item_func_find_in_set::fix_length_and_dec()
+bool Item_func_find_in_set::fix_length_and_dec()
{
decimals=0;
max_length=3; // 1-999
@@ -3118,7 +3124,7 @@ void Item_func_find_in_set::fix_length_and_dec()
}
}
}
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ return agg_arg_charsets_for_comparison(cmp_collation, args, 2);
}
static const char separator=',';
@@ -3321,7 +3327,8 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
DBUG_RETURN(TRUE);
}
}
- func->fix_length_and_dec();
+ if (func->fix_length_and_dec())
+ DBUG_RETURN(TRUE);
initid.max_length=func->max_length;
initid.maybe_null=func->maybe_null;
initid.const_item=func->const_item_cache;
@@ -3661,13 +3668,13 @@ String *Item_func_udf_decimal::val_str(String *str)
/* Default max_length is max argument length */
-void Item_func_udf_str::fix_length_and_dec()
+bool Item_func_udf_str::fix_length_and_dec()
{
DBUG_ENTER("Item_func_udf_str::fix_length_and_dec");
max_length=0;
for (uint i = 0; i < arg_count; i++)
set_if_bigger(max_length,args[i]->max_length);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
String *Item_func_udf_str::val_str(String *str)
@@ -4575,7 +4582,7 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
}
-void
+bool
Item_func_set_user_var::fix_length_and_dec()
{
maybe_null=args[0]->maybe_null;
@@ -4589,6 +4596,7 @@ Item_func_set_user_var::fix_length_and_dec()
args[0]->collation.collation);
}
unsigned_flag= args[0]->unsigned_flag;
+ return FALSE;
}
@@ -5428,7 +5436,7 @@ err:
return 1;
}
-void Item_func_get_user_var::fix_length_and_dec()
+bool Item_func_get_user_var::fix_length_and_dec()
{
THD *thd=current_thd;
int error;
@@ -5477,6 +5485,7 @@ void Item_func_get_user_var::fix_length_and_dec()
set_handler(&type_handler_long_blob);
max_length= MAX_BLOB_WIDTH;
}
+ return false;
}
@@ -5628,7 +5637,7 @@ void Item_func_get_system_var::update_null_value()
}
-void Item_func_get_system_var::fix_length_and_dec()
+bool Item_func_get_system_var::fix_length_and_dec()
{
char *cptr;
maybe_null= TRUE;
@@ -5640,7 +5649,7 @@ void Item_func_get_system_var::fix_length_and_dec()
{
my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
var->name.str, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
- return;
+ return TRUE;
}
/* As there was no local variable, return the global value */
var_type= OPT_GLOBAL;
@@ -5704,6 +5713,7 @@ void Item_func_get_system_var::fix_length_and_dec()
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
break;
}
+ return FALSE;
}
@@ -6363,7 +6373,7 @@ bool Item_func_sp::is_expensive()
@note called from Item::fix_fields.
*/
-void Item_func_sp::fix_length_and_dec()
+bool Item_func_sp::fix_length_and_dec()
{
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
@@ -6373,7 +6383,7 @@ void Item_func_sp::fix_length_and_dec()
collation.derivation= DERIVATION_COERCIBLE;
maybe_null= 1;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -6688,11 +6698,12 @@ bool Item_func_last_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
}
-void Item_func_last_value::fix_length_and_dec()
+bool Item_func_last_value::fix_length_and_dec()
{
last_value= args[arg_count -1];
Type_std_attributes::set(last_value);
maybe_null= last_value->maybe_null;
+ return FALSE;
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 3b6cb4ceeac..083b49bdda5 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -398,8 +398,12 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_real(ltime, fuzzydate); }
const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec()
- { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
+ bool fix_length_and_dec()
+ {
+ decimals= NOT_FIXED_DEC;
+ max_length= float_length(decimals);
+ return FALSE;
+ }
};
@@ -785,7 +789,7 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_int(ltime, fuzzydate); }
const Type_handler *type_handler() const= 0;
- void fix_length_and_dec() {}
+ bool fix_length_and_dec() { return FALSE; }
};
@@ -799,7 +803,7 @@ public:
Item_long_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
Item_long_func(THD *thd, Item_long_func *item) :Item_int_func(thd, item) {}
const Type_handler *type_handler() const { return &type_handler_long; }
- void fix_length_and_dec() { max_length= 11; }
+ bool fix_length_and_dec() { max_length= 11; return FALSE; }
};
@@ -861,7 +865,7 @@ class Item_func_connection_id :public Item_long_func
public:
Item_func_connection_id(THD *thd): Item_long_func(thd) { unsigned_flag=1; }
const char *func_name() const { return "connection_id"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
bool check_vcol_func_processor(void *arg)
@@ -918,9 +922,9 @@ public:
set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
fix_char_length(char_length);
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
+ return args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
}
virtual void print(String *str, enum_query_type query_type);
uint decimal_precision() const { return args[0]->decimal_precision(); }
@@ -950,9 +954,9 @@ public:
null_value= args[0]->null_value;
return value;
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
+ return args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
}
uint decimal_precision() const { return max_length; }
virtual void print(String *str, enum_query_type query_type);
@@ -981,9 +985,10 @@ public:
{ return get_date_from_decimal(ltime, fuzzydate); }
const Type_handler *type_handler() const { return &type_handler_newdecimal; }
void fix_length_and_dec_generic() {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this);
+ return
+ args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this);
}
const char *func_name() const { return "decimal_typecast"; }
virtual void print(String *str, enum_query_type query_type);
@@ -1004,9 +1009,10 @@ public:
}
double val_real();
void fix_length_and_dec_generic() { maybe_null= 1; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
+ return
+ args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
}
const char *func_name() const { return "double_typecast"; }
virtual void print(String *str, enum_query_type query_type);
@@ -1033,7 +1039,7 @@ public:
Item_func_additive_op(thd, a, b) {}
const char *func_name() const { return "+"; }
enum precedence precedence() const { return ADD_PRECEDENCE; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
@@ -1051,7 +1057,7 @@ public:
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void fix_unsigned_flag();
void fix_length_and_dec_double()
{
@@ -1084,7 +1090,7 @@ public:
double real_op();
my_decimal *decimal_op(my_decimal *);
void result_precision();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
Item *get_copy(THD *thd)
@@ -1102,7 +1108,7 @@ public:
my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "/"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void fix_length_and_dec_double();
void fix_length_and_dec_int();
void result_precision();
@@ -1121,7 +1127,7 @@ public:
enum precedence precedence() const { return MUL_PRECEDENCE; }
const Type_handler *type_handler() const
{ return type_handler_long_or_longlong(); }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void print(String *str, enum_query_type query_type)
{
print_op(str, query_type);
@@ -1145,7 +1151,7 @@ public:
const char *func_name() const { return "MOD"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
void result_precision();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void fix_length_and_dec_double()
{
Item_num_op::fix_length_and_dec_double();
@@ -1188,7 +1194,7 @@ public:
void fix_length_and_dec_int();
void fix_length_and_dec_double();
void fix_length_and_dec_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
bool need_parentheses_in_default() { return true; }
Item *get_copy(THD *thd)
@@ -1207,7 +1213,7 @@ public:
void fix_length_and_dec_int();
void fix_length_and_dec_double();
void fix_length_and_dec_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_abs>(thd, this); }
};
@@ -1221,10 +1227,11 @@ class Item_dec_func :public Item_real_func
public:
Item_dec_func(THD *thd, Item *a): Item_real_func(thd, a) {}
Item_dec_func(THD *thd, Item *a, Item *b): Item_real_func(thd, a, b) {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=NOT_FIXED_DEC; max_length=float_length(decimals);
maybe_null=1;
+ return FALSE;
}
};
@@ -1384,7 +1391,7 @@ public:
Item_func_int_val(THD *thd, Item *a): Item_func_num1(thd, a) {}
void fix_length_and_dec_double();
void fix_length_and_dec_int_or_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
};
@@ -1430,9 +1437,9 @@ public:
void fix_arg_decimal();
void fix_arg_int();
void fix_arg_double();
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_func_round_fix_length_and_dec(this);
+ return args[0]->type_handler()->Item_func_round_fix_length_and_dec(this);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_round>(thd, this); }
@@ -1474,7 +1481,7 @@ public:
Item_func_sign(THD *thd, Item *a): Item_long_func(thd, a) {}
const char *func_name() const { return "sign"; }
uint decimal_precision() const { return 1; }
- void fix_length_and_dec() { fix_char_length(2); }
+ bool fix_length_and_dec() { fix_char_length(2); return FALSE; }
longlong val_int();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_sign>(thd, this); }
@@ -1493,8 +1500,12 @@ public:
Item_real_func(thd, a), name(name_arg), mul(mul_arg), add(add_arg) {}
double val_real();
const char *func_name() const { return name; }
- void fix_length_and_dec()
- { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
+ bool fix_length_and_dec()
+ {
+ decimals= NOT_FIXED_DEC;
+ max_length= float_length(decimals);
+ return FALSE;
+ }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_units>(thd, this); }
};
@@ -1578,11 +1589,12 @@ public:
Item_func::aggregate_attributes_real(items, nitems);
max_length= float_length(decimals);
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
if (aggregate_for_min_max(func_name(), args, arg_count))
- return;
+ return true;
fix_attributes(args, arg_count);
+ return false;
}
};
@@ -1627,11 +1639,12 @@ public:
const char *func_name() const { return "rollup_const"; }
bool const_item() const { return 0; }
const Type_handler *type_handler() const { return args[0]->type_handler(); }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation= args[0]->collation;
max_length= args[0]->max_length;
decimals=args[0]->decimals;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_rollup_const>(thd, this); }
@@ -1644,7 +1657,7 @@ class Item_long_func_length: public Item_long_func
{ return args[0]->check_type_can_return_str(func_name()); }
public:
Item_long_func_length(THD *thd, Item *a): Item_long_func(thd, a) {}
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
};
@@ -1664,9 +1677,10 @@ class Item_func_bit_length :public Item_longlong_func
String value;
public:
Item_func_bit_length(THD *thd, Item *a): Item_longlong_func(thd, a) {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= 11; // 0x100000000*8 = 34,359,738,368
+ return FALSE;
}
longlong val_int();
const char *func_name() const { return "bit_length"; }
@@ -1693,7 +1707,7 @@ public:
Item_func_coercibility(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "coercibility"; }
- void fix_length_and_dec() { max_length=10; maybe_null= 0; }
+ bool fix_length_and_dec() { max_length=10; maybe_null= 0; return FALSE; }
bool eval_not_null_tables(void *)
{
not_null_tables_cache= 0;
@@ -1729,10 +1743,10 @@ public:
:Item_long_func(thd, a, b, c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= MY_INT32_NUM_DECIMAL_DIGITS;
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ return agg_arg_charsets_for_comparison(cmp_collation, args, 2);
}
virtual void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd)
@@ -1749,7 +1763,7 @@ public:
Item_func_field(THD *thd, List<Item> &list): Item_long_func(thd, list) {}
longlong val_int();
const char *func_name() const { return "field"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_field>(thd, this); }
};
@@ -1764,7 +1778,7 @@ public:
Item_func_ascii(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "ascii"; }
- void fix_length_and_dec() { max_length=3; }
+ bool fix_length_and_dec() { max_length=3; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_ascii>(thd, this); }
};
@@ -1776,7 +1790,7 @@ class Item_func_ord :public Item_long_func
String value;
public:
Item_func_ord(THD *thd, Item *a): Item_long_func(thd, a) {}
- void fix_length_and_dec() { fix_char_length(7); }
+ bool fix_length_and_dec() { fix_char_length(7); return FALSE; }
longlong val_int();
const char *func_name() const { return "ord"; }
Item *get_copy(THD *thd)
@@ -1796,7 +1810,7 @@ public:
Item_long_func(thd, a, b), enum_value(0) {}
longlong val_int();
const char *func_name() const { return "find_in_set"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_find_in_set>(thd, this); }
};
@@ -1810,7 +1824,7 @@ class Item_func_bit: public Item_longlong_func
public:
Item_func_bit(THD *thd, Item *a, Item *b): Item_longlong_func(thd, a, b) {}
Item_func_bit(THD *thd, Item *a): Item_longlong_func(thd, a) {}
- void fix_length_and_dec() { unsigned_flag= 1; }
+ bool fix_length_and_dec() { unsigned_flag= 1; return FALSE; }
virtual inline void print(String *str, enum_query_type query_type)
{
@@ -1849,7 +1863,7 @@ public:
Item_func_bit_count(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "bit_count"; }
- void fix_length_and_dec() { max_length=2; }
+ bool fix_length_and_dec() { max_length=2; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_bit_count>(thd, this); }
};
@@ -1902,11 +1916,12 @@ public:
Item_func_last_insert_id(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
unsigned_flag= true;
if (arg_count)
max_length= args[0]->max_length;
+ return FALSE;
}
bool fix_fields(THD *thd, Item **ref);
bool check_vcol_func_processor(void *arg)
@@ -1931,7 +1946,7 @@ public:
{}
longlong val_int();
const char *func_name() const { return "benchmark"; }
- void fix_length_and_dec() { max_length=1; maybe_null=0; }
+ bool fix_length_and_dec() { max_length=1; maybe_null=0; return FALSE; }
virtual void print(String *str, enum_query_type query_type);
bool check_vcol_func_processor(void *arg)
{
@@ -1951,7 +1966,7 @@ class Item_func_sleep :public Item_long_func
{ return args[0]->check_type_can_return_real(func_name()); }
public:
Item_func_sleep(THD *thd, Item *a): Item_long_func(thd, a) {}
- void fix_length_and_dec() { fix_char_length(1); }
+ bool fix_length_and_dec() { fix_char_length(1); return FALSE; }
bool const_item() const { return 0; }
const char *func_name() const { return "sleep"; }
table_map used_tables() const
@@ -2095,7 +2110,7 @@ class Item_func_udf_float :public Item_udf_func
double val_real();
String *val_str(String *str);
const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_udf_float>(thd, this); }
};
@@ -2113,7 +2128,7 @@ public:
double val_real() { return (double) Item_func_udf_int::val_int(); }
String *val_str(String *str);
const Type_handler *type_handler() const { return &type_handler_longlong; }
- void fix_length_and_dec() { decimals= 0; max_length= 21; }
+ bool fix_length_and_dec() { decimals= 0; max_length= 21; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_udf_int>(thd, this); }
};
@@ -2131,7 +2146,7 @@ public:
my_decimal *val_decimal(my_decimal *);
String *val_str(String *str);
const Type_handler *type_handler() const { return &type_handler_newdecimal; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_udf_decimal>(thd, this); }
};
@@ -2170,7 +2185,7 @@ public:
return dec_buf;
}
const Type_handler *type_handler() const { return string_type_handler(); }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_udf_str>(thd, this); }
};
@@ -2223,7 +2238,7 @@ public:
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- void fix_length_and_dec() { maybe_null=1; max_length=0; }
+ bool fix_length_and_dec() { maybe_null=1; max_length=0; return FALSE; }
};
#endif /* HAVE_DLOPEN */
@@ -2243,7 +2258,7 @@ class Item_func_get_lock :public Item_long_func
Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "get_lock"; }
- void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool fix_length_and_dec() { max_length=1; maybe_null=1; return FALSE; }
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@ -2267,7 +2282,7 @@ public:
Item_func_release_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
- void fix_length_and_dec() { max_length= 1; maybe_null= 1;}
+ bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; }
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@ -2304,7 +2319,7 @@ public:
Item_longlong_func(thd, a, b, c, d) {}
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
- void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ bool fix_length_and_dec() { max_length=21; maybe_null=1; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2329,7 +2344,7 @@ public:
:Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "master_gtid_wait"; }
- void fix_length_and_dec() { max_length=2; }
+ bool fix_length_and_dec() { max_length=2; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2426,7 +2441,7 @@ public:
void save_item_result(Item *item);
bool update();
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void print(String *str, enum_query_type query_type);
enum precedence precedence() const { return ASSIGN_PRECEDENCE; }
void print_as_stmt(String *str, enum_query_type query_type);
@@ -2461,7 +2476,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal*);
String *val_str(String* str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
virtual void print(String *str, enum_query_type query_type);
/*
We must always return variables as strings to guard against selects of type
@@ -2584,7 +2599,7 @@ public:
size_t name_len_arg);
enum Functype functype() const { return GSYSVAR_FUNC; }
void update_null_value();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void print(String *str, enum_query_type query_type);
bool const_item() const { return true; }
table_map used_tables() const { return 0; }
@@ -2728,7 +2743,11 @@ public:
Item_func_is_free_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ bool fix_length_and_dec()
+ {
+ decimals=0; max_length=1; maybe_null=1;
+ return FALSE;
+ }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2746,7 +2765,11 @@ public:
Item_func_is_used_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ bool fix_length_and_dec()
+ {
+ decimals=0; max_length=10; maybe_null=1;
+ return FALSE;
+ }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2795,7 +2818,7 @@ public:
Item_func_row_count(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "row_count"; }
- void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool fix_length_and_dec() { decimals= 0; maybe_null=0; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2915,7 +2938,7 @@ public:
virtual enum Functype functype() const { return FUNC_SP; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec(void);
+ bool fix_length_and_dec(void);
bool is_expensive();
inline Field *get_sp_result_field()
@@ -2955,7 +2978,7 @@ public:
Item_func_found_rows(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "found_rows"; }
- void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool fix_length_and_dec() { decimals= 0; maybe_null=0; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@ -2998,10 +3021,11 @@ public:
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
maybe_null= null_value= false;
max_length= 11;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_sqlcode>(thd, this); }
@@ -3017,8 +3041,8 @@ public:
const char *func_name() const { return "uuid_short"; }
longlong val_int();
bool const_item() const { return false; }
- void fix_length_and_dec()
- { max_length= 21; unsigned_flag=1; }
+ bool fix_length_and_dec()
+ { max_length= 21; unsigned_flag=1; return FALSE; }
table_map used_tables() const { return RAND_TABLE_BIT; }
bool check_vcol_func_processor(void *arg)
{
@@ -3040,7 +3064,7 @@ public:
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "last_value"; }
const Type_handler *type_handler() const { return last_value->type_handler(); }
bool eval_not_null_tables(void *)
@@ -3072,11 +3096,12 @@ public:
Item_longlong_func(thd), table_list(table_list_arg) {}
longlong val_int();
const char *func_name() const { return "nextval"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
unsigned_flag= 0;
max_length= MAX_BIGINT_WIDTH;
maybe_null= 1; /* In case of errors */
+ return FALSE;
}
/*
update_table() function must be called during the value function
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index aee44a7a01f..4c2a2fa8b11 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -40,12 +40,13 @@
#include "opt_range.h"
-void Item_geometry_func::fix_length_and_dec()
+bool Item_geometry_func::fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
max_length= (uint32) UINT_MAX32;
maybe_null= 1;
+ return FALSE;
}
@@ -214,11 +215,12 @@ String *Item_func_as_wkt::val_str_ascii(String *str)
}
-void Item_func_as_wkt::fix_length_and_dec()
+bool Item_func_as_wkt::fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
max_length= (uint32) UINT_MAX32;
maybe_null= 1;
+ return FALSE;
}
@@ -240,11 +242,12 @@ String *Item_func_as_wkb::val_str(String *str)
}
-void Item_func_as_geojson::fix_length_and_dec()
+bool Item_func_as_geojson::fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
max_length=MAX_BLOB_WIDTH;
maybe_null= 1;
+ return FALSE;
}
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index ede118cc4f3..e6c198fb8b2 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -38,7 +38,7 @@ public:
Item_geometry_func(THD *thd, Item *a, Item *b, Item *c):
Item_str_func(thd, a, b, c) {}
Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const Type_handler *type_handler() const { return &type_handler_geometry; }
};
@@ -253,7 +253,7 @@ public:
:Item_str_ascii_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_astext"; }
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_as_wkt>(thd, this); }
};
@@ -266,12 +266,13 @@ public:
const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
const Type_handler *type_handler() const { return &type_handler_long_blob; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
max_length= (uint32) UINT_MAX32;
maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_as_wkb>(thd, this); }
@@ -294,7 +295,7 @@ public:
Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
:Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
const char *func_name() const { return "st_asgeojson"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str_ascii(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_as_geojson>(thd, this); }
@@ -308,11 +309,12 @@ public:
:Item_str_ascii_func_args_geometry(thd, a) {}
String *val_str_ascii(String *);
const char *func_name() const { return "st_geometrytype"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
// "GeometryCollection" is the longest
fix_length_and_charset(20, default_charset());
maybe_null= 1;
+ return FALSE;
};
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_geometry_type>(thd, this); }
@@ -504,9 +506,10 @@ public:
item_type=it;
}
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_geometry_func::fix_length_and_dec();
+ if (Item_geometry_func::fix_length_and_dec())
+ return TRUE;
for (unsigned int i= 0; i < arg_count; ++i)
{
if (args[i]->is_fixed() && args[i]->field_type() != MYSQL_TYPE_GEOMETRY)
@@ -516,8 +519,10 @@ public:
str.append('\0');
my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "non geometric",
str.ptr());
+ return TRUE;
}
}
+ return FALSE;
}
const char *func_name() const { return "geometrycollection"; }
@@ -727,7 +732,7 @@ public:
:Item_bool_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isempty"; }
- void fix_length_and_dec() { maybe_null= 1; }
+ bool fix_length_and_dec() { maybe_null= 1; return FALSE; }
bool need_parentheses_in_default() { return false; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isempty>(thd, this); }
@@ -744,7 +749,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_issimple"; }
- void fix_length_and_dec() { decimals=0; max_length=2; }
+ bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
uint decimal_precision() const { return 1; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_issimple>(thd, this); }
@@ -757,7 +762,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isclosed"; }
- void fix_length_and_dec() { decimals=0; max_length=2; }
+ bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
uint decimal_precision() const { return 1; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_isclosed>(thd, this); }
@@ -780,7 +785,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_dimension"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_dimension>(thd, this); }
};
@@ -792,10 +797,12 @@ public:
Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_x"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_x>(thd, this); }
@@ -808,10 +815,12 @@ public:
Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_y"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_y>(thd, this); }
@@ -825,7 +834,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numgeometries"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_numgeometries>(thd, this); }
};
@@ -838,7 +847,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numinteriorrings"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_numinteriorring>(thd, this); }
};
@@ -851,7 +860,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numpoints"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_numpoints>(thd, this); }
};
@@ -863,10 +872,12 @@ public:
Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_area"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_area>(thd, this); }
@@ -881,10 +892,12 @@ public:
:Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_length"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_glength>(thd, this); }
@@ -898,7 +911,7 @@ public:
:Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "srid"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_srid>(thd, this); }
};
@@ -944,7 +957,7 @@ class Item_func_gis_debug: public Item_long_func
public:
Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
{ null_value= false; }
- void fix_length_and_dec() { fix_char_length(10); }
+ bool fix_length_and_dec() { fix_char_length(10); return FALSE; }
const char *func_name() const { return "st_gis_debug"; }
longlong val_int();
bool check_vcol_func_processor(void *arg)
diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h
index d934cef43dd..024ff8ce4f0 100644
--- a/sql/item_inetfunc.h
+++ b/sql/item_inetfunc.h
@@ -32,12 +32,13 @@ public:
Item_func_inet_aton(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "inet_aton"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals= 0;
max_length= 21;
maybe_null= 1;
unsigned_flag= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_inet_aton>(thd, this); }
@@ -55,11 +56,12 @@ public:
{ }
String* val_str(String* str);
const char *func_name() const { return "inet_ntoa"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals= 0;
fix_length_and_charset(3 * 8 + 7, default_charset());
maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_inet_ntoa>(thd, this); }
@@ -124,11 +126,12 @@ public:
virtual const char *func_name() const
{ return "inet6_aton"; }
- virtual void fix_length_and_dec()
+ virtual bool fix_length_and_dec()
{
decimals= 0;
fix_length_and_charset(16, &my_charset_bin);
maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_inet6_aton>(thd, this); }
@@ -153,7 +156,7 @@ public:
virtual const char *func_name() const
{ return "inet6_ntoa"; }
- virtual void fix_length_and_dec()
+ virtual bool fix_length_and_dec()
{
decimals= 0;
@@ -163,6 +166,7 @@ public:
fix_length_and_charset(8 * 4 + 7, default_charset());
maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_inet6_ntoa>(thd, this); }
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index a45baec8e92..8d8a0d4e5db 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -388,11 +388,13 @@ longlong Item_func_json_valid::val_int()
}
-void Item_func_json_exists::fix_length_and_dec()
+bool Item_func_json_exists::fix_length_and_dec()
{
- Item_bool_func::fix_length_and_dec();
+ if (Item_bool_func::fix_length_and_dec())
+ return TRUE;
maybe_null= 1;
path.set_constant_flag(args[1]->const_item());
+ return FALSE;
}
@@ -439,12 +441,13 @@ err_return:
}
-void Item_func_json_value::fix_length_and_dec()
+bool Item_func_json_value::fix_length_and_dec()
{
collation.set(args[0]->collation);
max_length= args[0]->max_length;
path.set_constant_flag(args[1]->const_item());
maybe_null= 1;
+ return FALSE;
}
@@ -510,6 +513,10 @@ err_return:
bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
int *error)
{
+ CHARSET_INFO *json_cs;
+ const uchar *js;
+ uint js_len;
+
if (!json_value_scalar(je))
{
/* We only look for scalar values! */
@@ -518,7 +525,22 @@ bool Item_func_json_value::check_and_get_value(json_engine_t *je, String *res,
return true;
}
- return st_append_json(res, je->s.cs, je->value, je->value_len);
+ if (je->value_type == JSON_VALUE_TRUE ||
+ je->value_type == JSON_VALUE_FALSE)
+ {
+ json_cs= &my_charset_utf8mb4_bin;
+ js= (const uchar *) ((je->value_type == JSON_VALUE_TRUE) ? "1" : "0");
+ js_len= 1;
+ }
+ else
+ {
+ json_cs= je->s.cs;
+ js= je->value;
+ js_len= je->value_len;
+ }
+
+
+ return st_append_json(res, json_cs, js, js_len);
}
@@ -546,7 +568,7 @@ bool Item_func_json_query::check_and_get_value(json_engine_t *je, String *res,
}
-void Item_func_json_quote::fix_length_and_dec()
+bool Item_func_json_quote::fix_length_and_dec()
{
collation.set(&my_charset_utf8mb4_bin);
/*
@@ -554,6 +576,7 @@ void Item_func_json_quote::fix_length_and_dec()
of the argument turn into '\uXXXX\uXXXX', which is 12.
*/
max_length= args[0]->max_length * 12 + 2;
+ return FALSE;
}
@@ -581,12 +604,13 @@ String *Item_func_json_quote::val_str(String *str)
}
-void Item_func_json_unquote::fix_length_and_dec()
+bool Item_func_json_unquote::fix_length_and_dec()
{
collation.set(&my_charset_utf8_general_ci,
DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
max_length= args[0]->max_length;
maybe_null= 1;
+ return FALSE;
}
@@ -702,13 +726,14 @@ void Item_json_str_multipath::cleanup()
}
-void Item_func_json_extract::fix_length_and_dec()
+bool Item_func_json_extract::fix_length_and_dec()
{
collation.set(args[0]->collation);
max_length= args[0]->max_length * (arg_count - 1);
mark_constant_paths(paths, args+1, arg_count-1);
maybe_null= 1;
+ return FALSE;
}
@@ -937,14 +962,14 @@ double Item_func_json_extract::val_real()
}
-void Item_func_json_contains::fix_length_and_dec()
+bool Item_func_json_contains::fix_length_and_dec()
{
a2_constant= args[1]->const_item();
a2_parsed= FALSE;
maybe_null= 1;
if (arg_count > 2)
path.set_constant_flag(args[2]->const_item());
- Item_bool_func::fix_length_and_dec();
+ return Item_bool_func::fix_length_and_dec();
}
@@ -1190,13 +1215,13 @@ bool Item_func_json_contains_path::fix_fields(THD *thd, Item **ref)
}
-void Item_func_json_contains_path::fix_length_and_dec()
+bool Item_func_json_contains_path::fix_length_and_dec()
{
ooa_constant= args[1]->const_item();
ooa_parsed= FALSE;
maybe_null= 1;
mark_constant_paths(paths, args+2, arg_count-2);
- Item_bool_func::fix_length_and_dec();
+ return Item_bool_func::fix_length_and_dec();
}
@@ -1455,7 +1480,7 @@ append_null:
}
-void Item_func_json_array::fix_length_and_dec()
+bool Item_func_json_array::fix_length_and_dec()
{
ulonglong char_length= 2;
uint n_arg;
@@ -1468,17 +1493,18 @@ void Item_func_json_array::fix_length_and_dec()
DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
tmp_val.set_charset(&my_charset_utf8_general_ci);
max_length= 2;
- return;
+ return FALSE;
}
if (agg_arg_charsets_for_string_result(collation, args, arg_count))
- return;
+ return TRUE;
for (n_arg=0 ; n_arg < arg_count ; n_arg++)
char_length+= args[n_arg]->max_char_length() + 4;
fix_char_length_ulonglong(char_length);
tmp_val.set_charset(collation.collation);
+ return FALSE;
}
@@ -1522,7 +1548,7 @@ err_return:
}
-void Item_func_json_array_append::fix_length_and_dec()
+bool Item_func_json_array_append::fix_length_and_dec()
{
uint n_arg;
ulonglong char_length;
@@ -1537,6 +1563,7 @@ void Item_func_json_array_append::fix_length_and_dec()
}
fix_char_length_ulonglong(char_length);
+ return FALSE;
}
@@ -2124,12 +2151,13 @@ null_return:
}
-void Item_func_json_length::fix_length_and_dec()
+bool Item_func_json_length::fix_length_and_dec()
{
if (arg_count > 1)
path.set_constant_flag(args[1]->const_item());
maybe_null= 1;
max_length= 10;
+ return FALSE;
}
@@ -2269,11 +2297,12 @@ longlong Item_func_json_depth::val_int()
}
-void Item_func_json_type::fix_length_and_dec()
+bool Item_func_json_type::fix_length_and_dec()
{
collation.set(&my_charset_utf8_general_ci);
max_length= 12;
maybe_null= 1;
+ return FALSE;
}
@@ -2326,7 +2355,7 @@ error:
}
-void Item_func_json_insert::fix_length_and_dec()
+bool Item_func_json_insert::fix_length_and_dec()
{
uint n_arg;
ulonglong char_length;
@@ -2342,6 +2371,7 @@ void Item_func_json_insert::fix_length_and_dec()
fix_char_length_ulonglong(char_length);
maybe_null= 1;
+ return FALSE;
}
@@ -2586,13 +2616,14 @@ return_null:
}
-void Item_func_json_remove::fix_length_and_dec()
+bool Item_func_json_remove::fix_length_and_dec()
{
collation.set(args[0]->collation);
max_length= args[0]->max_length;
mark_constant_paths(paths, args+1, arg_count-1);
maybe_null= 1;
+ return FALSE;
}
@@ -2772,13 +2803,14 @@ null_return:
}
-void Item_func_json_keys::fix_length_and_dec()
+bool Item_func_json_keys::fix_length_and_dec()
{
collation.set(args[0]->collation);
max_length= args[0]->max_length;
maybe_null= 1;
if (arg_count > 1)
path.set_constant_flag(args[1]->const_item());
+ return FALSE;
}
@@ -2939,7 +2971,7 @@ bool Item_func_json_search::fix_fields(THD *thd, Item **ref)
static const uint SQR_MAX_BLOB_WIDTH= (uint) sqrt(MAX_BLOB_WIDTH);
-void Item_func_json_search::fix_length_and_dec()
+bool Item_func_json_search::fix_length_and_dec()
{
collation.set(args[0]->collation);
@@ -2961,6 +2993,7 @@ void Item_func_json_search::fix_length_and_dec()
if (arg_count > 4)
mark_constant_paths(paths, args+4, arg_count-4);
maybe_null= 1;
+ return FALSE;
}
@@ -3138,11 +3171,12 @@ const char *Item_func_json_format::func_name() const
}
-void Item_func_json_format::fix_length_and_dec()
+bool Item_func_json_format::fix_length_and_dec()
{
decimals= 0;
max_length= args[0]->max_length;
maybe_null= 1;
+ return FALSE;
}
@@ -3198,34 +3232,44 @@ String *Item_func_json_format::val_json(String *str)
int Arg_comparator::compare_json_str_basic(Item *j, Item *s)
{
- String *res1,*res2;
- json_value_types type;
- char *value;
- int value_len, c_len;
- Item_func_json_extract *e= (Item_func_json_extract *) j;
-
- if ((res1= e->read_json(&value1, &type, &value, &value_len)))
- {
- if ((res2= s->val_str(&value2)))
- {
- if (type == JSON_VALUE_STRING)
- {
- if (value1.realloc_with_extra_if_needed(value_len) ||
- (c_len= json_unescape(value1.charset(), (uchar *) value,
- (uchar *) value+value_len,
- &my_charset_utf8_general_ci,
- (uchar *) value1.ptr(),
- (uchar *) (value1.ptr() + value_len))) < 0)
- goto error;
- value1.length(c_len);
- res1= &value1;
- }
+ String *js,*str;
+ int c_len;
+ json_engine_t je;
- if (set_null)
- owner->null_value= 0;
- return sortcmp(res1, res2, compare_collation());
- }
+ if ((js= j->val_str(&value1)))
+ {
+ json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
+ (const uchar *) js->ptr()+js->length());
+ if (json_read_value(&je))
+ goto error;
+ if (je.value_type == JSON_VALUE_STRING)
+ {
+ if (value2.realloc_with_extra_if_needed(je.value_len) ||
+ (c_len= json_unescape(js->charset(), je.value,
+ je.value + je.value_len,
+ &my_charset_utf8_general_ci,
+ (uchar *) value2.ptr(),
+ (uchar *) (value2.ptr() + je.value_len))) < 0)
+ goto error;
+
+ value2.length(c_len);
+ js= &value2;
+ str= &value1;
+ }
+ else
+ {
+ str= &value2;
+ }
+
+
+ if ((str= s->val_str(str)))
+ {
+ if (set_null)
+ owner->null_value= 0;
+ return sortcmp(js, str, compare_collation());
+ }
}
+
error:
if (set_null)
owner->null_value= 1;
diff --git a/sql/item_jsonfunc.h b/sql/item_jsonfunc.h
index 354de69eee4..af0995b9605 100644
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@ -49,10 +49,12 @@ public:
Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {}
longlong val_int();
const char *func_name() const { return "json_valid"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_bool_func::fix_length_and_dec();
+ if (Item_bool_func::fix_length_and_dec())
+ return TRUE;
maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_valid>(thd, this); }
@@ -69,7 +71,7 @@ public:
Item_func_json_exists(THD *thd, Item *js, Item *i_path):
Item_bool_func(thd, js, i_path) {}
const char *func_name() const { return "json_exists"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_exists>(thd, this); }
longlong val_int();
@@ -86,7 +88,7 @@ public:
Item_func_json_value(THD *thd, Item *js, Item *i_path):
Item_str_func(thd, js, i_path) {}
const char *func_name() const { return "json_value"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
virtual bool check_and_get_value(json_engine_t *je, String *res, int *error);
Item *get_copy(THD *thd)
@@ -115,7 +117,7 @@ protected:
public:
Item_func_json_quote(THD *thd, Item *s): Item_str_func(thd, s) {}
const char *func_name() const { return "json_quote"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_quote>(thd, this); }
@@ -130,7 +132,7 @@ protected:
public:
Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
const char *func_name() const { return "json_unquote"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_unquote>(thd, this); }
@@ -163,7 +165,7 @@ public:
Item_json_str_multipath(thd, list) {}
const char *func_name() const { return "json_extract"; }
enum Functype functype() const { return JSON_EXTRACT_FUNC; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
longlong val_int();
double val_real();
@@ -185,7 +187,7 @@ public:
Item_func_json_contains(THD *thd, List<Item> &list):
Item_bool_func(thd, list) {}
const char *func_name() const { return "json_contains"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
longlong val_int();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_contains>(thd, this); }
@@ -207,7 +209,7 @@ public:
Item_bool_func(thd, list), tmp_paths(0) {}
const char *func_name() const { return "json_contains_path"; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void cleanup();
longlong val_int();
Item *get_copy(THD *thd)
@@ -227,7 +229,7 @@ public:
Item_str_func(thd, list) {}
String *val_str(String *);
bool is_json_type() { return true; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "json_array"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_array>(thd, this); }
@@ -242,7 +244,7 @@ protected:
public:
Item_func_json_array_append(THD *thd, List<Item> &list):
Item_json_str_multipath(thd, list) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count/2; }
const char *func_name() const { return "json_array_append"; }
@@ -309,7 +311,7 @@ public:
Item_func_json_length(THD *thd, List<Item> &list):
Item_long_func(thd, list) {}
const char *func_name() const { return "json_length"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
longlong val_int();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_length>(thd, this); }
@@ -325,7 +327,7 @@ protected:
public:
Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {}
const char *func_name() const { return "json_depth"; }
- void fix_length_and_dec() { max_length= 10; }
+ bool fix_length_and_dec() { max_length= 10; return FALSE; }
longlong val_int();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_depth>(thd, this); }
@@ -339,7 +341,7 @@ protected:
public:
Item_func_json_type(THD *thd, Item *js): Item_str_func(thd, js) {}
const char *func_name() const { return "json_type"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_type>(thd, this); }
@@ -356,7 +358,7 @@ public:
Item_func_json_insert(bool i_mode, bool r_mode, THD *thd, List<Item> &list):
Item_json_str_multipath(thd, list),
mode_insert(i_mode), mode_replace(r_mode) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count/2; }
const char *func_name() const
@@ -376,7 +378,7 @@ protected:
public:
Item_func_json_remove(THD *thd, List<Item> &list):
Item_json_str_multipath(thd, list) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count - 1; }
const char *func_name() const { return "json_remove"; }
@@ -395,7 +397,7 @@ public:
Item_func_json_keys(THD *thd, List<Item> &list):
Item_str_func(thd, list) {}
const char *func_name() const { return "json_keys"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_json_keys>(thd, this); }
@@ -419,7 +421,7 @@ public:
Item_json_str_multipath(thd, list) {}
const char *func_name() const { return "json_search"; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count > 4 ? arg_count - 4 : 0; }
Item *get_copy(THD *thd)
@@ -447,7 +449,7 @@ public:
Item_str_func(thd, list), fmt(DETAILED) {}
const char *func_name() const;
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *str);
String *val_json(String *str);
bool is_json_type() { return true; }
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 6af49d494d4..c914c6cbdf8 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -188,10 +188,11 @@ String *Item_func_sha::val_str_ascii(String *str)
return 0;
}
-void Item_func_sha::fix_length_and_dec()
+bool Item_func_sha::fix_length_and_dec()
{
// size of hex representation of hash
fix_length_and_charset(MY_SHA1_HASH_SIZE * 2, default_charset());
+ return FALSE;
}
String *Item_func_sha2::val_str_ascii(String *str)
@@ -267,7 +268,7 @@ String *Item_func_sha2::val_str_ascii(String *str)
}
-void Item_func_sha2::fix_length_and_dec()
+bool Item_func_sha2::fix_length_and_dec()
{
maybe_null= 1;
max_length = 0;
@@ -292,6 +293,7 @@ void Item_func_sha2::fix_length_and_dec()
ER_THD(thd, ER_WRONG_PARAMETERS_TO_NATIVE_FCT),
"sha2");
}
+ return FALSE;
}
/* Implementation of AES encryption routines */
@@ -344,23 +346,25 @@ String *Item_aes_crypt::val_str(String *str2)
return 0;
}
-void Item_func_aes_encrypt::fix_length_and_dec()
+bool Item_func_aes_encrypt::fix_length_and_dec()
{
max_length=my_aes_get_size(MY_AES_ECB, args[0]->max_length);
what= ENCRYPTION_FLAG_ENCRYPT;
+ return FALSE;
}
-void Item_func_aes_decrypt::fix_length_and_dec()
+bool Item_func_aes_decrypt::fix_length_and_dec()
{
max_length=args[0]->max_length;
maybe_null= 1;
what= ENCRYPTION_FLAG_DECRYPT;
+ return FALSE;
}
-void Item_func_to_base64::fix_length_and_dec()
+bool Item_func_to_base64::fix_length_and_dec()
{
maybe_null= args[0]->maybe_null;
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
@@ -375,6 +379,7 @@ void Item_func_to_base64::fix_length_and_dec()
DBUG_ASSERT(length > 0);
fix_char_length_ulonglong((ulonglong) length - 1);
}
+ return FALSE;
}
@@ -410,7 +415,7 @@ String *Item_func_to_base64::val_str_ascii(String *str)
}
-void Item_func_from_base64::fix_length_and_dec()
+bool Item_func_from_base64::fix_length_and_dec()
{
if (args[0]->max_length > (uint) my_base64_decode_max_arg_length())
{
@@ -422,6 +427,7 @@ void Item_func_from_base64::fix_length_and_dec()
fix_char_length_ulonglong((ulonglong) length);
}
maybe_null= 1; // Can be NULL, e.g. in case of badly formed input string
+ return FALSE;
}
@@ -670,17 +676,18 @@ bool Item_func_concat::append_value(THD *thd, String *res, const String *app)
}
-void Item_func_concat::fix_length_and_dec()
+bool Item_func_concat::fix_length_and_dec()
{
ulonglong char_length= 0;
if (agg_arg_charsets_for_string_result(collation, args, arg_count))
- return;
+ return TRUE;
for (uint i=0 ; i < arg_count ; i++)
char_length+= args[i]->max_char_length();
fix_char_length_ulonglong(char_length);
+ return FALSE;
}
/**
@@ -1032,12 +1039,12 @@ null:
}
-void Item_func_concat_ws::fix_length_and_dec()
+bool Item_func_concat_ws::fix_length_and_dec()
{
ulonglong char_length;
if (agg_arg_charsets_for_string_result(collation, args, arg_count))
- return;
+ return TRUE;
/*
arg_count cannot be less than 2,
@@ -1049,6 +1056,7 @@ void Item_func_concat_ws::fix_length_and_dec()
char_length+= args[i]->max_char_length();
fix_char_length_ulonglong(char_length);
+ return FALSE;
}
@@ -1102,11 +1110,13 @@ String *Item_func_reverse::val_str(String *str)
}
-void Item_func_reverse::fix_length_and_dec()
+bool Item_func_reverse::fix_length_and_dec()
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
fix_char_length(args[0]->max_char_length());
+ return FALSE;
}
/**
@@ -1259,7 +1269,7 @@ null:
}
-void Item_func_replace::fix_length_and_dec()
+bool Item_func_replace::fix_length_and_dec()
{
ulonglong char_length= (ulonglong) args[0]->max_char_length();
int diff=(int) (args[2]->max_char_length() - args[1]->max_char_length());
@@ -1270,8 +1280,9 @@ void Item_func_replace::fix_length_and_dec()
}
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3))
- return;
+ return TRUE;
fix_char_length_ulonglong(char_length);
+ return FALSE;
}
@@ -1283,13 +1294,14 @@ bool Item_func_regexp_replace::fix_fields(THD *thd, Item **ref)
}
-void Item_func_regexp_replace::fix_length_and_dec()
+bool Item_func_regexp_replace::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3))
- return;
+ return TRUE;
max_length= MAX_BLOB_WIDTH;
re.init(collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
+ return FALSE;
}
@@ -1425,13 +1437,14 @@ bool Item_func_regexp_substr::fix_fields(THD *thd, Item **ref)
}
-void Item_func_regexp_substr::fix_length_and_dec()
+bool Item_func_regexp_substr::fix_length_and_dec()
{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2))
- return;
+ return TRUE;
fix_char_length(args[0]->max_char_length());
re.init(collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
+ return FALSE;
}
@@ -1539,16 +1552,17 @@ null:
}
-void Item_func_insert::fix_length_and_dec()
+bool Item_func_insert::fix_length_and_dec()
{
ulonglong char_length;
// Handle character set for args[0] and args[3].
if (agg_arg_charsets_for_string_result(collation, args, 2, 3))
- return;
+ return TRUE;
char_length= ((ulonglong) args[0]->max_char_length() +
(ulonglong) args[3]->max_char_length());
fix_char_length_ulonglong(char_length);
+ return FALSE;
}
@@ -1585,22 +1599,26 @@ String *Item_str_conv::val_str(String *str)
}
-void Item_func_lcase::fix_length_and_dec()
+bool Item_func_lcase::fix_length_and_dec()
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
multiply= collation.collation->casedn_multiply;
converter= collation.collation->cset->casedn;
fix_char_length_ulonglong((ulonglong) args[0]->max_char_length() * multiply);
+ return FALSE;
}
-void Item_func_ucase::fix_length_and_dec()
+bool Item_func_ucase::fix_length_and_dec()
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
multiply= collation.collation->caseup_multiply;
converter= collation.collation->cset->caseup;
fix_char_length_ulonglong((ulonglong) args[0]->max_char_length() * multiply);
+ return FALSE;
}
@@ -1643,11 +1661,13 @@ void Item_str_func::left_right_max_length()
}
-void Item_func_left::fix_length_and_dec()
+bool Item_func_left::fix_length_and_dec()
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
left_right_max_length();
+ return FALSE;
}
@@ -1677,11 +1697,13 @@ String *Item_func_right::val_str(String *str)
}
-void Item_func_right::fix_length_and_dec()
+bool Item_func_right::fix_length_and_dec()
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
left_right_max_length();
+ return FALSE;
}
@@ -1732,11 +1754,12 @@ String *Item_func_substr::val_str(String *str)
}
-void Item_func_substr::fix_length_and_dec()
+bool Item_func_substr::fix_length_and_dec()
{
max_length=args[0]->max_length;
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
if (args[1]->const_item())
{
@@ -1757,14 +1780,16 @@ void Item_func_substr::fix_length_and_dec()
set_if_smaller(max_length,(uint) length);
}
max_length*= collation.collation->mbmaxlen;
+ return FALSE;
}
-void Item_func_substr_index::fix_length_and_dec()
-{
+bool Item_func_substr_index::fix_length_and_dec()
+{
if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2))
- return;
+ return TRUE;
fix_char_length(args[0]->max_char_length());
+ return FALSE;
}
@@ -2088,11 +2113,12 @@ String *Item_func_trim::val_str(String *str)
return trimmed_value(res, (uint32) (ptr - res->ptr()), (uint32) (end - ptr));
}
-void Item_func_trim::fix_length_and_dec()
+bool Item_func_trim::fix_length_and_dec()
{
if (arg_count == 1)
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
remove.set_charset(collation.collation);
remove.set_ascii(" ",1);
@@ -2103,9 +2129,10 @@ void Item_func_trim::fix_length_and_dec()
// Note that we pass args[1] as the first item, and args[0] as the second.
if (agg_arg_charsets_for_string_result_with_comparison(collation,
&args[1], 2, -1))
- return;
+ return TRUE;
}
fix_char_length(args[0]->max_char_length());
+ return FALSE;
}
void Item_func_trim::print(String *str, enum_query_type query_type)
@@ -2245,7 +2272,7 @@ bool Item_func_encode::seed()
return FALSE;
}
-void Item_func_encode::fix_length_and_dec()
+bool Item_func_encode::fix_length_and_dec()
{
max_length=args[0]->max_length;
maybe_null=args[0]->maybe_null || args[1]->maybe_null;
@@ -2253,6 +2280,7 @@ void Item_func_encode::fix_length_and_dec()
/* Precompute the seed state if the item is constant. */
seeded= args[1]->const_item() &&
(args[1]->result_type() == STRING_RESULT) && !seed();
+ return FALSE;
}
String *Item_func_encode::val_str(String *str)
@@ -2417,13 +2445,15 @@ bool Item_func_current_role::fix_fields(THD *thd, Item **ref)
return 0;
}
-void Item_func_soundex::fix_length_and_dec()
+bool Item_func_soundex::fix_length_and_dec()
{
uint32 char_length= args[0]->max_char_length();
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
set_if_bigger(char_length, 4);
fix_char_length(char_length);
+ return FALSE;
}
@@ -2581,7 +2611,7 @@ String *Item_func_soundex::val_str(String *str)
const int FORMAT_MAX_DECIMALS= 30;
-void Item_func_format::fix_length_and_dec()
+bool Item_func_format::fix_length_and_dec()
{
uint32 char_length= args[0]->max_char_length();
uint32 max_sep_count= (char_length / 3) + (decimals ? 1 : 0) + /*sign*/1;
@@ -2591,6 +2621,7 @@ void Item_func_format::fix_length_and_dec()
locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL;
else
locale= &my_locale_en_US; /* Two arguments */
+ return FALSE;
}
@@ -2704,13 +2735,13 @@ String *Item_func_format::val_str_ascii(String *str)
}
-void Item_func_elt::fix_length_and_dec()
+bool Item_func_elt::fix_length_and_dec()
{
uint32 char_length= 0;
decimals=0;
if (agg_arg_charsets_for_string_result(collation, args + 1, arg_count - 1))
- return;
+ return TRUE;
for (uint i= 1 ; i < arg_count ; i++)
{
@@ -2719,6 +2750,7 @@ void Item_func_elt::fix_length_and_dec()
}
fix_char_length(char_length);
maybe_null=1; // NULL if wrong first arg
+ return FALSE;
}
@@ -2765,16 +2797,17 @@ String *Item_func_elt::val_str(String *str)
}
-void Item_func_make_set::fix_length_and_dec()
+bool Item_func_make_set::fix_length_and_dec()
{
uint32 char_length= arg_count - 2; /* Separators */
if (agg_arg_charsets_for_string_result(collation, args + 1, arg_count - 1))
- return;
+ return TRUE;
for (uint i=1 ; i < arg_count ; i++)
char_length+= args[i]->max_char_length();
fix_char_length(char_length);
+ return FALSE;
}
@@ -2927,9 +2960,10 @@ inline String* alloc_buffer(String *res,String *str,String *tmp_value,
}
-void Item_func_repeat::fix_length_and_dec()
+bool Item_func_repeat::fix_length_and_dec()
{
- agg_arg_charsets_for_string_result(collation, args, 1);
+ if (agg_arg_charsets_for_string_result(collation, args, 1))
+ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
if (args[1]->const_item())
{
@@ -2951,6 +2985,7 @@ void Item_func_repeat::fix_length_and_dec()
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
}
+ return FALSE;
}
/**
@@ -3012,7 +3047,7 @@ err:
}
-void Item_func_space::fix_length_and_dec()
+bool Item_func_space::fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
if (args[0]->const_item())
@@ -3028,12 +3063,13 @@ void Item_func_space::fix_length_and_dec()
if (count > INT_MAX32)
count= INT_MAX32;
fix_char_length_ulonglong(count);
- return;
+ return FALSE;
}
end:
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
+ return FALSE;
}
@@ -3083,11 +3119,12 @@ err:
}
-void Item_func_binlog_gtid_pos::fix_length_and_dec()
+bool Item_func_binlog_gtid_pos::fix_length_and_dec()
{
collation.set(system_charset_info);
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
+ return FALSE;
}
@@ -3123,18 +3160,18 @@ err:
}
-void Item_func_pad::fix_length_and_dec()
+bool Item_func_pad::fix_length_and_dec()
{
if (arg_count == 3)
{
// Handle character set for args[0] and args[2].
if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2))
- return;
+ return TRUE;
}
else
{
if (agg_arg_charsets_for_string_result(collation, &args[0], 1, 1))
- return;
+ return TRUE;
pad_str.set_charset(collation.collation);
pad_str.length(0);
pad_str.append(" ", 1);
@@ -3157,6 +3194,7 @@ void Item_func_pad::fix_length_and_dec()
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
}
+ return FALSE;
}
@@ -3411,10 +3449,11 @@ String *Item_func_conv_charset::val_str(String *str)
0 : str;
}
-void Item_func_conv_charset::fix_length_and_dec()
+bool Item_func_conv_charset::fix_length_and_dec()
{
DBUG_ASSERT(collation.derivation == DERIVATION_IMPLICIT);
fix_char_length(args[0]->max_char_length());
+ return FALSE;
}
void Item_func_conv_charset::print(String *str, enum_query_type query_type)
@@ -3436,17 +3475,18 @@ String *Item_func_set_collation::val_str(String *str)
return str;
}
-void Item_func_set_collation::fix_length_and_dec()
+bool Item_func_set_collation::fix_length_and_dec()
{
if (!my_charset_same(args[0]->collation.collation, m_set_collation))
{
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
m_set_collation->name, args[0]->collation.collation->csname);
- return;
+ return TRUE;
}
collation.set(m_set_collation, DERIVATION_EXPLICIT,
args[0]->collation.repertoire);
max_length= args[0]->max_length;
+ return FALSE;
}
@@ -3489,7 +3529,7 @@ String *Item_func_collation::val_str(String *str)
}
-void Item_func_weight_string::fix_length_and_dec()
+bool Item_func_weight_string::fix_length_and_dec()
{
CHARSET_INFO *cs= args[0]->collation.collation;
collation.set(&my_charset_bin, args[0]->collation.derivation);
@@ -3507,6 +3547,7 @@ void Item_func_weight_string::fix_length_and_dec()
max_length= (uint32)cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen);
}
maybe_null= 1;
+ return FALSE;
}
@@ -3878,15 +3919,16 @@ String* Item_func_export_set::val_str(String* str)
return str;
}
-void Item_func_export_set::fix_length_and_dec()
+bool Item_func_export_set::fix_length_and_dec()
{
uint32 length= MY_MAX(args[1]->max_char_length(), args[2]->max_char_length());
uint32 sep_length= (arg_count > 3 ? args[3]->max_char_length() : 1);
if (agg_arg_charsets_for_string_result(collation,
args + 1, MY_MIN(4, arg_count) - 1))
- return;
+ return TRUE;
fix_char_length(length * 64 + sep_length * 63);
+ return FALSE;
}
@@ -4286,12 +4328,13 @@ bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref)
}
-void Item_func_dyncol_create::fix_length_and_dec()
+bool Item_func_dyncol_create::fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
maybe_null= TRUE;
collation.set(&my_charset_bin);
decimals= 0;
+ return FALSE;
}
bool Item_func_dyncol_create::prepare_arguments(THD *thd, bool force_names_arg)
@@ -5211,10 +5254,11 @@ Item_temptable_rowid::Item_temptable_rowid(TABLE *table_arg)
max_length= table->file->ref_length;
}
-void Item_temptable_rowid::fix_length_and_dec()
+bool Item_temptable_rowid::fix_length_and_dec()
{
used_tables_cache= table->map;
const_item_cache= false;
+ return FALSE;
}
String *Item_temptable_rowid::val_str(String *str)
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index eb084c3f58d..29af0b43d9d 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -144,9 +144,10 @@ class Item_func_md5 :public Item_str_ascii_checksum_func
public:
Item_func_md5(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {}
String *val_str_ascii(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_length_and_charset(32, default_charset());
+ return FALSE;
}
const char *func_name() const { return "md5"; }
Item *get_copy(THD *thd)
@@ -159,7 +160,7 @@ class Item_func_sha :public Item_str_ascii_checksum_func
public:
Item_func_sha(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "sha"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_sha>(thd, this); }
@@ -171,7 +172,7 @@ public:
Item_func_sha2(THD *thd, Item *a, Item *b)
:Item_str_ascii_checksum_func(thd, a, b) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "sha2"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_sha2>(thd, this); }
@@ -184,7 +185,7 @@ public:
Item_func_to_base64(THD *thd, Item *a)
:Item_str_ascii_checksum_func(thd, a) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "to_base64"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_to_base64>(thd, this); }
@@ -197,7 +198,7 @@ public:
Item_func_from_base64(THD *thd, Item *a)
:Item_str_binary_checksum_func(thd, a) { }
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "from_base64"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_from_base64>(thd, this); }
@@ -224,7 +225,7 @@ class Item_func_aes_encrypt :public Item_aes_crypt
public:
Item_func_aes_encrypt(THD *thd, Item *a, Item *b)
:Item_aes_crypt(thd, a, b) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "aes_encrypt"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_aes_encrypt>(thd, this); }
@@ -235,7 +236,7 @@ class Item_func_aes_decrypt :public Item_aes_crypt
public:
Item_func_aes_decrypt(THD *thd, Item *a, Item *b):
Item_aes_crypt(thd, a, b) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "aes_decrypt"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_aes_decrypt>(thd, this); }
@@ -259,7 +260,7 @@ public:
Item_func_concat(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "concat"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_concat>(thd, this); }
@@ -294,11 +295,12 @@ public:
Item_func_decode_histogram(THD *thd, Item *a, Item *b):
Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(system_charset_info);
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
+ return FALSE;
}
const char *func_name() const { return "decode_histogram"; }
Item *get_copy(THD *thd)
@@ -311,7 +313,7 @@ class Item_func_concat_ws :public Item_str_func
public:
Item_func_concat_ws(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "concat_ws"; }
table_map not_null_tables() const { return 0; }
Item *get_copy(THD *thd)
@@ -324,7 +326,7 @@ class Item_func_reverse :public Item_str_func
public:
Item_func_reverse(THD *thd, Item *a): Item_str_func(thd, a) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "reverse"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_reverse>(thd, this); }
@@ -338,7 +340,7 @@ public:
Item_func_replace(THD *thd, Item *org, Item *find, Item *replace):
Item_str_func(thd, org, find, replace) {}
String *val_str(String *to) { return val_str_internal(to, NULL); };
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str_internal(String *str, String *empty_string_for_null);
const char *func_name() const { return "replace"; }
Item *get_copy(THD *thd)
@@ -378,7 +380,7 @@ public:
}
String *val_str(String *str);
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp_replace"; }
Item *get_copy(THD *thd) { return 0;}
};
@@ -400,7 +402,7 @@ public:
}
String *val_str(String *str);
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp_substr"; }
Item *get_copy(THD *thd) { return 0; }
};
@@ -414,7 +416,7 @@ public:
Item *new_str):
Item_str_func(thd, org, start, length, new_str) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "insert"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_insert>(thd, this); }
@@ -438,7 +440,7 @@ class Item_func_lcase :public Item_str_conv
public:
Item_func_lcase(THD *thd, Item *item): Item_str_conv(thd, item) {}
const char *func_name() const { return "lcase"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_lcase>(thd, this); }
};
@@ -448,7 +450,7 @@ class Item_func_ucase :public Item_str_conv
public:
Item_func_ucase(THD *thd, Item *item): Item_str_conv(thd, item) {}
const char *func_name() const { return "ucase"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_ucase>(thd, this); }
};
@@ -460,7 +462,7 @@ class Item_func_left :public Item_str_func
public:
Item_func_left(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "left"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_left>(thd, this); }
@@ -473,7 +475,7 @@ class Item_func_right :public Item_str_func
public:
Item_func_right(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "right"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_right>(thd, this); }
@@ -490,7 +492,7 @@ public:
Item_func_substr(THD *thd, Item *a, Item *b, Item *c):
Item_str_func(thd, a, b, c) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "substr"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_substr>(thd, this); }
@@ -508,10 +510,11 @@ public:
Item_func_substr(thd, a, b) {}
Item_func_substr_oracle(THD *thd, Item *a, Item *b, Item *c):
Item_func_substr(thd, a, b, c) {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_substr::fix_length_and_dec();
+ bool res= Item_func_substr::fix_length_and_dec();
maybe_null= true;
+ return res;
}
const char *func_name() const { return "substr_oracle"; }
Item *get_copy(THD *thd)
@@ -525,7 +528,7 @@ public:
Item_func_substr_index(THD *thd, Item *a,Item *b,Item *c):
Item_str_func(thd, a, b, c) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "substring_index"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_substr_index>(thd, this); }
@@ -561,7 +564,7 @@ public:
Item_func_trim(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
Item_func_trim(THD *thd, Item *a): Item_str_func(thd, a) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "trim"; }
void print(String *str, enum_query_type query_type);
virtual const char *mode_name() const { return "both"; }
@@ -581,10 +584,11 @@ public:
Item_func_trim(thd, a, b) {}
Item_func_trim_oracle(THD *thd, Item *a): Item_func_trim(thd, a) {}
const char *func_name() const { return "trim_oracle"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_trim::fix_length_and_dec();
+ bool res= Item_func_trim::fix_length_and_dec();
maybe_null= true;
+ return res;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_trim_oracle>(thd, this); }
@@ -615,10 +619,11 @@ public:
Item_func_ltrim(thd, a, b) {}
Item_func_ltrim_oracle(THD *thd, Item *a): Item_func_ltrim(thd, a) {}
const char *func_name() const { return "ltrim_oracle"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_ltrim::fix_length_and_dec();
+ bool res= Item_func_ltrim::fix_length_and_dec();
maybe_null= true;
+ return res;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_ltrim_oracle>(thd, this); }
@@ -649,10 +654,11 @@ public:
Item_func_rtrim(thd, a, b) {}
Item_func_rtrim_oracle(THD *thd, Item *a): Item_func_rtrim(thd, a) {}
const char *func_name() const { return "rtrim_oracle"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_rtrim::fix_length_and_dec();
+ bool res= Item_func_rtrim::fix_length_and_dec();
maybe_null= true;
+ return res;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_rtrim_oracle>(thd, this); }
@@ -681,12 +687,13 @@ public:
Item_str_ascii_checksum_func(thd, a), alg(al), deflt(0) {}
String *val_str_ascii(String *str);
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_length_and_charset((alg == 1 ?
SCRAMBLED_PASSWORD_CHAR_LENGTH :
SCRAMBLED_PASSWORD_CHAR_LENGTH_323),
default_charset());
+ return FALSE;
}
const char *func_name() const { return ((deflt || alg == 1) ?
"password" : "old_password"); }
@@ -707,11 +714,12 @@ public:
Item_func_des_encrypt(THD *thd, Item *a, Item *b)
:Item_str_binary_checksum_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
maybe_null=1;
/* 9 = MAX ((8- (arg_len % 8)) + 1) */
max_length = args[0]->max_length + 9;
+ return FALSE;
}
const char *func_name() const { return "des_encrypt"; }
Item *get_copy(THD *thd)
@@ -727,13 +735,14 @@ public:
Item_func_des_decrypt(THD *thd, Item *a, Item *b)
:Item_str_binary_checksum_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
maybe_null=1;
/* 9 = MAX ((8- (arg_len % 8)) + 1) */
max_length= args[0]->max_length;
if (max_length >= 9U)
max_length-= 9U;
+ return FALSE;
}
const char *func_name() const { return "des_decrypt"; }
Item *get_copy(THD *thd)
@@ -766,7 +775,7 @@ public:
constructor_helper();
}
String *val_str(String *);
- void fix_length_and_dec() { maybe_null=1; max_length = 13; }
+ bool fix_length_and_dec() { maybe_null=1; max_length = 13; return FALSE; }
const char *func_name() const { return "encrypt"; }
bool check_vcol_func_processor(void *arg)
{
@@ -790,7 +799,7 @@ public:
Item_func_encode(THD *thd, Item *a, Item *seed_arg):
Item_str_binary_checksum_func(thd, a, seed_arg) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "encode"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_encode>(thd, this); }
@@ -840,10 +849,11 @@ class Item_func_database :public Item_func_sysconst
public:
Item_func_database(THD *thd): Item_func_sysconst(thd) {}
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= MAX_FIELD_NAME * system_charset_info->mbmaxlen;
maybe_null=1;
+ return FALSE;
}
const char *func_name() const { return "database"; }
const char *fully_qualified_func_name() const { return "database()"; }
@@ -863,10 +873,11 @@ public:
{
str->append(func_name());
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= 512 * system_charset_info->mbmaxlen;
null_value= maybe_null= false;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_sqlerrm>(thd, this); }
@@ -889,10 +900,11 @@ public:
return (null_value ? 0 : &str_value);
}
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= (uint32) (username_char_length +
HOSTNAME_LENGTH + 1) * SYSTEM_CHARSET_MBMAXLEN;
+ return FALSE;
}
const char *func_name() const { return "user"; }
const char *fully_qualified_func_name() const { return "user()"; }
@@ -932,8 +944,11 @@ public:
Item_func_current_role(THD *thd, Name_resolution_context *context_arg):
Item_func_sysconst(thd), context(context_arg) {}
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec()
- { max_length= (uint32) username_char_length * SYSTEM_CHARSET_MBMAXLEN; }
+ bool fix_length_and_dec()
+ {
+ max_length= (uint32) username_char_length * SYSTEM_CHARSET_MBMAXLEN;
+ return FALSE;
+ }
int save_in_field(Field *field, bool no_conversions)
{ return save_str_value_in_field(field, &str_value); }
const char *func_name() const { return "current_role"; }
@@ -961,7 +976,7 @@ class Item_func_soundex :public Item_str_func
public:
Item_func_soundex(THD *thd, Item *a): Item_str_func(thd, a) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "soundex"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_soundex>(thd, this); }
@@ -975,7 +990,7 @@ public:
double val_real();
longlong val_int();
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "elt"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_elt>(thd, this); }
@@ -989,7 +1004,7 @@ class Item_func_make_set :public Item_str_func
public:
Item_func_make_set(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "make_set"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_make_set>(thd, this); }
@@ -1006,7 +1021,7 @@ public:
Item_str_ascii_func(thd, org, dec, lang) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "format"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_format>(thd, this); }
@@ -1026,9 +1041,10 @@ public:
{ collation.set(cs); }
String *val_str(String *);
void append_char(String * str, int32 num);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= arg_count * 4;
+ return FALSE;
}
const char *func_name() const { return "char"; }
void print(String *str, enum_query_type query_type);
@@ -1042,9 +1058,10 @@ public:
Item_func_chr(THD *thd, Item *arg1, CHARSET_INFO *cs):
Item_func_char(thd, arg1, cs) {}
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= 4;
+ return FALSE;
}
const char *func_name() const { return "chr"; }
Item *get_copy(THD *thd)
@@ -1058,7 +1075,7 @@ public:
Item_func_repeat(THD *thd, Item *arg1, Item *arg2):
Item_str_func(thd, arg1, arg2) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "repeat"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_repeat>(thd, this); }
@@ -1070,7 +1087,7 @@ class Item_func_space :public Item_str_func
public:
Item_func_space(THD *thd, Item *arg1): Item_str_func(thd, arg1) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "space"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_space>(thd, this); }
@@ -1083,7 +1100,7 @@ public:
Item_func_binlog_gtid_pos(THD *thd, Item *arg1, Item *arg2):
Item_str_func(thd, arg1, arg2) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "binlog_gtid_pos"; }
bool check_vcol_func_processor(void *arg)
{
@@ -1103,7 +1120,7 @@ public:
Item_str_func(thd, arg1, arg2, arg3) {}
Item_func_pad(THD *thd, Item *arg1, Item *arg2):
Item_str_func(thd, arg1, arg2) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
};
@@ -1130,10 +1147,11 @@ public:
Item_func_rpad(thd, arg1, arg2, arg3) {}
Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2):
Item_func_rpad(thd, arg1, arg2) {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_rpad::fix_length_and_dec();
+ bool res= Item_func_rpad::fix_length_and_dec();
maybe_null= true;
+ return res;
}
const char *func_name() const { return "rpad_oracle"; }
Item *get_copy(THD *thd)
@@ -1164,10 +1182,11 @@ public:
Item_func_lpad(thd, arg1, arg2, arg3) {}
Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2):
Item_func_lpad(thd, arg1, arg2) {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_lpad::fix_length_and_dec();
+ bool res= Item_func_lpad::fix_length_and_dec();
maybe_null= true;
+ return res;
}
const char *func_name() const { return "lpad_oracle"; }
Item *get_copy(THD *thd)
@@ -1182,11 +1201,12 @@ public:
Item_str_func(thd, a, b, c) {}
const char *func_name() const { return "conv"; }
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(default_charset());
max_length=64;
maybe_null= 1;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_conv>(thd, this); }
@@ -1216,12 +1236,13 @@ public:
DBUG_ASSERT(fixed);
return m_arg0_type_handler->Item_func_hex_val_str_ascii(this, str);
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
decimals=0;
fix_char_length(args[0]->max_length * 2);
m_arg0_type_handler= args[0]->type_handler();
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_hex>(thd, this); }
@@ -1238,11 +1259,12 @@ public:
}
const char *func_name() const { return "unhex"; }
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
max_length=(1+args[0]->max_length)/2;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_unhex>(thd, this); }
@@ -1261,11 +1283,12 @@ public:
Item_str_func(thd, a, b), is_min(is_min_arg)
{ maybe_null= 1; }
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(args[0]->collation);
decimals=0;
max_length= MAX_BLOB_WIDTH;
+ return FALSE;
}
};
@@ -1306,10 +1329,11 @@ public:
tmp->set_charset(&my_charset_bin);
return tmp;
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(&my_charset_bin);
max_length=args[0]->max_length;
+ return FALSE;
}
void print(String *str, enum_query_type query_type);
const char *func_name() const { return "cast_as_binary"; }
@@ -1326,11 +1350,12 @@ public:
Item_load_file(THD *thd, Item *a): Item_str_func(thd, a) {}
String *val_str(String *);
const char *func_name() const { return "load_file"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(&my_charset_bin, DERIVATION_COERCIBLE);
maybe_null=1;
max_length=MAX_BLOB_WIDTH;
+ return FALSE;
}
bool check_vcol_func_processor(void *arg)
{
@@ -1351,7 +1376,7 @@ class Item_func_export_set: public Item_str_func
Item_func_export_set(THD *thd, Item *a, Item *b, Item* c, Item* d, Item* e):
Item_str_func(thd, a, b, c, d, e) {}
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "export_set"; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_export_set>(thd, this); }
@@ -1365,12 +1390,13 @@ public:
Item_func_quote(THD *thd, Item *a): Item_str_func(thd, a) {}
const char *func_name() const { return "quote"; }
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(args[0]->collation);
ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 +
2 * collation.collation->mbmaxlen;
max_length= (uint32) MY_MIN(max_result_length, MAX_BLOB_WIDTH);
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_quote>(thd, this); }
@@ -1453,7 +1479,7 @@ public:
return 1;
return res;
}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "convert"; }
void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd)
@@ -1467,7 +1493,7 @@ public:
Item_func_set_collation(THD *thd, Item *a, CHARSET_INFO *set_collation):
Item_str_func(thd, a), m_set_collation(set_collation) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "collate"; }
enum precedence precedence() const { return COLLATE_PRECEDENCE; }
@@ -1488,11 +1514,12 @@ class Item_func_expr_str_metadata :public Item_str_func
{
public:
Item_func_expr_str_metadata(THD *thd, Item *a): Item_str_func(thd, a) { }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(system_charset_info);
max_length= 64 * collation.collation->mbmaxlen; // should be enough
maybe_null= 0;
+ return FALSE;
};
table_map not_null_tables() const { return 0; }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
@@ -1542,7 +1569,7 @@ public:
}
const char *func_name() const { return "weight_string"; }
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const
{
if (!Item_str_func::eq(item, binary_cmp))
@@ -1568,7 +1595,7 @@ public:
Item_func_crc32(THD *thd, Item *a): Item_long_func(thd, a)
{ unsigned_flag= 1; }
const char *func_name() const { return "crc32"; }
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
longlong val_int();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_crc32>(thd, this); }
@@ -1581,7 +1608,7 @@ public:
Item_func_uncompressed_length(THD *thd, Item *a)
:Item_long_func_length(thd, a) {}
const char *func_name() const{return "uncompressed_length";}
- void fix_length_and_dec() { max_length=10; maybe_null= true; }
+ bool fix_length_and_dec() { max_length=10; maybe_null= true; return FALSE; }
longlong val_int();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_uncompressed_length>(thd, this); }
@@ -1599,7 +1626,11 @@ class Item_func_compress: public Item_str_binary_checksum_func
public:
Item_func_compress(THD *thd, Item *a)
:Item_str_binary_checksum_func(thd, a) {}
- void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
+ bool fix_length_and_dec()
+ {
+ max_length= (args[0]->max_length * 120) / 100 + 12;
+ return FALSE;
+ }
const char *func_name() const{return "compress";}
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
Item *get_copy(THD *thd)
@@ -1612,7 +1643,11 @@ class Item_func_uncompress: public Item_str_binary_checksum_func
public:
Item_func_uncompress(THD *thd, Item *a)
:Item_str_binary_checksum_func(thd, a) {}
- void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; }
+ bool fix_length_and_dec()
+ {
+ maybe_null= 1; max_length= MAX_BLOB_WIDTH;
+ return FALSE;
+ }
const char *func_name() const{return "uncompress";}
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
Item *get_copy(THD *thd)
@@ -1624,11 +1659,12 @@ class Item_func_uuid: public Item_str_func
{
public:
Item_func_uuid(THD *thd): Item_str_func(thd) {}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation.set(system_charset_info,
DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
fix_char_length(MY_UUID_STRING_LENGTH);
+ return FALSE;
}
bool const_item() const { return false; }
table_map used_tables() const { return RAND_TABLE_BIT; }
@@ -1656,7 +1692,7 @@ protected:
public:
Item_func_dyncol_create(THD *thd, List<Item> &args, DYNCALL_CREATE_DEF *dfs);
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const{ return "column_create"; }
String *val_str(String *);
void print(String *str, enum_query_type query_type);
@@ -1686,11 +1722,12 @@ public:
{collation.set(DYNCOL_UTF);}
const char *func_name() const{ return "column_json"; }
String *val_str(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
decimals= 0;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_dyncol_json>(thd, this); }
@@ -1705,8 +1742,8 @@ class Item_dyncol_get: public Item_str_func
public:
Item_dyncol_get(THD *thd, Item *str, Item *num): Item_str_func(thd, str, num)
{}
- void fix_length_and_dec()
- { maybe_null= 1;; max_length= MAX_BLOB_WIDTH; }
+ bool fix_length_and_dec()
+ { maybe_null= 1;; max_length= MAX_BLOB_WIDTH; return FALSE; }
/* Mark that collation can change between calls */
bool dynamic_result() { return 1; }
@@ -1744,7 +1781,8 @@ class Item_func_dyncol_list: public Item_str_func
public:
Item_func_dyncol_list(THD *thd, Item *str): Item_str_func(thd, str)
{collation.set(DYNCOL_UTF);}
- void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; };
+ bool fix_length_and_dec()
+ { maybe_null= 1; max_length= MAX_BLOB_WIDTH; return FALSE; };
const char *func_name() const{ return "column_list"; }
String *val_str(String *);
Item *get_copy(THD *thd)
@@ -1767,7 +1805,7 @@ public:
String *val_str(String *str);
enum Functype functype() const { return TEMPTABLE_ROWID; }
const char *func_name() const { return "<rowid>"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_temptable_rowid>(thd, this); }
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index ca3316a1b5d..9b513ac9795 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -310,10 +310,14 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
if (engine->cols() > max_columns)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
-
+ res= TRUE;
+ goto end;
+ }
+ if (fix_length_and_dec())
+ {
+ res= TRUE;
goto end;
}
- fix_length_and_dec();
}
else
goto end;
@@ -910,9 +914,11 @@ Item::Type Item_subselect::type() const
}
-void Item_subselect::fix_length_and_dec()
+bool Item_subselect::fix_length_and_dec()
{
- engine->fix_length_and_dec(0);
+ if (engine->fix_length_and_dec(0))
+ return TRUE;
+ return FALSE;
}
@@ -1186,18 +1192,19 @@ const Type_handler *Item_singlerow_subselect::type_handler() const
return engine->type_handler();
}
-void Item_singlerow_subselect::fix_length_and_dec()
+bool Item_singlerow_subselect::fix_length_and_dec()
{
if ((max_columns= engine->cols()) == 1)
{
- engine->fix_length_and_dec(row= &value);
+ if (engine->fix_length_and_dec(row= &value))
+ return TRUE;
}
else
{
if (!(row= (Item_cache**) current_thd->alloc(sizeof(Item_cache*) *
- max_columns)))
- return;
- engine->fix_length_and_dec(row);
+ max_columns)) ||
+ engine->fix_length_and_dec(row))
+ return TRUE;
value= *row;
}
unsigned_flag= value->unsigned_flag;
@@ -1213,6 +1220,7 @@ void Item_singlerow_subselect::fix_length_and_dec()
for (uint i= 0; i < max_columns; i++)
row[i]->maybe_null= TRUE;
}
+ return FALSE;
}
@@ -1497,7 +1505,7 @@ void Item_exists_subselect::init_length_and_dec()
}
-void Item_exists_subselect::fix_length_and_dec()
+bool Item_exists_subselect::fix_length_and_dec()
{
DBUG_ENTER("Item_exists_subselect::fix_length_and_dec");
init_length_and_dec();
@@ -1505,14 +1513,17 @@ void Item_exists_subselect::fix_length_and_dec()
We need only 1 row to determine existence (i.e. any EXISTS that is not
an IN always requires LIMIT 1)
*/
+ Item *item= new (thd->mem_root) Item_int(thd, (int32) 1);
+ if (!item)
+ DBUG_RETURN(TRUE);
thd->change_item_tree(&unit->global_parameters()->select_limit,
- new (thd->mem_root) Item_int(thd, (int32) 1));
+ item);
DBUG_PRINT("info", ("Set limit to 1"));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
-void Item_in_subselect::fix_length_and_dec()
+bool Item_in_subselect::fix_length_and_dec()
{
DBUG_ENTER("Item_in_subselect::fix_length_and_dec");
init_length_and_dec();
@@ -1520,7 +1531,7 @@ void Item_in_subselect::fix_length_and_dec()
Unlike Item_exists_subselect, LIMIT 1 is set later for
Item_in_subselect, depending on the chosen strategy.
*/
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -3705,11 +3716,11 @@ bool subselect_single_select_engine::no_rows()
}
-/*
- makes storage for the output values for the subquery and calcuates
+/**
+ Makes storage for the output values for the subquery and calcuates
their data and column types and their nullability.
-*/
-void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
+*/
+bool subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
{
Item *sel_item;
List_iterator_fast<Item> li(item_list);
@@ -3722,44 +3733,51 @@ void subselect_engine::set_row(List<Item> &item_list, Item_cache **row)
item->unsigned_flag= sel_item->unsigned_flag;
maybe_null= sel_item->maybe_null;
if (!(row[i]= sel_item->get_cache(thd)))
- return;
+ return TRUE;
row[i]->setup(thd, sel_item);
//psergey-backport-timours: row[i]->store(sel_item);
}
if (item_list.elements > 1)
set_handler(&type_handler_row);
+ return FALSE;
}
-void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
+bool subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
DBUG_ASSERT(row || select_lex->item_list.elements==1);
- set_row(select_lex->item_list, row);
+ if (set_row(select_lex->item_list, row))
+ return TRUE;
item->collation.set(row[0]->collation);
if (cols() != 1)
maybe_null= 0;
+ return FALSE;
}
-void subselect_union_engine::fix_length_and_dec(Item_cache **row)
+bool subselect_union_engine::fix_length_and_dec(Item_cache **row)
{
DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
if (unit->first_select()->item_list.elements == 1)
{
- set_row(unit->types, row);
+ if (set_row(unit->types, row))
+ return TRUE;
item->collation.set(row[0]->collation);
}
else
{
bool maybe_null_saved= maybe_null;
- set_row(unit->types, row);
+ if (set_row(unit->types, row))
+ return TRUE;
maybe_null= maybe_null_saved;
}
+ return FALSE;
}
-void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
+bool subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
{
//this never should be called
DBUG_ASSERT(0);
+ return FALSE;
}
int read_first_record_seq(JOIN_TAB *tab);
@@ -5586,9 +5604,10 @@ void subselect_hash_sj_engine::print(String *str, enum_query_type query_type)
));
}
-void subselect_hash_sj_engine::fix_length_and_dec(Item_cache** row)
+bool subselect_hash_sj_engine::fix_length_and_dec(Item_cache** row)
{
DBUG_ASSERT(FALSE);
+ return FALSE;
}
void subselect_hash_sj_engine::exclude()
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 5b27181743f..084abf787af 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -201,7 +201,7 @@ public:
const_item_cache= 0;
forced_const= TRUE;
}
- virtual void fix_length_and_dec();
+ virtual bool fix_length_and_dec();
table_map used_tables() const;
table_map not_null_tables() const { return 0; }
bool const_item() const;
@@ -310,7 +310,7 @@ public:
bool val_bool();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
const Type_handler *type_handler() const;
- void fix_length_and_dec();
+ bool fix_length_and_dec();
uint cols() const;
Item* element_index(uint i) { return reinterpret_cast<Item*>(row[i]); }
@@ -408,7 +408,7 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date_from_int(ltime, fuzzydate); }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void print(String *str, enum_query_type query_type);
bool select_transformer(JOIN *join);
void top_level_item() { abort_on_null=1; }
@@ -633,7 +633,7 @@ public:
void print(String *str, enum_query_type query_type);
enum precedence precedence() const { return CMP_PRECEDENCE; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
bool const_item() const
{
@@ -816,7 +816,7 @@ public:
void set_thd(THD *thd_arg);
THD * get_thd() { return thd ? thd : current_thd; }
virtual int prepare(THD *)= 0;
- virtual void fix_length_and_dec(Item_cache** row)= 0;
+ virtual bool fix_length_and_dec(Item_cache** row)= 0;
/*
Execute the engine
@@ -857,7 +857,7 @@ public:
virtual int get_identifier() { DBUG_ASSERT(0); return 0; }
virtual void force_reexecution() {}
protected:
- void set_row(List<Item> &item_list, Item_cache **row);
+ bool set_row(List<Item> &item_list, Item_cache **row);
};
class subselect_single_select_engine: public subselect_engine
@@ -872,7 +872,7 @@ public:
Item_subselect *item);
void cleanup();
int prepare(THD *thd);
- void fix_length_and_dec(Item_cache** row);
+ bool fix_length_and_dec(Item_cache** row);
int exec();
uint cols() const;
uint8 uncacheable();
@@ -909,7 +909,7 @@ public:
Item_subselect *item);
void cleanup();
int prepare(THD *);
- void fix_length_and_dec(Item_cache** row);
+ bool fix_length_and_dec(Item_cache** row);
int exec();
uint cols() const;
uint8 uncacheable();
@@ -967,7 +967,7 @@ public:
~subselect_uniquesubquery_engine();
void cleanup();
int prepare(THD *);
- void fix_length_and_dec(Item_cache** row);
+ bool fix_length_and_dec(Item_cache** row);
int exec();
uint cols() const { return 1; }
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT_INJECTED; }
@@ -1116,7 +1116,7 @@ public:
TODO: factor out all these methods in a base subselect_index_engine class
because all of them have dummy implementations and should never be called.
*/
- void fix_length_and_dec(Item_cache** row);//=>base class
+ bool fix_length_and_dec(Item_cache** row);//=>base class
void exclude(); //=>base class
//=>base class
bool change_result(Item_subselect *si,
@@ -1389,7 +1389,7 @@ public:
uint count_columns_with_nulls_arg);
int prepare(THD *thd_arg) { set_thd(thd_arg); return 0; }
int exec();
- void fix_length_and_dec(Item_cache**) {}
+ bool fix_length_and_dec(Item_cache**) { return FALSE; }
uint cols() const { /* TODO: what is the correct value? */ return 1; }
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; }
void exclude() {}
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 69e228ec384..3e26e70ee6e 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -72,14 +72,14 @@ size_t Item_sum::ram_limitation(THD *thd)
bool Item_sum::init_sum_func_check(THD *thd)
{
SELECT_LEX *curr_sel= thd->lex->current_select;
- if (!curr_sel->name_visibility_map)
+ if (curr_sel && !curr_sel->name_visibility_map)
{
for (SELECT_LEX *sl= curr_sel; sl; sl= sl->context.outer_select())
{
curr_sel->name_visibility_map|= (1 << sl-> nest_level);
}
}
- if (!(thd->lex->allow_sum_func & curr_sel->name_visibility_map))
+ if (!curr_sel || !(thd->lex->allow_sum_func & curr_sel->name_visibility_map))
{
my_message(ER_INVALID_GROUP_FUNC_USE, ER_THD(thd, ER_INVALID_GROUP_FUNC_USE),
MYF(0));
@@ -1138,9 +1138,8 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
result_field=0;
max_length=float_length(decimals);
null_value=1;
- fix_length_and_dec();
-
- if (check_sum_func(thd, ref))
+ if (fix_length_and_dec() ||
+ check_sum_func(thd, ref))
return TRUE;
memcpy (orig_args, args, sizeof (Item *) * arg_count);
@@ -1166,7 +1165,9 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
with_param= args[0]->with_param;
with_window_func|= args[0]->with_window_func;
- fix_length_and_dec();
+ if (fix_length_and_dec())
+ DBUG_RETURN(TRUE);
+
if (!is_window_func_sum_expr())
setup_hybrid(thd, args[0], NULL);
result_field=0;
@@ -1180,11 +1181,11 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
}
-void Item_sum_hybrid::fix_length_and_dec()
+bool Item_sum_hybrid::fix_length_and_dec()
{
DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_type());
DBUG_ASSERT(args[0]->result_type() == args[0]->real_item()->result_type());
- (void) args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
+ return args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
}
@@ -1305,7 +1306,8 @@ Item_sum_sp::fix_fields(THD *thd, Item **ref)
result_field= NULL;
max_length= float_length(decimals);
null_value= 1;
- fix_length_and_dec();
+ if (fix_length_and_dec())
+ return TRUE;
if (check_sum_func(thd, ref))
return TRUE;
@@ -1387,14 +1389,14 @@ Item_sum_sp::cleanup()
@note called from Item::fix_fields.
*/
-void
+bool
Item_sum_sp::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_sp::fix_length_and_dec");
DBUG_ASSERT(sp_result_field);
Type_std_attributes::set(sp_result_field->type_std_attributes());
- Item_sum::fix_length_and_dec();
- DBUG_VOID_RETURN;
+ bool res= Item_sum::fix_length_and_dec();
+ DBUG_RETURN(res);
}
const char *
@@ -1490,14 +1492,16 @@ void Item_sum_sum::fix_length_and_dec_decimal()
}
-void Item_sum_sum::fix_length_and_dec()
+bool Item_sum_sum::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
maybe_null=null_value=1;
- args[0]->cast_to_int_type_handler()->Item_sum_sum_fix_length_and_dec(this);
+ if (args[0]->cast_to_int_type_handler()->
+ Item_sum_sum_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
max_length, (int) decimals));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -1914,15 +1918,17 @@ void Item_sum_avg::fix_length_and_dec_double()
}
-void Item_sum_avg::fix_length_and_dec()
+bool Item_sum_avg::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_avg::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
maybe_null=null_value=1;
- args[0]->cast_to_int_type_handler()->Item_sum_avg_fix_length_and_dec(this);
+ if (args[0]->cast_to_int_type_handler()->
+ Item_sum_avg_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
max_length, (int) decimals));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -2134,7 +2140,7 @@ void Item_sum_variance::fix_length_and_dec_decimal()
}
-void Item_sum_variance::fix_length_and_dec()
+bool Item_sum_variance::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
maybe_null= null_value= 1;
@@ -2146,11 +2152,11 @@ void Item_sum_variance::fix_length_and_dec()
type of the result is an implementation-defined aproximate numeric
type.
*/
-
- args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this);
+ if (args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this))
+ DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
max_length, (int)decimals));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@ -3376,13 +3382,13 @@ my_decimal *Item_sum_udf_int::val_decimal(my_decimal *dec)
/** Default max_length is max argument length. */
-void Item_sum_udf_str::fix_length_and_dec()
+bool Item_sum_udf_str::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_udf_str::fix_length_and_dec");
max_length=0;
for (uint i = 0; i < arg_count; i++)
set_if_bigger(max_length,args[i]->max_length);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 89ebb04366a..769d4f2f26c 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -457,7 +457,8 @@ public:
Updated value is then saved in the field.
*/
virtual void update_field()=0;
- virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
+ virtual bool fix_length_and_dec()
+ { maybe_null=1; null_value=1; return FALSE; }
virtual Item *result_item(THD *thd, Field *field);
void update_used_tables ();
@@ -760,8 +761,8 @@ public:
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
const Type_handler *type_handler() const { return &type_handler_longlong; }
- void fix_length_and_dec()
- { decimals=0; max_length=21; maybe_null=null_value=0; }
+ bool fix_length_and_dec()
+ { decimals=0; max_length=21; maybe_null=null_value=0; return FALSE; }
};
@@ -777,7 +778,7 @@ protected:
my_decimal direct_sum_decimal;
my_decimal dec_buffs[2];
uint curr_dec_buff;
- void fix_length_and_dec();
+ bool fix_length_and_dec();
public:
Item_sum_sum(THD *thd, Item *item_par, bool distinct):
@@ -912,7 +913,7 @@ public:
void fix_length_and_dec_double();
void fix_length_and_dec_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
enum Sumfunctype sum_func () const
{
return has_with_distinct() ? AVG_DISTINCT_FUNC : AVG_FUNC;
@@ -972,7 +973,7 @@ But, this falls prey to catastrophic cancellation. Instead, use the recurrence
class Item_sum_variance : public Item_sum_num
{
- void fix_length_and_dec();
+ bool fix_length_and_dec();
public:
double recurrence_m, recurrence_s; /* Used in recurrence relation. */
@@ -1059,7 +1060,7 @@ protected:
cmp_sign(item->cmp_sign), was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void setup_hybrid(THD *thd, Item *item, Item *value_arg);
void clear();
void direct_add(Item *item);
@@ -1139,8 +1140,11 @@ public:
longlong val_int();
void reset_field();
void update_field();
- void fix_length_and_dec()
- { decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0; }
+ bool fix_length_and_dec()
+ {
+ decimals= 0; max_length=21; unsigned_flag= 1; maybe_null= null_value= 0;
+ return FALSE;
+ }
void cleanup()
{
bits= reset_bits;
@@ -1309,7 +1313,7 @@ public:
{
return create_table_field_from_handler(table);
}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
const char *func_name() const;
const Type_handler *type_handler() const;
@@ -1573,7 +1577,7 @@ class Item_sum_udf_float :public Item_udf_sum
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_sum_udf_float>(thd, this); }
@@ -1595,7 +1599,7 @@ public:
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
const Type_handler *type_handler() const { return &type_handler_longlong; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ bool fix_length_and_dec() { decimals=0; max_length=21; return FALSE; }
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_sum_udf_int>(thd, this); }
@@ -1636,7 +1640,7 @@ public:
}
my_decimal *val_decimal(my_decimal *dec);
const Type_handler *type_handler() const { return string_type_handler(); }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_sum_udf_str>(thd, this); }
@@ -1657,7 +1661,7 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *);
const Type_handler *type_handler() const { return &type_handler_newdecimal; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
Item *copy_or_same(THD* thd);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_sum_udf_decimal>(thd, this); }
@@ -1731,7 +1735,7 @@ public:
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
double val_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- void fix_length_and_dec() { maybe_null=1; max_length=0; }
+ bool fix_length_and_dec() { maybe_null=1; max_length=0; return FALSE; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
void clear() {}
bool add() { return 0; }
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index e01114fb0ad..b4d929e0f70 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -954,7 +954,7 @@ longlong Item_func_month::val_int()
}
-void Item_func_monthname::fix_length_and_dec()
+bool Item_func_monthname::fix_length_and_dec()
{
THD* thd= current_thd;
CHARSET_INFO *cs= thd->variables.collation_connection;
@@ -962,7 +962,8 @@ void Item_func_monthname::fix_length_and_dec()
collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire());
decimals=0;
max_length= locale->max_month_name_length * collation.collation->mbmaxlen;
- maybe_null=1;
+ maybe_null=1;
+ return FALSE;
}
@@ -1102,7 +1103,7 @@ longlong Item_func_weekday::val_int()
odbc_type) + MY_TEST(odbc_type);
}
-void Item_func_dayname::fix_length_and_dec()
+bool Item_func_dayname::fix_length_and_dec()
{
THD* thd= current_thd;
CHARSET_INFO *cs= thd->variables.collation_connection;
@@ -1110,7 +1111,8 @@ void Item_func_dayname::fix_length_and_dec()
collation.set(cs, DERIVATION_COERCIBLE, locale->repertoire());
decimals=0;
max_length= locale->max_day_name_length * collation.collation->mbmaxlen;
- maybe_null=1;
+ maybe_null=1;
+ return FALSE;
}
@@ -1842,7 +1844,7 @@ overflow:
return 0;
}
-void Item_func_date_format::fix_length_and_dec()
+bool Item_func_date_format::fix_length_and_dec()
{
THD* thd= current_thd;
if (!is_time_format)
@@ -1881,6 +1883,7 @@ void Item_func_date_format::fix_length_and_dec()
set_if_smaller(max_length,MAX_BLOB_WIDTH);
}
maybe_null=1; // If wrong date
+ return FALSE;
}
@@ -2034,13 +2037,14 @@ null_date:
}
-void Item_func_from_unixtime::fix_length_and_dec()
-{
+bool Item_func_from_unixtime::fix_length_and_dec()
+{
THD *thd= current_thd;
thd->time_zone_used= 1;
tz= thd->variables.time_zone;
fix_attributes_datetime_not_fixed_dec(args[0]->decimals);
maybe_null= true;
+ return FALSE;
}
@@ -2112,7 +2116,7 @@ void Item_func_convert_tz::cleanup()
}
-void Item_date_add_interval::fix_length_and_dec()
+bool Item_date_add_interval::fix_length_and_dec()
{
enum_field_types arg0_field_type;
@@ -2121,7 +2125,7 @@ void Item_date_add_interval::fix_length_and_dec()
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
args[0]->type_handler()->name().ptr(),
"interval", func_name());
- return;
+ return TRUE;
}
/*
The field type for the result of an Item_datefunc is defined as
@@ -2189,6 +2193,7 @@ void Item_date_add_interval::fix_length_and_dec()
fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
}
maybe_null= true;
+ return FALSE;
}
@@ -2259,7 +2264,7 @@ void Item_extract::print(String *str, enum_query_type query_type)
str->append(')');
}
-void Item_extract::fix_length_and_dec()
+bool Item_extract::fix_length_and_dec()
{
maybe_null=1; // If wrong date
switch (int_type) {
@@ -2285,6 +2290,7 @@ void Item_extract::fix_length_and_dec()
case INTERVAL_SECOND_MICROSECOND: set_time_length(8); break; // ssffffff
case INTERVAL_LAST: DBUG_ASSERT(0); break; /* purecov: deadcode */
}
+ return FALSE;
}
@@ -2688,7 +2694,7 @@ err:
}
-void Item_func_add_time::fix_length_and_dec()
+bool Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
@@ -2698,7 +2704,7 @@ void Item_func_add_time::fix_length_and_dec()
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
args[0]->type_handler()->name().ptr(),
args[1]->type_handler()->name().ptr(), func_name());
- return;
+ return TRUE;
}
/*
The field type for the result of an Item_func_add_time function is defined
@@ -2734,6 +2740,7 @@ void Item_func_add_time::fix_length_and_dec()
fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
}
maybe_null= true;
+ return FALSE;
}
/**
@@ -3220,7 +3227,7 @@ get_date_time_result_type(const char *format, uint length)
}
-void Item_func_str_to_date::fix_length_and_dec()
+bool Item_func_str_to_date::fix_length_and_dec()
{
if (!args[0]->type_handler()->is_traditional_type() ||
!args[1]->type_handler()->is_traditional_type())
@@ -3228,10 +3235,10 @@ void Item_func_str_to_date::fix_length_and_dec()
my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
args[0]->type_handler()->name().ptr(),
args[1]->type_handler()->name().ptr(), func_name());
- return;
+ return TRUE;
}
if (agg_arg_charsets(collation, args, 2, MY_COLL_ALLOW_CONV, 1))
- return;
+ return TRUE;
if (collation.collation->mbminlen > 1)
internal_charset= &my_charset_utf8mb4_general_ci;
@@ -3275,6 +3282,7 @@ void Item_func_str_to_date::fix_length_and_dec()
}
}
cached_timestamp_type= mysql_timestamp_type();
+ return FALSE;
}
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 30d5018ff36..51ce3bf2988 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -62,9 +62,10 @@ public:
Item_func_period_add(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_add"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_period_add>(thd, this); }
@@ -79,10 +80,11 @@ public:
Item_func_period_diff(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_diff"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ return FALSE;
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_period_diff>(thd, this); }
@@ -95,11 +97,12 @@ public:
Item_func_to_days(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_days"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
- maybe_null=1;
+ maybe_null=1;
+ return FALSE;
}
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
@@ -122,11 +125,12 @@ public:
Item_func_to_seconds(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_seconds"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
fix_char_length(12);
maybe_null= 1;
+ return FALSE;
}
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
@@ -148,11 +152,12 @@ public:
Item_func_dayofmonth(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofmonth"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
- maybe_null=1;
+ maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -187,11 +192,12 @@ public:
}
const char *func_name() const { return "month"; }
const Type_handler *type_handler() const { return &type_handler_long; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals= 0;
fix_char_length(2);
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -211,7 +217,7 @@ public:
Item_func_monthname(THD *thd, Item *a): Item_str_func(thd, a) {}
const char *func_name() const { return "monthname"; }
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool check_partition_func_processor(void *int_arg) {return TRUE;}
bool check_valid_arguments_processor(void *int_arg)
{
@@ -232,11 +238,12 @@ public:
Item_func_dayofyear(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofyear"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals= 0;
fix_char_length(3);
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -255,11 +262,12 @@ public:
Item_func_hour(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "hour"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -278,11 +286,12 @@ public:
Item_func_minute(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "minute"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -301,11 +310,12 @@ public:
Item_func_quarter(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "quarter"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=1*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -324,11 +334,12 @@ public:
Item_func_second(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "second"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -353,11 +364,12 @@ public:
Item_func_week(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "week"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_vcol_func_processor(void *arg)
{
@@ -385,11 +397,12 @@ public:
:Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "yearweek"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -410,11 +423,12 @@ public:
const char *func_name() const { return "year"; }
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=4*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -450,11 +464,12 @@ public:
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
const Type_handler *type_handler() const { return &type_handler_long; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals= 0;
fix_char_length(1);
maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -474,7 +489,7 @@ class Item_func_dayname :public Item_func_weekday
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
const Type_handler *type_handler() const { return &type_handler_varchar; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool check_partition_func_processor(void *int_arg) {return TRUE;}
bool check_vcol_func_processor(void *arg)
{
@@ -535,9 +550,10 @@ public:
return FALSE;
return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0);
+ fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0);
+ return FALSE;
}
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
@@ -558,9 +574,10 @@ public:
{
return !has_time_args();
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_length_and_dec_generic(args[0]->time_precision());
+ return FALSE;
}
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
@@ -629,10 +646,11 @@ public:
Item_datefunc(THD *thd, Item *a): Item_temporal_func(thd, a) { }
Item_datefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) { }
const Type_handler *type_handler() const { return &type_handler_newdate; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_attributes_date();
maybe_null= (arg_count > 0);
+ return FALSE;
}
};
@@ -670,7 +688,7 @@ public:
Item_func_curtime(THD *thd, uint dec): Item_timefunc(thd), last_query_id(0)
{ decimals= dec; }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec() { fix_attributes_time(decimals); }
+ bool fix_length_and_dec() { fix_attributes_time(decimals); return FALSE; }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
/*
Abstract method that defines which time zone is used for conversion.
@@ -757,7 +775,8 @@ public:
Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd), last_query_id(0)
{ decimals= dec; }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec() { fix_attributes_datetime(decimals); }
+ bool fix_length_and_dec()
+ { fix_attributes_datetime(decimals); return FALSE;}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
bool check_vcol_func_processor(void *arg)
@@ -864,7 +883,7 @@ public:
Item_str_func(thd, a, b, c), locale(0), is_time_format(false) {}
String *val_str(String *str);
const char *func_name() const { return "date_format"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
uint format_length(const String *format);
bool eq(const Item *item, bool binary_cmp) const;
bool check_vcol_func_processor(void *arg)
@@ -897,7 +916,7 @@ class Item_func_from_unixtime :public Item_datetimefunc
public:
Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {}
const char *func_name() const { return "from_unixtime"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_from_unixtime>(thd, this); }
@@ -937,10 +956,11 @@ class Item_func_convert_tz :public Item_datetimefunc
Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c):
Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {}
const char *func_name() const { return "convert_tz"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_attributes_datetime(args[0]->datetime_precision());
maybe_null= true;
+ return FALSE;
}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void cleanup();
@@ -956,10 +976,11 @@ class Item_func_sec_to_time :public Item_timefunc
public:
Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_attributes_time(args[0]->decimals);
maybe_null= true;
+ return FALSE;
}
const char *func_name() const { return "sec_to_time"; }
Item *get_copy(THD *thd)
@@ -977,7 +998,7 @@ public:
Item_temporal_hybrid_func(thd, a, b),int_type(type_arg),
date_sub_interval(neg_arg) {}
const char *func_name() const { return "date_add_interval"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
bool eq(const Item *item, bool binary_cmp) const;
void print(String *str, enum_query_type query_type);
@@ -1045,7 +1066,7 @@ class Item_extract :public Item_int_func
longlong val_int();
enum Functype functype() const { return EXTRACT_FUNC; }
const char *func_name() const { return "extract"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
void print(String *str, enum_query_type query_type);
bool check_partition_func_processor(void *int_arg) {return FALSE;}
@@ -1125,9 +1146,9 @@ public:
fix_length_and_dec_generic();
m_suppress_warning_to_error_escalation= true;
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
+ return args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
}
void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
@@ -1152,9 +1173,9 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "date"; }
const Type_handler *type_handler() const { return &type_handler_newdate; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
+ return args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_date_typecast>(thd, this); }
@@ -1170,9 +1191,10 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "time"; }
const Type_handler *type_handler() const { return &type_handler_time2; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_time_typecast_fix_length_and_dec(this);
+ return args[0]->type_handler()->
+ Item_time_typecast_fix_length_and_dec(this);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_time_typecast>(thd, this); }
@@ -1188,9 +1210,10 @@ public:
const char *cast_type() const { return "datetime"; }
const Type_handler *type_handler() const { return &type_handler_datetime2; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- args[0]->type_handler()->Item_datetime_typecast_fix_length_and_dec(this);
+ return args[0]->type_handler()->
+ Item_datetime_typecast_fix_length_and_dec(this);
}
Item *get_copy(THD *thd)
{ return get_item_copy<Item_datetime_typecast>(thd, this); }
@@ -1220,7 +1243,7 @@ public:
Item_func_add_time(THD *thd, Item *a, Item *b, bool type_arg, bool neg_arg):
Item_temporal_hybrid_func(thd, a, b), is_date(type_arg)
{ sign= neg_arg ? -1 : 1; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
void print(String *str, enum_query_type query_type);
const char *func_name() const { return "add_time"; }
@@ -1235,11 +1258,12 @@ class Item_func_timediff :public Item_timefunc
public:
Item_func_timediff(THD *thd, Item *a, Item *b): Item_timefunc(thd, a, b) {}
const char *func_name() const { return "timediff"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
fix_attributes_time(dec);
maybe_null= true;
+ return FALSE;
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
Item *get_copy(THD *thd)
@@ -1257,10 +1281,11 @@ public:
Item_func_maketime(THD *thd, Item *a, Item *b, Item *c):
Item_timefunc(thd, a, b, c)
{}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_attributes_time(args[2]->decimals);
maybe_null= true;
+ return FALSE;
}
const char *func_name() const { return "maketime"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
@@ -1275,11 +1300,12 @@ public:
Item_func_microsecond(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "microsecond"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
maybe_null=1;
fix_char_length(6);
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@ -1302,10 +1328,11 @@ public:
Item_longlong_func(thd, a, b), int_type(type_arg) {}
const char *func_name() const { return "timestampdiff"; }
longlong val_int();
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=0;
maybe_null=1;
+ return FALSE;
}
virtual void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd)
@@ -1327,11 +1354,12 @@ public:
{}
String *val_str_ascii(String *str);
const char *func_name() const { return "get_format"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
maybe_null= 1;
decimals=0;
fix_length_and_charset(17, default_charset());
+ return FALSE;
}
virtual void print(String *str, enum_query_type query_type);
Item *get_copy(THD *thd)
@@ -1353,7 +1381,7 @@ public:
{}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *func_name() const { return "str_to_date"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_str_to_date>(thd, this); }
};
diff --git a/sql/item_vers.h b/sql/item_vers.h
index 17ad3daa73c..8b9c0e6056c 100644
--- a/sql/item_vers.h
+++ b/sql/item_vers.h
@@ -38,7 +38,8 @@ public:
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_trt_ts>(thd, this); }
- void fix_length_and_dec() { fix_attributes_datetime(decimals); }
+ bool fix_length_and_dec()
+ { fix_attributes_datetime(decimals); return FALSE; }
};
class Item_func_trt_id : public Item_longlong_func
@@ -69,10 +70,11 @@ public:
return NULL;
}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_int_func::fix_length_and_dec();
+ bool res= Item_int_func::fix_length_and_dec();
max_length= 20;
+ return res;
}
longlong val_int();
diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc
index a3a9fc120bc..49ee14bed20 100644
--- a/sql/item_windowfunc.cc
+++ b/sql/item_windowfunc.cc
@@ -86,9 +86,9 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
- enum_parsing_place place= thd->lex->current_select->context_analysis_place;
-
- if (!(place == SELECT_LIST || place == IN_ORDER_BY))
+ if (!thd->lex->current_select ||
+ (thd->lex->current_select->context_analysis_place != SELECT_LIST &&
+ thd->lex->current_select->context_analysis_place != IN_ORDER_BY))
{
my_error(ER_WRONG_PLACEMENT_OF_WINDOW_FUNCTION, MYF(0));
return true;
@@ -121,7 +121,8 @@ Item_window_func::fix_fields(THD *thd, Item **ref)
const_item_cache= false;
with_window_func= true;
- fix_length_and_dec();
+ if (fix_length_and_dec())
+ return TRUE;
max_length= window_func()->max_length;
maybe_null= window_func()->maybe_null;
@@ -361,7 +362,8 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref)
maybe_null= 1;
result_field=0;
null_value=1;
- fix_length_and_dec();
+ if (fix_length_and_dec())
+ return TRUE;
if (check_sum_func(thd, ref))
return TRUE;
@@ -441,7 +443,7 @@ bool Item_sum_hybrid_simple::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
DBUG_ASSERT(fixed == 1);
if (null_value)
- return 0;
+ return true;
bool retval= value->get_date(ltime, fuzzydate);
if ((null_value= value->null_value))
DBUG_ASSERT(retval == true);
diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h
index cb85a2c06d1..48851da7d96 100644
--- a/sql/item_windowfunc.h
+++ b/sql/item_windowfunc.h
@@ -526,10 +526,11 @@ class Item_sum_percent_rank: public Item_sum_window_with_row_count
bool add();
const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = 10; // TODO-cvicentiu find out how many decimals the standard
// requires.
+ return FALSE;
}
void setup_window_func(THD *thd, Window_spec *window_spec);
@@ -614,10 +615,11 @@ class Item_sum_cume_dist: public Item_sum_window_with_row_count
void update_field() {}
const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = 10; // TODO-cvicentiu find out how many decimals the standard
// requires.
+ return FALSE;
}
Item *get_copy(THD *thd)
@@ -820,10 +822,11 @@ public:
const Type_handler *type_handler() const
{return Type_handler_hybrid_field_type::type_handler();}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = 10; // TODO-cvicentiu find out how many decimals the standard
// requires.
+ return FALSE;
}
Item *get_copy(THD *thd)
@@ -950,10 +953,11 @@ public:
const Type_handler *type_handler() const
{return Type_handler_hybrid_field_type::type_handler();}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = 10; // TODO-cvicentiu find out how many decimals the standard
// requires.
+ return FALSE;
}
Item *get_copy(THD *thd)
@@ -1292,9 +1296,10 @@ public:
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
List<Item> &fields, uint flags);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = window_func()->decimals;
+ return FALSE;
}
const char* func_name() const { return "WF"; }
diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc
index c2b09e4f564..146c5aa57fe 100644
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@ -236,13 +236,14 @@ public:
return str;
}
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
collation.collation= pxml->charset();
// To avoid premature evaluation, mark all nodeset functions as non-const.
used_tables_cache= RAND_TABLE_BIT;
const_item_cache= false;
+ return FALSE;
}
const char *func_name() const { return "nodeset"; }
bool check_vcol_func_processor(void *arg)
@@ -470,7 +471,7 @@ public:
Item_nodeset_func(thd, pxml), string_cache(str_arg) { }
String *val_raw(String *res)
{ return string_cache; }
- void fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; }
+ bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH;; return FALSE; }
Item *get_copy(THD *thd)
{ return get_item_copy<Item_nodeset_context_cache>(thd, this); }
};
@@ -484,7 +485,7 @@ public:
Item_func_xpath_position(THD *thd, Item *a, String *p):
Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_position"; }
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
longlong val_int()
{
String *flt= args[0]->val_raw(&tmp_value);
@@ -505,7 +506,7 @@ public:
Item_func_xpath_count(THD *thd, Item *a, String *p):
Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_count"; }
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
longlong val_int()
{
uint predicate_supplied_context_size;
@@ -2749,10 +2750,10 @@ my_xpath_parse(MY_XPATH *xpath, const char *str, const char *strend)
}
-void Item_xml_str_func::fix_length_and_dec()
+bool Item_xml_str_func::fix_length_and_dec()
{
max_length= MAX_BLOB_WIDTH;
- agg_arg_charsets_for_comparison(collation, args, arg_count);
+ return agg_arg_charsets_for_comparison(collation, args, arg_count);
}
diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h
index 33e85ba5628..6846063aab7 100644
--- a/sql/item_xmlfunc.h
+++ b/sql/item_xmlfunc.h
@@ -82,7 +82,7 @@ public:
maybe_null= TRUE;
}
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool const_item() const
{
return const_item_cache && (!nodeset_func || nodeset_func->const_item());
diff --git a/sql/log.cc b/sql/log.cc
index afd6c90e386..5019760cdbc 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -44,6 +44,8 @@
#include <my_dir.h>
#include <m_ctype.h> // For test_if_number
+#include <set_var.h> // for Sys_last_gtid_ptr
+
#ifdef _WIN32
#include "message.h"
#endif
@@ -2606,7 +2608,7 @@ bool MYSQL_LOG::open(
File file= -1;
my_off_t seek_offset;
bool is_fifo = false;
- int open_flags= O_CREAT | O_BINARY;
+ int open_flags= O_CREAT | O_BINARY | O_CLOEXEC;
DBUG_ENTER("MYSQL_LOG::open");
DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg));
@@ -3343,7 +3345,7 @@ bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg,
".index", opt);
if ((index_file_nr= mysql_file_open(m_key_file_log_index,
index_file_name,
- O_RDWR | O_CREAT | O_BINARY,
+ O_RDWR | O_CREAT | O_BINARY | O_CLOEXEC,
MYF(MY_WME))) < 0 ||
mysql_file_sync(index_file_nr, MYF(MY_WME)) ||
init_io_cache(&index_file, index_file_nr,
@@ -6010,7 +6012,8 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
}
if (err)
DBUG_RETURN(true);
- thd->last_commit_gtid= gtid;
+
+ thd->set_last_commit_gtid(gtid);
Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone,
LOG_EVENT_SUPPRESS_USE_F, is_transactional,
@@ -9007,14 +9010,14 @@ int TC_LOG_MMAP::open(const char *opt_name)
tc_log_page_size= my_getpagesize();
fn_format(logname,opt_name,mysql_data_home,"",MY_UNPACK_FILENAME);
- if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR, MYF(0))) < 0)
+ if ((fd= mysql_file_open(key_file_tclog, logname, O_RDWR | O_CLOEXEC, MYF(0))) < 0)
{
if (my_errno != ENOENT)
goto err;
if (using_heuristic_recover())
return 1;
if ((fd= mysql_file_create(key_file_tclog, logname, CREATE_MODE,
- O_RDWR, MYF(MY_WME))) < 0)
+ O_RDWR | O_CLOEXEC, MYF(MY_WME))) < 0)
goto err;
inited=1;
file_length= opt_tc_log_size;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 7a6d0a1821b..c550adea26b 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -5550,22 +5550,6 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi,
else
thd->variables.collation_database= thd->db_charset;
- {
- const CHARSET_INFO *cs= thd->charset();
- /*
- We cannot ask for parsing a statement using a character set
- without state_maps (parser internal data).
- */
- if (!cs->state_map)
- {
- rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
- ER_THD(thd, ER_SLAVE_FATAL_ERROR),
- "character_set cannot be parsed");
- thd->is_slave_error= true;
- goto end;
- }
- }
-
/*
Record any GTID in the same transaction, so slave state is
transactionally consistent.
@@ -13155,8 +13139,7 @@ Rows_log_event::write_row(rpl_group_info *rgi,
}
// Handle INSERT.
- // Set vers fields when replicating from not system-versioned table.
- if (m_type == WRITE_ROWS_EVENT_V1 && table->versioned(VERS_TIMESTAMP))
+ if (table->versioned(VERS_TIMESTAMP))
{
ulong sec_part;
bitmap_set_bit(table->read_set, table->vers_start_field()->field_index);
@@ -13637,6 +13620,16 @@ void issue_long_find_row_warning(Log_event_type type,
}
+/*
+ HA_ERR_KEY_NOT_FOUND is a fatal error normally, but it's an expected
+ error in speculate optimistic mode, so use something non-fatal instead
+*/
+static int row_not_found_error(rpl_group_info *rgi)
+{
+ return rgi->speculation != rpl_group_info::SPECULATE_OPTIMISTIC
+ ? HA_ERR_KEY_NOT_FOUND : HA_ERR_RECORD_CHANGED;
+}
+
/**
Locate the current row in event's table.
@@ -13734,14 +13727,12 @@ int Rows_log_event::find_row(rpl_group_info *rgi)
int error;
DBUG_PRINT("info",("locating record using primary key (position)"));
- if (!table->file->inited &&
- (error= table->file->ha_rnd_init_with_error(0)))
- DBUG_RETURN(error);
-
error= table->file->ha_rnd_pos_by_record(table->record[0]);
if (unlikely(error))
{
DBUG_PRINT("info",("rnd_pos returns error %d",error));
+ if (error == HA_ERR_KEY_NOT_FOUND)
+ error= row_not_found_error(rgi);
table->file->print_error(error, MYF(0));
}
DBUG_RETURN(error);
@@ -13807,6 +13798,8 @@ int Rows_log_event::find_row(rpl_group_info *rgi)
HA_READ_KEY_EXACT))))
{
DBUG_PRINT("info",("no record matching the key found in the table"));
+ if (error == HA_ERR_KEY_NOT_FOUND)
+ error= row_not_found_error(rgi);
table->file->print_error(error, MYF(0));
table->file->ha_index_end();
goto end;
diff --git a/sql/mysql_install_db.cc b/sql/mysql_install_db.cc
index 0483c7f5fbf..ce40b5edc2c 100644
--- a/sql/mysql_install_db.cc
+++ b/sql/mysql_install_db.cc
@@ -198,7 +198,7 @@ int main(int argc, char **argv)
die("database creation failed");
}
- printf("Creation of the database was successfull");
+ printf("Creation of the database was successful");
return 0;
}
diff --git a/sql/mysql_upgrade_service.cc b/sql/mysql_upgrade_service.cc
index 599f4a40ea0..1a3df4f5536 100644
--- a/sql/mysql_upgrade_service.cc
+++ b/sql/mysql_upgrade_service.cc
@@ -146,6 +146,11 @@ static void die(const char *fmt, ...)
exit(1);
}
+#define WRITE_LOG(fmt,...) {\
+ char log_buf[1024]; \
+ snprintf(log_buf,sizeof(log_buf), fmt, __VA_ARGS__);\
+ WriteFile(logfile_handle,log_buf, (DWORD)strlen(log_buf), 0 , 0);\
+}
/*
spawn-like function to run subprocesses.
@@ -187,17 +192,22 @@ static intptr_t run_tool(int wait_flag, const char *program,...)
{
char tmpdir[FN_REFLEN];
GetTempPath(FN_REFLEN, tmpdir);
- sprintf_s(logfile_path, "%s\\mysql_upgrade_service.%s.log", tmpdir,
+ sprintf_s(logfile_path, "%smysql_upgrade_service.%s.log", tmpdir,
opt_service);
- logfile_handle= CreateFile(logfile_path, GENERIC_WRITE, FILE_SHARE_READ,
- NULL, TRUNCATE_EXISTING, 0, NULL);
- if (!logfile_handle)
+ SECURITY_ATTRIBUTES attr= {0};
+ attr.nLength= sizeof(SECURITY_ATTRIBUTES);
+ attr.bInheritHandle= TRUE;
+ logfile_handle= CreateFile(logfile_path, FILE_APPEND_DATA,
+ FILE_SHARE_READ|FILE_SHARE_WRITE, &attr, CREATE_ALWAYS, 0, NULL);
+ if (logfile_handle == INVALID_HANDLE_VALUE)
{
die("Cannot open log file %s, windows error %u",
logfile_path, GetLastError());
}
}
+ WRITE_LOG("Executing %s\r\n", cmdline);
+
/* Start child process */
STARTUPINFO si= {0};
si.cb= sizeof(si);
@@ -458,7 +468,7 @@ int main(int argc, char **argv)
log("Phase 3/8: Starting mysqld for upgrade");
mysqld_process= (HANDLE)run_tool(P_NOWAIT, mysqld_path,
defaults_file_param, "--skip-networking", "--skip-grant-tables",
- "--enable-named-pipe", socket_param, NULL);
+ "--enable-named-pipe", socket_param,"--skip-slave-start", NULL);
if (mysqld_process == INVALID_HANDLE_VALUE)
{
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 0d3aa12465d..576ef5009b5 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -47,6 +47,12 @@
#include "probes_mysql.h"
#include "proxy_protocol.h"
+#ifdef EMBEDDED_LIBRARY
+#undef MYSQL_SERVER
+#undef MYSQL_CLIENT
+#define MYSQL_CLIENT
+#endif /*EMBEDDED_LIBRARY */
+
/*
to reduce the number of ifdef's in the code
*/
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 6f761c9c5d3..6879eb6bdcf 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -6528,6 +6528,8 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
if (ror_intersect_add(intersect, cpk_scan, TRUE) &&
(intersect->total_cost < min_cost))
intersect_best= intersect; //just set pointer here
+ else
+ cpk_scan= 0; // Don't use cpk_scan
}
else
cpk_scan= 0; // Don't use cpk_scan
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 5051c26f4a3..ba57d9d3ca4 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -6291,6 +6291,7 @@ bool JOIN::choose_tableless_subquery_plan()
functions produce empty subquery result. There is no need to further
rewrite the subquery because it will not be executed at all.
*/
+ exec_const_cond= 0;
return FALSE;
}
@@ -6322,7 +6323,7 @@ bool JOIN::choose_tableless_subquery_plan()
tmp_having= having;
}
}
- exec_const_cond= conds;
+ exec_const_cond= zero_result_cause ? 0 : conds;
return FALSE;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index c9dfeb3e211..8ab892068b3 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -454,6 +454,22 @@ void sys_var::do_deprecated_warning(THD *thd)
@retval true on error, false otherwise (warning or ok)
*/
+
+
+bool throw_bounds_warning(THD *thd, const char *name,const char *v)
+{
+ if (thd->variables.sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, v);
+ return true;
+ }
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE,
+ ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, v);
+ return false;
+}
+
+
bool throw_bounds_warning(THD *thd, const char *name,
bool fixed, bool is_unsigned, longlong v)
{
@@ -471,9 +487,7 @@ bool throw_bounds_warning(THD *thd, const char *name,
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
return true;
}
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, buf);
+ return throw_bounds_warning(thd, name, buf);
}
return false;
}
@@ -491,9 +505,7 @@ bool throw_bounds_warning(THD *thd, const char *name, bool fixed, double v)
my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name, buf);
return true;
}
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_TRUNCATED_WRONG_VALUE,
- ER_THD(thd, ER_TRUNCATED_WRONG_VALUE), name, buf);
+ return throw_bounds_warning(thd, name, buf);
}
return false;
}
@@ -1006,24 +1018,12 @@ int set_var_collation_client::update(THD *thd)
#ifndef EMBEDDED_LIBRARY
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
{
- sys_var *svar;
- mysql_mutex_lock(&LOCK_plugin);
- if ((svar= find_sys_var_ex(thd, "character_set_client",
- sizeof("character_set_client") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- if ((svar= find_sys_var_ex(thd, "character_set_results",
- sizeof("character_set_results") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- if ((svar= find_sys_var_ex(thd, "character_set_connection",
- sizeof("character_set_connection") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- mysql_mutex_unlock(&LOCK_plugin);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_client_ptr);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_results_ptr);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_connection_ptr);
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
#endif //EMBEDDED_LIBRARY
diff --git a/sql/set_var.h b/sql/set_var.h
index 82afb3ceea6..6097b28e76f 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -244,6 +244,12 @@ protected:
uchar *global_var_ptr()
{ return ((uchar*)&global_system_variables) + offset; }
+ void *max_var_ptr()
+ {
+ return scope() == SESSION ? (((uchar*)&max_system_variables) + offset) :
+ 0;
+ }
+
friend class Session_sysvars_tracker;
friend class Session_tracker;
};
@@ -427,7 +433,9 @@ bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
LEX_CSTRING *ls);
int default_regex_flags_pcre(const THD *thd);
-extern sys_var *Sys_autocommit_ptr;
+extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr,
+ *Sys_character_set_client_ptr, *Sys_character_set_connection_ptr,
+ *Sys_character_set_results_ptr;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
@@ -435,6 +443,7 @@ int sys_var_init();
uint sys_var_elements();
int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags);
void sys_var_end(void);
+bool check_has_super(sys_var *self, THD *thd, set_var *var);
plugin_ref *resolve_engine_list(THD *thd, const char *str_arg, size_t str_arg_len,
bool error_on_unknown_engine, bool temp_copy);
void free_engine_list(plugin_ref *list);
@@ -443,4 +452,3 @@ plugin_ref *temp_copy_engine_list(THD *thd, plugin_ref *list);
char *pretty_print_engine_list(THD *thd, plugin_ref *list);
#endif
-
diff --git a/sql/slave.cc b/sql/slave.cc
index 275db6165e9..bb1300d36e6 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -5663,7 +5663,7 @@ err_during_init:
*/
if (WSREP_ON && wsrep_node_dropped && wsrep_restart_slave)
{
- if (wsrep_ready)
+ if (wsrep_ready_get())
{
WSREP_INFO("Slave error due to node temporarily non-primary"
"SQL slave will continue");
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 12fb63925ce..0d5e1abfdf2 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1379,7 +1379,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
/* Only pop cursors when we're done with group aggregate running. */
if (m_chistics.agg_type != GROUP_AGGREGATE ||
(m_chistics.agg_type == GROUP_AGGREGATE && thd->spcont->quit_func))
- thd->spcont->pop_all_cursors(); // To avoid memory leaks after an error
+ thd->spcont->pop_all_cursors(thd); // To avoid memory leaks after an error
/* Restore all saved */
if (m_chistics.agg_type == GROUP_AGGREGATE)
@@ -2709,7 +2709,6 @@ sp_head::restore_thd_mem_root(THD *thd)
Item *flist= free_list; // The old list
set_query_arena(thd); // Get new free_list and mem_root
state= STMT_INITIALIZED_FOR_SP;
- is_stored_procedure= true;
DBUG_PRINT("info", ("mem_root %p returned from thd mem root %p",
&mem_root, &thd->mem_root));
@@ -4001,7 +4000,7 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_hpush_jump::execute");
- int ret= thd->spcont->push_handler(m_handler, m_ip + 1);
+ int ret= thd->spcont->push_handler(this);
*nextp= m_dest;
@@ -4160,11 +4159,13 @@ sp_instr_cpush::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_cpush::execute");
- int ret= thd->spcont->push_cursor(thd, &m_lex_keeper);
+ sp_cursor::reset(thd, &m_lex_keeper);
+ m_lex_keeper.disable_query_cache();
+ thd->spcont->push_cursor(this);
*nextp= m_ip+1;
- DBUG_RETURN(ret);
+ DBUG_RETURN(false);
}
@@ -4198,7 +4199,7 @@ int
sp_instr_cpop::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_cpop::execute");
- thd->spcont->pop_cursors(m_count);
+ thd->spcont->pop_cursors(thd, m_count);
*nextp= m_ip+1;
DBUG_RETURN(0);
}
@@ -4479,7 +4480,7 @@ void
sp_instr_cursor_copy_struct::print(String *str)
{
sp_variable *var= m_ctx->find_variable(m_var);
- const LEX_CSTRING *name= m_lex_keeper.cursor_name();
+ const LEX_CSTRING *name= m_ctx->find_cursor(m_cursor);
str->append(STRING_WITH_LEN("cursor_copy_struct "));
str->append(name);
str->append(' ');
@@ -4974,7 +4975,8 @@ bool sp_head::add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont,
sp_instr *instr_copy_struct=
new (thd->mem_root) sp_instr_cursor_copy_struct(instructions(),
- spcont, pcursor->lex(),
+ spcont, coffset,
+ pcursor->lex(),
index->offset);
if (instr_copy_struct == NULL || add_instr(instr_copy_struct))
return true;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 5c9183f79ab..3ec8bba1b50 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -1001,12 +1001,10 @@ public:
class sp_lex_cursor: public sp_lex_local, public Query_arena
{
- LEX_CSTRING m_cursor_name;
public:
sp_lex_cursor(THD *thd, const LEX *oldlex, MEM_ROOT *mem_root_arg)
:sp_lex_local(thd, oldlex),
- Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP),
- m_cursor_name(null_clex_str)
+ Query_arena(mem_root_arg, STMT_INITIALIZED_FOR_SP)
{ }
sp_lex_cursor(THD *thd, const LEX *oldlex)
:sp_lex_local(thd, oldlex),
@@ -1034,8 +1032,6 @@ public:
thd->free_list= NULL;
return false;
}
- const LEX_CSTRING *cursor_name() const { return &m_cursor_name; }
- void set_cursor_name(const LEX_CSTRING *name) { m_cursor_name= *name; }
};
@@ -1210,10 +1206,6 @@ public:
m_lex->safe_to_cache_query= 0;
}
- const LEX_CSTRING *cursor_name() const
- {
- return m_lex->cursor_name();
- }
private:
LEX *m_lex;
@@ -1682,8 +1674,6 @@ public:
{ return m_handler; }
private:
-
-private:
/// Handler.
sp_handler *m_handler;
@@ -1762,7 +1752,8 @@ private:
/** This is DECLARE CURSOR */
-class sp_instr_cpush : public sp_instr
+class sp_instr_cpush : public sp_instr,
+ public sp_cursor
{
sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
void operator=(sp_instr_cpush &);
@@ -1861,11 +1852,14 @@ class sp_instr_cursor_copy_struct: public sp_instr
sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &);
void operator=(sp_instr_cursor_copy_struct &);
sp_lex_keeper m_lex_keeper;
+ uint m_cursor;
uint m_var;
public:
- sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx,
+ sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs,
sp_lex_cursor *lex, uint voffs)
- : sp_instr(ip, ctx), m_lex_keeper(lex, FALSE), m_var(voffs)
+ : sp_instr(ip, ctx), m_lex_keeper(lex, FALSE),
+ m_cursor(coffs),
+ m_var(voffs)
{}
virtual ~sp_instr_cursor_copy_struct()
{}
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 6166d1d9615..24777abe1c3 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -425,44 +425,32 @@ bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
}
-bool sp_rcontext::push_cursor(THD *thd, sp_lex_keeper *lex_keeper)
+void sp_rcontext::push_cursor(sp_cursor *c)
{
- /*
- We should create cursors in the callers arena, as
- it could be (and usually is) used in several instructions.
- */
- sp_cursor *c= new (callers_arena->mem_root) sp_cursor(thd, lex_keeper);
+ m_cstack[m_ccount++]= c;
+}
- if (c == NULL)
- return true;
- m_cstack[m_ccount++]= c;
- return false;
+void sp_rcontext::pop_cursor(THD *thd)
+{
+ DBUG_ASSERT(m_ccount > 0);
+ if (m_cstack[m_ccount - 1]->is_open())
+ m_cstack[m_ccount - 1]->close(thd);
+ m_ccount--;
}
-void sp_rcontext::pop_cursors(size_t count)
+void sp_rcontext::pop_cursors(THD *thd, size_t count)
{
DBUG_ASSERT(m_ccount >= count);
-
while (count--)
- delete m_cstack[--m_ccount];
+ pop_cursor(thd);
}
-bool sp_rcontext::push_handler(sp_handler *handler, uint first_ip)
+bool sp_rcontext::push_handler(sp_instr_hpush_jump *entry)
{
- /*
- We should create handler entries in the callers arena, as
- they could be (and usually are) used in several instructions.
- */
- sp_handler_entry *he=
- new (callers_arena->mem_root) sp_handler_entry(handler, first_ip);
-
- if (he == NULL)
- return true;
-
- return m_handlers.append(he);
+ return m_handlers.append(entry);
}
@@ -550,12 +538,12 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
DBUG_ASSERT(found_condition);
- sp_handler_entry *handler_entry= NULL;
+ sp_instr_hpush_jump *handler_entry= NULL;
for (size_t i= 0; i < m_handlers.elements(); ++i)
{
- sp_handler_entry *h= m_handlers.at(i);
+ sp_instr_hpush_jump *h= m_handlers.at(i);
- if (h->handler == found_handler)
+ if (h->get_handler() == found_handler)
{
handler_entry= h;
break;
@@ -584,7 +572,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
// Mark active conditions so that they can be deleted when the handler exits.
da->mark_sql_conditions_for_removal();
- uint continue_ip= handler_entry->handler->type == sp_handler::CONTINUE ?
+ uint continue_ip= handler_entry->get_handler()->type == sp_handler::CONTINUE ?
cur_spi->get_cont_dest() : 0;
/* End aborted result set. */
@@ -603,7 +591,7 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
new (callers_arena->mem_root) Handler_call_frame(cond_info, continue_ip);
m_handler_call_stack.append(frame);
- *ip= handler_entry->first_ip;
+ *ip= handler_entry->m_ip + 1;
DBUG_RETURN(true);
}
@@ -733,22 +721,6 @@ bool sp_rcontext::set_case_expr(THD *thd, int case_expr_id,
///////////////////////////////////////////////////////////////////////////
-sp_cursor::sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper):
- result(thd_arg),
- m_lex_keeper(lex_keeper),
- server_side_cursor(NULL),
- m_fetch_count(0),
- m_row_count(0),
- m_found(false)
-{
- /*
- currsor can't be stored in QC, so we should prevent opening QC for
- try to write results which are absent.
- */
- lex_keeper->disable_query_cache();
-}
-
-
/*
Open an SP cursor
@@ -811,8 +783,7 @@ int sp_cursor::close(THD *thd)
MYF(0));
return -1;
}
- m_row_count= m_fetch_count= 0;
- m_found= false;
+ sp_cursor_statistics::reset();
destroy();
return 0;
}
@@ -851,9 +822,15 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars, bool error_on_no_data)
result.set_spvar_list(vars);
+ DBUG_ASSERT(!thd->is_error());
+
/* Attempt to fetch one row */
if (server_side_cursor->is_open())
+ {
server_side_cursor->fetch(1);
+ if (thd->is_error())
+ return -1; // e.g. data type conversion failed
+ }
/*
If the cursor was pointing after the last row, the fetch will
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 33d76e1c85a..b02ba14b99b 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -31,6 +31,7 @@
class sp_cursor;
class sp_lex_keeper;
class sp_instr_cpush;
+class sp_instr_hpush_jump;
class Query_arena;
class sp_head;
class Item_cache;
@@ -87,27 +88,6 @@ private:
sp_rcontext(const sp_rcontext &);
void operator=(sp_rcontext &);
-private:
- /// This is an auxillary class to store entering instruction pointer for an
- /// SQL-handler.
- class sp_handler_entry : public Sql_alloc
- {
- public:
- /// Handler definition (from parsing context).
- const sp_handler *handler;
-
- /// Instruction pointer to the first instruction.
- uint first_ip;
-
- /// The constructor.
- ///
- /// @param _handler sp_handler object.
- /// @param _first_ip first instruction pointer.
- sp_handler_entry(const sp_handler *_handler, uint _first_ip)
- :handler(_handler), first_ip(_first_ip)
- { }
- };
-
public:
/// This class stores basic information about SQL-condition, such as:
/// - SQL error code;
@@ -235,18 +215,16 @@ public:
// SQL-handlers.
/////////////////////////////////////////////////////////////////////////
- /// Create a new sp_handler_entry instance and push it to the handler call
- /// stack.
+ /// Push an sp_instr_hpush_jump instance to the handler call stack.
///
- /// @param handler SQL-handler object.
- /// @param first_ip First instruction pointer of the handler.
+ /// @param entry The condition handler entry
///
/// @return error flag.
/// @retval false on success.
/// @retval true on error.
- bool push_handler(sp_handler *handler, uint first_ip);
+ bool push_handler(sp_instr_hpush_jump *entry);
- /// Pop and delete given number of sp_handler_entry instances from the handler
+ /// Pop and delete given number of instances from the handler
/// call stack.
///
/// @param count Number of handler entries to pop & delete.
@@ -293,23 +271,20 @@ public:
// Cursors.
/////////////////////////////////////////////////////////////////////////
- /// Create a new sp_cursor instance and push it to the cursor stack.
+ /// Push a cursor to the cursor stack.
///
- /// @param lex_keeper SP-instruction execution helper.
- /// @param i Cursor-push instruction.
+ /// @param cursor The cursor
///
- /// @return error flag.
- /// @retval false on success.
- /// @retval true on error.
- bool push_cursor(THD *thd, sp_lex_keeper *lex_keeper);
+ void push_cursor(sp_cursor *cur);
+ void pop_cursor(THD *thd);
/// Pop and delete given number of sp_cursor instance from the cursor stack.
///
/// @param count Number of cursors to pop & delete.
- void pop_cursors(size_t count);
+ void pop_cursors(THD *thd, size_t count);
- void pop_all_cursors()
- { pop_cursors(m_ccount); }
+ void pop_all_cursors(THD *thd)
+ { pop_cursors(thd, m_ccount); }
sp_cursor *get_cursor(uint i) const
{ return m_cstack[i]; }
@@ -414,7 +389,7 @@ private:
bool m_in_sub_stmt;
/// Stack of visible handlers.
- Dynamic_array<sp_handler_entry *> m_handlers;
+ Dynamic_array<sp_instr_hpush_jump *> m_handlers;
/// Stack of caught SQL conditions.
Dynamic_array<Handler_call_frame *> m_handler_call_stack;
@@ -429,74 +404,4 @@ private:
Bounds_checked_array<Item_cache *> m_case_expr_holders;
}; // class sp_rcontext : public Sql_alloc
-///////////////////////////////////////////////////////////////////////////
-// sp_cursor declaration.
-///////////////////////////////////////////////////////////////////////////
-
-class Server_side_cursor;
-typedef class st_select_lex_unit SELECT_LEX_UNIT;
-
-/* A mediator between stored procedures and server side cursors */
-
-class sp_cursor : public Sql_alloc
-{
-private:
- /// An interceptor of cursor result set used to implement
- /// FETCH <cname> INTO <varlist>.
- class Select_fetch_into_spvars: public select_result_interceptor
- {
- List<sp_variable> *spvar_list;
- uint field_count;
- bool send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items);
- public:
- Select_fetch_into_spvars(THD *thd_arg): select_result_interceptor(thd_arg) {}
- uint get_field_count() { return field_count; }
- void set_spvar_list(List<sp_variable> *vars) { spvar_list= vars; }
-
- virtual bool send_eof() { return FALSE; }
- virtual int send_data(List<Item> &items);
- virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
-};
-
-public:
- sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper);
-
- virtual ~sp_cursor()
- { destroy(); }
-
- sp_lex_keeper *get_lex_keeper() { return m_lex_keeper; }
-
- int open(THD *thd);
-
- int open_view_structure_only(THD *thd);
-
- int close(THD *thd);
-
- my_bool is_open()
- { return MY_TEST(server_side_cursor); }
-
- bool found() const
- { return m_found; }
-
- ulonglong row_count() const
- { return m_row_count; }
-
- ulonglong fetch_count() const
- { return m_fetch_count; }
-
- int fetch(THD *, List<sp_variable> *vars, bool error_on_no_data);
-
- bool export_structure(THD *thd, Row_definition_list *list);
-
-private:
- Select_fetch_into_spvars result;
- sp_lex_keeper *m_lex_keeper;
- Server_side_cursor *server_side_cursor;
- ulonglong m_fetch_count; // Number of FETCH commands since last OPEN
- ulonglong m_row_count; // Number of successful FETCH since last OPEN
- bool m_found; // If last FETCH fetched a row
- void destroy();
-
-}; // class sp_cursor : public Sql_alloc
-
#endif /* _SP_RCONTEXT_H_ */
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index aec15d38847..d00ee3e07ef 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -3766,7 +3766,8 @@ bool hostname_requires_resolving(const char *hostname)
void set_authentication_plugin_from_password(const User_table& user_table,
const char* password, size_t password_length)
{
- if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH)
+ if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH ||
+ password_length == 0)
{
user_table.plugin()->store(native_password_plugin_name.str,
native_password_plugin_name.length,
@@ -3821,13 +3822,16 @@ static bool update_user_table(THD *thd, const User_table& user_table,
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,record[1]);
- /* If the password column is missing, we use the
- authentication_string column. */
- if (user_table.password())
- user_table.password()->store(new_password, new_password_len, system_charset_info);
- else
+
+ if (user_table.plugin())
+ {
set_authentication_plugin_from_password(user_table, new_password,
new_password_len);
+ new_password_len= 0;
+ }
+
+ if (user_table.password())
+ user_table.password()->store(new_password, new_password_len, system_charset_info);
if (unlikely(error= table->file->ha_update_row(table->record[1],
@@ -7540,7 +7544,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
INSERT_ACL : SELECT_ACL);
}
- if (tl->with ||
+ if (tl->with || !tl->db.str ||
(tl->select_lex &&
(tl->with= tl->select_lex->find_table_def_in_with_clauses(tl))))
continue;
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index bf78bd12192..a96b0a5a32b 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- Copyright (c) 2016, MariaDB Corporation
+ Copyright (c) 2016, 2018, MariaDB Corporation
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -209,6 +209,35 @@ bool Alter_info::supports_lock(THD *thd, enum_alter_inplace_result result,
return false;
}
+bool Alter_info::vers_prohibited(THD *thd) const
+{
+ if (thd->slave_thread ||
+ thd->variables.vers_alter_history != VERS_ALTER_HISTORY_ERROR)
+ {
+ return false;
+ }
+ if (flags & (
+ ALTER_PARSER_ADD_COLUMN |
+ ALTER_PARSER_DROP_COLUMN |
+ ALTER_CHANGE_COLUMN |
+ ALTER_COLUMN_ORDER))
+ {
+ return true;
+ }
+ if (flags & ALTER_ADD_INDEX)
+ {
+ List_iterator_fast<Key> key_it(const_cast<List<Key> &>(key_list));
+ Key *key;
+ while ((key= key_it++))
+ {
+ if (key->type == Key::PRIMARY || key->type == Key::UNIQUE)
+ return true;
+ }
+ }
+ return false;
+}
+
+
Alter_table_ctx::Alter_table_ctx()
: datetime_field(NULL), error_if_not_empty(false),
tables_opened(0),
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 268dbc43abd..108b98afdd7 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -32,14 +32,7 @@ public:
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
- bool data_modifying() const
- {
- return flags & (
- ALTER_PARSER_ADD_COLUMN |
- ALTER_PARSER_DROP_COLUMN |
- ALTER_CHANGE_COLUMN |
- ALTER_COLUMN_ORDER);
- }
+ bool vers_prohibited(THD *thd) const;
/**
The different values of the ALGORITHM clause.
diff --git a/sql/sql_analyze_stmt.cc b/sql/sql_analyze_stmt.cc
index 2c09772bd66..b66d69334f0 100644
--- a/sql/sql_analyze_stmt.cc
+++ b/sql/sql_analyze_stmt.cc
@@ -45,7 +45,7 @@ void Filesort_tracker::print_json_members(Json_writer *writer)
else if (r_limit == 0)
writer->add_str(varied_str);
else
- writer->add_ll((longlong) rint(r_limit/get_r_loops()));
+ writer->add_ll((longlong) rint(r_limit));
}
writer->add_member("r_used_priority_queue");
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 094a77e74a1..6aafdcd7a71 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1572,6 +1572,12 @@ bool open_table(THD *thd, TABLE_LIST *table_list, Open_table_context *ot_ctx)
DBUG_RETURN(true);
}
+ if (!table_list->db.str)
+ {
+ my_error(ER_NO_DB_ERROR, MYF(0));
+ DBUG_RETURN(true);
+ }
+
key_length= get_table_def_key(table_list, &key);
/*
@@ -5585,6 +5591,9 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, si
column reference. See create_view_field() for details.
*/
item= nj_col->create_item(thd);
+ if (!item)
+ DBUG_RETURN(NULL);
+
/*
*ref != NULL means that *ref contains the item that we need to
replace. If the item was aliased by the user, set the alias to
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index df9c60ba6f0..77bc6494732 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -519,100 +519,6 @@ extern "C"
}
-/**
- Dumps a text description of a thread, its security context
- (user, host) and the current query.
-
- @param thd thread context
- @param buffer pointer to preferred result buffer
- @param length length of buffer
- @param max_query_len how many chars of query to copy (0 for all)
-
- @return Pointer to string
-*/
-
-extern "C"
-char *thd_get_error_context_description(THD *thd, char *buffer,
- unsigned int length,
- unsigned int max_query_len)
-{
- String str(buffer, length, &my_charset_latin1);
- const Security_context *sctx= &thd->main_security_ctx;
- char header[256];
- size_t len;
-
- /*
- The pointers thd->query and thd->proc_info might change since they are
- being modified concurrently. This is acceptable for proc_info since its
- values doesn't have to very accurate and the memory it points to is static,
- but we need to attempt a snapshot on the pointer values to avoid using NULL
- values. The pointer to thd->query however, doesn't point to static memory
- and has to be protected by thd->LOCK_thd_data or risk pointing to
- uninitialized memory.
- */
- const char *proc_info= thd->proc_info;
-
- len= my_snprintf(header, sizeof(header),
- "MySQL thread id %u, OS thread handle %lu, query id %llu",
- (uint)thd->thread_id, (ulong) thd->real_id, (ulonglong) thd->query_id);
- str.length(0);
- str.append(header, len);
-
- if (sctx->host)
- {
- str.append(' ');
- str.append(sctx->host);
- }
-
- if (sctx->ip)
- {
- str.append(' ');
- str.append(sctx->ip);
- }
-
- if (sctx->user)
- {
- str.append(' ');
- str.append(sctx->user);
- }
-
- if (proc_info)
- {
- str.append(' ');
- str.append(proc_info);
- }
-
- /* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
- if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
- {
- if (thd->query())
- {
- if (max_query_len < 1)
- len= thd->query_length();
- else
- len= MY_MIN(thd->query_length(), max_query_len);
- str.append('\n');
- str.append(thd->query(), len);
- }
- mysql_mutex_unlock(&thd->LOCK_thd_data);
- }
-
- if (str.c_ptr_safe() == buffer)
- return buffer;
-
- /*
- We have to copy the new string to the destination buffer because the string
- was reallocated to a larger buffer to be able to fit.
- */
- DBUG_ASSERT(buffer != NULL);
- length= MY_MIN(str.length(), length-1);
- memcpy(buffer, str.c_ptr_quick(), length);
- /* Make sure that the new string is null terminated */
- buffer[length]= '\0';
- return buffer;
-}
-
-
#if MARIA_PLUGIN_INTERFACE_VERSION < 0x0200
/**
TODO: This function is for API compatibility, remove it eventually.
@@ -1305,7 +1211,7 @@ void THD::init(bool skip_lock)
bzero((char *) &org_status_var, sizeof(org_status_var));
status_in_global= 0;
start_bytes_received= 0;
- last_commit_gtid.seq_no= 0;
+ m_last_commit_gtid.seq_no= 0;
last_stmt= NULL;
/* Reset status of last insert id */
arg_of_last_insert_id_function= FALSE;
@@ -3809,7 +3715,6 @@ void Query_arena::set_query_arena(Query_arena *set)
mem_root= set->mem_root;
free_list= set->free_list;
state= set->state;
- is_stored_procedure= set->is_stored_procedure;
}
@@ -7353,6 +7258,21 @@ THD::signal_wakeup_ready()
mysql_cond_signal(&COND_wakeup_ready);
}
+void THD::set_last_commit_gtid(rpl_gtid &gtid)
+{
+#ifndef EMBEDDED_LIBRARY
+ bool changed_gtid= (m_last_commit_gtid.seq_no != gtid.seq_no);
+#endif
+ m_last_commit_gtid= gtid;
+#ifndef EMBEDDED_LIBRARY
+ if (changed_gtid &&
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
+ {
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(this, (LEX_CSTRING*)Sys_last_gtid_ptr);
+ }
+#endif
+}
void
wait_for_commit::reinit()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 5adb5bf3823..359d5f93a1f 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -974,10 +974,6 @@ public:
enum_state state;
-protected:
- friend class sp_head;
- bool is_stored_procedure;
-
public:
/* We build without RTTI, so dynamic_cast can't be used. */
enum Type
@@ -986,8 +982,7 @@ public:
};
Query_arena(MEM_ROOT *mem_root_arg, enum enum_state state_arg) :
- free_list(0), mem_root(mem_root_arg), state(state_arg),
- is_stored_procedure(state_arg == STMT_INITIALIZED_FOR_SP ? true : false)
+ free_list(0), mem_root(mem_root_arg), state(state_arg)
{ INIT_ARENA_DBUG_INFO; }
/*
This constructor is used only when Query_arena is created as
@@ -3216,6 +3211,7 @@ public:
query_id_t first_query_id;
} binlog_evt_union;
+ mysql_cond_t COND_wsrep_thd;
/**
Internal parser state.
Note that since the parser is not re-entrant, we keep only one parser
@@ -3674,6 +3670,10 @@ public:
lex_str->length= length;
return lex_str;
}
+ LEX_CSTRING *make_clex_string(const LEX_CSTRING from)
+ {
+ return make_clex_string(from.str, from.length);
+ }
// Allocate LEX_STRING for character set conversion
bool alloc_lex_string(LEX_STRING *dst, size_t length)
@@ -4180,18 +4180,33 @@ public:
{
if (db.str == NULL)
{
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
- return TRUE;
+ /*
+ No default database is set. In this case if it's guaranteed that
+ no CTE can be used in the statement then we can throw an error right
+ now at the parser stage. Otherwise the decision about throwing such
+ a message must be postponed until a post-parser stage when we are able
+ to resolve all CTE names as we don't need this message to be thrown
+ for any CTE references.
+ */
+ if (!lex->with_clauses_list)
+ {
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ return TRUE;
+ }
+ /* This will allow to throw an error later for non-CTE references */
+ to->str= NULL;
+ to->length= 0;
+ return FALSE;
}
+
to->str= strmake(db.str, db.length);
to->length= db.length;
return to->str == NULL; /* True on error */
}
/* Get db name or "". Use for printing current db */
const char *get_db()
- {
- return db.str ? db.str : "";
- }
+ { return safe_str(db.str); }
+
thd_scheduler event_scheduler;
public:
@@ -4558,7 +4573,13 @@ public:
The GTID assigned to the last commit. If no GTID was assigned to any commit
so far, this is indicated by last_commit_gtid.seq_no == 0.
*/
- rpl_gtid last_commit_gtid;
+private:
+ rpl_gtid m_last_commit_gtid;
+
+public:
+ rpl_gtid get_last_commit_gtid() { return m_last_commit_gtid; }
+ void set_last_commit_gtid(rpl_gtid &gtid);
+
LF_PINS *tdc_hash_pins;
LF_PINS *xid_hash_pins;
@@ -4909,6 +4930,7 @@ public:
*/
virtual int send_data(List<Item> &items)=0;
virtual ~select_result_sink() {};
+ void reset(THD *thd_arg) { thd= thd_arg; }
};
@@ -4986,6 +5008,11 @@ public:
*/
virtual void cleanup();
void set_thd(THD *thd_arg) { thd= thd_arg; }
+ void reset(THD *thd_arg)
+ {
+ select_result_sink::reset(thd_arg);
+ unit= NULL;
+ }
#ifdef EMBEDDED_LIBRARY
virtual void begin_dataset() {}
#else
@@ -5082,11 +5109,114 @@ public:
elsewhere. (this is used by ANALYZE $stmt feature).
*/
void disable_my_ok_calls() { suppress_my_ok= true; }
+ void reset(THD *thd_arg)
+ {
+ select_result::reset(thd_arg);
+ suppress_my_ok= false;
+ }
protected:
bool suppress_my_ok;
};
+class sp_cursor_statistics
+{
+protected:
+ ulonglong m_fetch_count; // Number of FETCH commands since last OPEN
+ ulonglong m_row_count; // Number of successful FETCH since last OPEN
+ bool m_found; // If last FETCH fetched a row
+public:
+ sp_cursor_statistics()
+ :m_fetch_count(0),
+ m_row_count(0),
+ m_found(false)
+ { }
+ bool found() const
+ { return m_found; }
+
+ ulonglong row_count() const
+ { return m_row_count; }
+
+ ulonglong fetch_count() const
+ { return m_fetch_count; }
+ void reset() { *this= sp_cursor_statistics(); }
+};
+
+
+/* A mediator between stored procedures and server side cursors */
+class sp_lex_keeper;
+class sp_cursor: public sp_cursor_statistics
+{
+private:
+ /// An interceptor of cursor result set used to implement
+ /// FETCH <cname> INTO <varlist>.
+ class Select_fetch_into_spvars: public select_result_interceptor
+ {
+ List<sp_variable> *spvar_list;
+ uint field_count;
+ bool send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items);
+ public:
+ Select_fetch_into_spvars(THD *thd_arg): select_result_interceptor(thd_arg) {}
+ void reset(THD *thd_arg)
+ {
+ select_result_interceptor::reset(thd_arg);
+ spvar_list= NULL;
+ field_count= 0;
+ }
+ uint get_field_count() { return field_count; }
+ void set_spvar_list(List<sp_variable> *vars) { spvar_list= vars; }
+
+ virtual bool send_eof() { return FALSE; }
+ virtual int send_data(List<Item> &items);
+ virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
+};
+
+public:
+ sp_cursor()
+ :result(NULL),
+ m_lex_keeper(NULL),
+ server_side_cursor(NULL)
+ { }
+ sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper)
+ :result(thd_arg),
+ m_lex_keeper(lex_keeper),
+ server_side_cursor(NULL)
+ {}
+
+ virtual ~sp_cursor()
+ { destroy(); }
+
+ sp_lex_keeper *get_lex_keeper() { return m_lex_keeper; }
+
+ int open(THD *thd);
+
+ int open_view_structure_only(THD *thd);
+
+ int close(THD *thd);
+
+ my_bool is_open()
+ { return MY_TEST(server_side_cursor); }
+
+ int fetch(THD *, List<sp_variable> *vars, bool error_on_no_data);
+
+ bool export_structure(THD *thd, Row_definition_list *list);
+
+ void reset(THD *thd_arg, sp_lex_keeper *lex_keeper)
+ {
+ sp_cursor_statistics::reset();
+ result.reset(thd_arg);
+ m_lex_keeper= lex_keeper;
+ server_side_cursor= NULL;
+ }
+
+private:
+ Select_fetch_into_spvars result;
+ sp_lex_keeper *m_lex_keeper;
+ Server_side_cursor *server_side_cursor;
+ void destroy();
+};
+
+
class select_send :public select_result {
/**
True if we have sent result set metadata to the client.
@@ -5950,6 +6080,7 @@ public:
void prepare_to_read_rows();
};
+class my_var_sp;
class my_var : public Sql_alloc {
public:
const LEX_CSTRING name;
@@ -5958,7 +6089,7 @@ public:
my_var(const LEX_CSTRING *j, enum type s) : name(*j), scope(s) { }
virtual ~my_var() {}
virtual bool set(THD *thd, Item *val) = 0;
- virtual class my_var_sp *get_my_var_sp() { return NULL; }
+ virtual my_var_sp *get_my_var_sp() { return NULL; }
};
class my_var_sp: public my_var {
@@ -6244,8 +6375,6 @@ inline int handler::ha_ft_read(uchar *buf)
inline int handler::ha_rnd_pos_by_record(uchar *buf)
{
int error= rnd_pos_by_record(buf);
- if (!error)
- update_rows_read();
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
diff --git a/sql/sql_digest.cc b/sql/sql_digest.cc
index 54ed1c3f225..a8afd33c46a 100644
--- a/sql/sql_digest.cc
+++ b/sql/sql_digest.cc
@@ -32,7 +32,7 @@
#include "sql_get_diagnostics.h"
/* Generated code */
-#include "sql_yacc.h"
+#include "sql_yacc.hh"
#define LEX_TOKEN_WITH_DEFINITION
#include "lex_token.h"
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 5d977c6d5c2..1c45b05ccc5 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -1693,7 +1693,7 @@ void Explain_table_access::print_explain_json(Explain_query *query,
{
/* Get r_filtered value from filesort */
if (pre_join_sort->tracker.get_r_loops())
- writer->add_double(pre_join_sort->tracker.get_r_filtered());
+ writer->add_double(pre_join_sort->tracker.get_r_filtered()*100);
else
writer->add_null();
}
@@ -2516,4 +2516,3 @@ void Explain_range_checked_fer::print_json(Json_writer *writer,
writer->end_object();
}
}
-
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 7c2ccf1b155..72df8367dc7 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -1029,6 +1029,7 @@ SQL_HANDLER *mysql_ha_read_prepare(THD *thd, TABLE_LIST *tables,
if (!(handler= mysql_ha_find_handler(thd, &tables->alias)))
DBUG_RETURN(0);
tables->table= handler->table; // This is used by fix_fields
+ handler->table->pos_in_table_list= tables;
if (mysql_ha_fix_cond_and_key(handler, mode, keyname, key_expr,
ha_rkey_mode, cond, 1))
DBUG_RETURN(0);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 6eefa322bf2..e3c53e59d21 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1970,13 +1970,12 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
error= table->file->ha_delete_row(table->record[1]);
else
{
- DBUG_ASSERT(table->insert_values);
- store_record(table,insert_values);
- restore_record(table,record[1]);
+ store_record(table, record[2]);
+ restore_record(table, record[1]);
table->vers_update_end();
error= table->file->ha_update_row(table->record[1],
table->record[0]);
- restore_record(table,insert_values);
+ restore_record(table, record[2]);
}
if (unlikely(error))
goto err;
@@ -4562,12 +4561,44 @@ bool select_create::send_eof()
*/
if (!table->s->tmp_table)
{
+#ifdef WITH_WSREP
+ if (WSREP_ON)
+ {
+ /*
+ append table level exclusive key for CTAS
+ */
+ wsrep_key_arr_t key_arr= {0, 0};
+ wsrep_prepare_keys_for_isolation(thd,
+ create_table->db.str,
+ create_table->table_name.str,
+ table_list,
+ &key_arr);
+ int rcode = wsrep->append_key(
+ wsrep,
+ &thd->wsrep_ws_handle,
+ key_arr.keys, //&wkey,
+ key_arr.keys_len,
+ WSREP_KEY_EXCLUSIVE,
+ false);
+ wsrep_keys_free(&key_arr);
+ if (rcode) {
+ DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
+ WSREP_ERROR("Appending table key for CTAS failed: %s, %d",
+ (wsrep_thd_query(thd)) ?
+ wsrep_thd_query(thd) : "void", rcode);
+ return true;
+ }
+ /* If commit fails, we should be able to reset the OK status. */
+ thd->get_stmt_da()->set_overwrite_status(TRUE);
+ }
+#endif /* WITH_WSREP */
trans_commit_stmt(thd);
if (!(thd->variables.option_bits & OPTION_GTID_BEGIN))
trans_commit_implicit(thd);
#ifdef WITH_WSREP
if (WSREP_ON)
{
+ thd->get_stmt_da()->set_overwrite_status(FALSE);
mysql_mutex_lock(&thd->LOCK_thd_data);
if (thd->wsrep_conflict_state != NO_CONFLICT)
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9922bdf7e59..ec38baa219a 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -2255,6 +2255,7 @@ void st_select_lex::init_query()
cond_pushed_into_where= cond_pushed_into_having= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
+ having_fix_field_for_pushed_cond= 0;
context.select_lex= this;
context.init();
/*
@@ -5480,7 +5481,8 @@ LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
spvar->field_def.set_cursor_rowtype_ref(offset);
sp_instr_cursor_copy_struct *instr=
new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(),
- spcont, pcursor->lex(),
+ spcont, offset,
+ pcursor->lex(),
spvar->offset);
if (instr == NULL || sphead->add_instr(instr))
return true;
@@ -5887,6 +5889,26 @@ bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop)
return sp_while_loop_finalize(thd);
}
+bool LEX::sp_for_loop_outer_block_finalize(THD *thd,
+ const Lex_for_loop_st &loop)
+{
+ Lex_spblock tmp;
+ tmp.curs= MY_TEST(loop.m_implicit_cursor);
+ if (unlikely(sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
+ return true;
+ if (!loop.is_for_loop_explicit_cursor())
+ return false;
+ /*
+ Explicit cursor FOR loop must close the cursor automatically.
+ Note, implicit cursor FOR loop does not need to close the cursor,
+ it's closed by sp_instr_cpop.
+ */
+ sp_instr_cclose *ic= new (thd->mem_root)
+ sp_instr_cclose(sphead->instructions(), spcont,
+ loop.m_cursor_offset);
+ return ic == NULL || sphead->add_instr(ic);
+}
+
/***************************************************************************/
bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
@@ -5901,7 +5923,6 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
my_error(ER_SP_DUP_CURS, MYF(0), name->str);
return true;
}
- cursor_stmt->set_cursor_name(name);
if (unlikely(spcont->add_cursor(name, param_ctx, cursor_stmt)))
return true;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index ebf643a5aa1..5cc46aa8615 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -269,10 +269,10 @@ struct LEX_TYPE
#else
#include "lex_symbol.h"
#ifdef MYSQL_LEX
-#include "item_func.h" /* Cast_target used in sql_yacc.h */
-#include "sql_get_diagnostics.h" /* Types used in sql_yacc.h */
+#include "item_func.h" /* Cast_target used in sql_yacc.hh */
+#include "sql_get_diagnostics.h" /* Types used in sql_yacc.hh */
#include "sp_pcontext.h"
-#include "sql_yacc.h"
+#include "sql_yacc.hh"
#define LEX_YYSTYPE YYSTYPE *
#else
#define LEX_YYSTYPE void *
@@ -1064,6 +1064,11 @@ public:
bool automatic_brackets; /* dummy select for INTERSECT precedence */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
+ /*
+ TRUE when fix field is called for a new condition pushed into the
+ HAVING clause of this SELECT
+ */
+ bool having_fix_field_for_pushed_cond;
/* List of references to fields referenced from inner selects */
List<Item_outer_ref> inner_refs_list;
/* Number of Item_sum-derived objects in this SELECT */
@@ -3177,8 +3182,6 @@ public:
return NULL;
}
- virtual const LEX_CSTRING *cursor_name() const { return &null_clex_str; }
-
void start(THD *thd);
inline bool is_ps_or_view_context_analysis()
@@ -3802,6 +3805,7 @@ public:
sp_for_loop_cursor_finalize(thd, loop) :
sp_for_loop_intrange_finalize(thd, loop);
}
+ bool sp_for_loop_outer_block_finalize(THD *thd, const Lex_for_loop_st &loop);
/* End of FOR LOOP methods */
bool add_signal_statement(THD *thd, const class sp_condition_value *value);
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index cc5a5c7c794..ddb5029c78a 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -431,13 +431,6 @@ int mysql_load(THD *thd, const sql_exchange *ex, TABLE_LIST *table_list,
is_concurrent= (table_list->lock_type == TL_WRITE_CONCURRENT_INSERT);
#endif
- if (table->versioned(VERS_TIMESTAMP) && handle_duplicates == DUP_REPLACE)
- {
- // Additional memory may be required to create historical items.
- if (table_list->set_insert_values(thd->mem_root))
- DBUG_RETURN(TRUE);
- }
-
if (!fields_vars.elements)
{
Field_iterator_table_ref field_iterator;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index a722bebe7bc..e981ed6d3f1 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3689,6 +3689,7 @@ mysql_execute_command(THD *thd)
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_SHOW);
execute_show_status(thd, all_tables);
+
break;
}
case SQLCOM_SHOW_EXPLAIN:
@@ -4753,7 +4754,7 @@ end_with_restore_list:
case SQLCOM_INSERT_SELECT:
{
WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE);
- select_result *sel_result;
+ select_insert *sel_result;
bool explain= MY_TEST(lex->describe);
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (WSREP_CLIENT(thd) &&
@@ -6753,11 +6754,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
THD_STAGE_INFO(thd, stage_checking_permissions);
if (unlikely((!db || !db[0]) && !thd->db.str && !dont_check_global_grants))
{
- DBUG_PRINT("error",("No database"));
- if (!no_errors)
- my_message(ER_NO_DB_ERROR, ER_THD(thd, ER_NO_DB_ERROR),
- MYF(0)); /* purecov: tested */
- DBUG_RETURN(TRUE); /* purecov: tested */
+ DBUG_RETURN(FALSE); // CTE reference or an error later
}
if (likely((db != NULL) && (db != any_db)))
@@ -8384,7 +8381,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
lex->add_to_query_tables(ptr);
// Pure table aliases do not need to be locked:
- if (!MY_TEST(table_options & TL_OPTION_ALIAS))
+ if (ptr->db.str && !(table_options & TL_OPTION_ALIAS))
{
ptr->mdl_request.init(MDL_key::TABLE, ptr->db.str, ptr->table_name.str,
mdl_type,
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index ac1524381c7..8c231d9b8f7 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -2156,8 +2156,7 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name,
tables.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PLUGIN_NAME, 0, TL_WRITE);
if (!opt_noacl && check_table_access(thd, INSERT_ACL, &tables, FALSE, 1, FALSE))
DBUG_RETURN(TRUE);
-
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* need to open before acquiring LOCK_plugin or it will deadlock */
if (! (table = open_ltable(thd, &tables, TL_WRITE,
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index aa07dc07aa2..2ee175293de 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -2572,6 +2572,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
linfo->pos= my_b_tell(log);
info->last_pos= my_b_tell(log);
+ log->end_of_file= end_pos;
while (linfo->pos < end_pos)
{
if (should_stop(info))
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 25b01e49a2f..536c14798d1 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -822,8 +822,10 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables)
lock_type= TL_READ; // ignore TL_WRITE, history is immutable anyway
}
- const LEX_CSTRING *fstart= &table->table->vers_start_field()->field_name;
- const LEX_CSTRING *fend= &table->table->vers_end_field()->field_name;
+ const LEX_CSTRING *fstart=
+ thd->make_clex_string(table->table->vers_start_field()->field_name);
+ const LEX_CSTRING *fend=
+ thd->make_clex_string(table->table->vers_end_field()->field_name);
Item *row_start=
newx Item_field(thd, &this->context, table->db.str, table->alias.str, fstart);
@@ -1674,9 +1676,11 @@ JOIN::optimize_inner()
if (having)
{
select_lex->having_fix_field= 1;
+ select_lex->having_fix_field_for_pushed_cond= 1;
if (having->fix_fields(thd, &having))
DBUG_RETURN(1);
select_lex->having_fix_field= 0;
+ select_lex->having_fix_field_for_pushed_cond= 0;
}
}
@@ -1780,10 +1784,18 @@ JOIN::optimize_inner()
if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
{ /* Impossible cond */
- DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE"));
- zero_result_cause= having_value == Item::COND_FALSE ?
- "Impossible HAVING" : "Impossible WHERE";
+ if (unit->select_limit_cnt)
+ {
+ DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE"));
+ zero_result_cause= having_value == Item::COND_FALSE ?
+ "Impossible HAVING" : "Impossible WHERE";
+ }
+ else
+ {
+ DBUG_PRINT("info", ("Zero limit"));
+ zero_result_cause= "Zero limit";
+ }
table_count= top_join_tab_count= 0;
error= 0;
subq_exit_fl= true;
@@ -10432,7 +10444,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
table_map current_map;
i= join->const_tables;
for (tab= first_depth_first_tab(join); tab;
- tab= next_depth_first_tab(join, tab), i++)
+ tab= next_depth_first_tab(join, tab))
{
bool is_hj;
@@ -10917,6 +10929,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
}
first_inner_tab= first_inner_tab->first_upper;
}
+ if (!tab->bush_children)
+ i++;
}
}
DBUG_RETURN(0);
@@ -14077,7 +14091,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
List_iterator_fast<Item_equal> it(cond_equal.current_level);
while ((item_equal= it++))
{
- item_equal->fix_length_and_dec();
+ if (item_equal->fix_length_and_dec())
+ return NULL;
item_equal->update_used_tables();
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->n_field_items());
@@ -16687,7 +16702,8 @@ Item_field::create_tmp_field_from_item_field(TABLE *new_table,
Record_addr rec(orig_item ? orig_item->maybe_null : maybe_null);
const Type_handler *handler= type_handler()->
type_handler_for_tmp_table(this);
- result= handler->make_and_init_table_field(&name, rec, *this, new_table);
+ result= handler->make_and_init_table_field(orig_item ? &orig_item->name : &name,
+ rec, *this, new_table);
}
else if (param->table_cant_handle_bit_fields() &&
field->type() == MYSQL_TYPE_BIT)
@@ -26276,21 +26292,18 @@ void JOIN::set_allowed_join_cache_types()
void JOIN::save_query_plan(Join_plan_state *save_to)
{
- if (keyuse.elements)
- {
- DYNAMIC_ARRAY tmp_keyuse;
- /* Swap the current and the backup keyuse internal arrays. */
- tmp_keyuse= keyuse;
- keyuse= save_to->keyuse; /* keyuse is reset to an empty array. */
- save_to->keyuse= tmp_keyuse;
+ DYNAMIC_ARRAY tmp_keyuse;
+ /* Swap the current and the backup keyuse internal arrays. */
+ tmp_keyuse= keyuse;
+ keyuse= save_to->keyuse; /* keyuse is reset to an empty array. */
+ save_to->keyuse= tmp_keyuse;
- for (uint i= 0; i < table_count; i++)
- {
- save_to->join_tab_keyuse[i]= join_tab[i].keyuse;
- join_tab[i].keyuse= NULL;
- save_to->join_tab_checked_keys[i]= join_tab[i].checked_keys;
- join_tab[i].checked_keys.clear_all();
- }
+ for (uint i= 0; i < table_count; i++)
+ {
+ save_to->join_tab_keyuse[i]= join_tab[i].keyuse;
+ join_tab[i].keyuse= NULL;
+ save_to->join_tab_checked_keys[i]= join_tab[i].checked_keys;
+ join_tab[i].checked_keys.clear_all();
}
memcpy((uchar*) save_to->best_positions, (uchar*) best_positions,
sizeof(POSITION) * (table_count + 1));
@@ -26328,20 +26341,17 @@ void JOIN::reset_query_plan()
void JOIN::restore_query_plan(Join_plan_state *restore_from)
{
- if (restore_from->keyuse.elements)
- {
- DYNAMIC_ARRAY tmp_keyuse;
- tmp_keyuse= keyuse;
- keyuse= restore_from->keyuse;
- restore_from->keyuse= tmp_keyuse;
-
- for (uint i= 0; i < table_count; i++)
- {
- join_tab[i].keyuse= restore_from->join_tab_keyuse[i];
- join_tab[i].checked_keys= restore_from->join_tab_checked_keys[i];
- }
+ DYNAMIC_ARRAY tmp_keyuse;
+ tmp_keyuse= keyuse;
+ keyuse= restore_from->keyuse;
+ restore_from->keyuse= tmp_keyuse;
+ for (uint i= 0; i < table_count; i++)
+ {
+ join_tab[i].keyuse= restore_from->join_tab_keyuse[i];
+ join_tab[i].checked_keys= restore_from->join_tab_checked_keys[i];
}
+
memcpy((uchar*) best_positions, (uchar*) restore_from->best_positions,
sizeof(POSITION) * (table_count + 1));
/* Restore SJM nests */
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 4923c628bf9..2484b5039ad 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2707,6 +2707,9 @@ static const char *thread_state_info(THD *tmp)
return "";
return "Reading from net";
}
+#else
+ if (tmp->get_command() == COM_SLEEP)
+ return "";
#endif
if (tmp->proc_info)
@@ -10316,3 +10319,85 @@ static void get_cs_converted_string_value(THD *thd,
return;
}
#endif
+
+/**
+ Dumps a text description of a thread, its security context
+ (user, host) and the current query.
+
+ @param thd thread context
+ @param buffer pointer to preferred result buffer
+ @param length length of buffer
+ @param max_query_len how many chars of query to copy (0 for all)
+
+ @return Pointer to string
+*/
+
+extern "C"
+char *thd_get_error_context_description(THD *thd, char *buffer,
+ unsigned int length,
+ unsigned int max_query_len)
+{
+ String str(buffer, length, &my_charset_latin1);
+ const Security_context *sctx= &thd->main_security_ctx;
+ char header[256];
+ size_t len;
+
+ len= my_snprintf(header, sizeof(header),
+ "MySQL thread id %u, OS thread handle %lu, query id %llu",
+ (uint)thd->thread_id, (ulong) thd->real_id, (ulonglong) thd->query_id);
+ str.length(0);
+ str.append(header, len);
+
+ if (sctx->host)
+ {
+ str.append(' ');
+ str.append(sctx->host);
+ }
+
+ if (sctx->ip)
+ {
+ str.append(' ');
+ str.append(sctx->ip);
+ }
+
+ if (sctx->user)
+ {
+ str.append(' ');
+ str.append(sctx->user);
+ }
+
+ /* Don't wait if LOCK_thd_data is used as this could cause a deadlock */
+ if (!mysql_mutex_trylock(&thd->LOCK_thd_data))
+ {
+ if (const char *info= thread_state_info(thd))
+ {
+ str.append(' ');
+ str.append(info);
+ }
+
+ if (thd->query())
+ {
+ if (max_query_len < 1)
+ len= thd->query_length();
+ else
+ len= MY_MIN(thd->query_length(), max_query_len);
+ str.append('\n');
+ str.append(thd->query(), len);
+ }
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+ }
+
+ if (str.c_ptr_safe() == buffer)
+ return buffer;
+
+ /*
+ We have to copy the new string to the destination buffer because the string
+ was reallocated to a larger buffer to be able to fit.
+ */
+ DBUG_ASSERT(buffer != NULL);
+ length= MY_MIN(str.length(), length-1);
+ memcpy(buffer, str.c_ptr_quick(), length);
+ /* Make sure that the new string is null terminated */
+ buffer[length]= '\0';
+ return buffer;
+}
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 4edcb779379..00ed7fb0202 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -3095,7 +3095,7 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && tl->table)
+ if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
@@ -3107,7 +3107,7 @@ bool statistics_for_tables_is_needed(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && tl->table)
+ if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
@@ -3236,7 +3236,7 @@ int read_statistics_for_tables_if_needed(THD *thd, TABLE_LIST *tables)
for (TABLE_LIST *tl= tables; tl; tl= tl->next_global)
{
- if (!tl->is_view_or_derived() && tl->table)
+ if (!tl->is_view_or_derived() && !is_temporary_table(tl) && tl->table)
{
TABLE_SHARE *table_share= tl->table->s;
if (table_share &&
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4ac8b102d79..04fd7bf6e32 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -4961,7 +4961,12 @@ int create_table_impl(THD *thd,
file= mysql_create_frm_image(thd, orig_db, orig_table_name, create_info,
alter_info, create_table_mode, key_info,
key_count, frm);
- if (!file)
+ /*
+ TODO: remove this check of thd->is_error() (now it intercept
+ errors in some val_*() methoids and bring some single place to
+ such error interception).
+ */
+ if (!file || thd->is_error())
goto err;
if (rea_create_table(thd, frm, path, db->str, table_name->str, create_info,
file, frm_only))
@@ -6232,8 +6237,11 @@ drop_create_field:
continue;
/* Check if the table already has a PRIMARY KEY */
- bool dup_primary_key= key->type == Key::PRIMARY &&
- table->s->primary_key != MAX_KEY;
+ bool dup_primary_key=
+ key->type == Key::PRIMARY &&
+ table->s->primary_key != MAX_KEY &&
+ (keyname= table->s->key_info[table->s->primary_key].name.str) &&
+ my_strcasecmp(system_charset_info, keyname, primary_key_name) == 0;
if (dup_primary_key)
goto remove_key;
@@ -6332,7 +6340,6 @@ remove_key:
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
- DBUG_ASSERT(thd->work_part_info == 0);
partition_info *tab_part_info= table->part_info;
thd->work_part_info= thd->lex->part_info;
if (tab_part_info)
@@ -6530,15 +6537,15 @@ static bool fill_alter_inplace_info(THD *thd,
ALTER_DROP_INDEX are replaced with versions that have higher granuality.
*/
- ha_alter_info->handler_flags|= (alter_info->flags &
- ~(ALTER_ADD_INDEX |
- ALTER_DROP_INDEX |
- ALTER_PARSER_ADD_COLUMN |
- ALTER_PARSER_DROP_COLUMN |
- ALTER_COLUMN_ORDER |
- ALTER_RENAME_COLUMN |
- ALTER_CHANGE_COLUMN |
- ALTER_COLUMN_UNVERSIONED));
+ alter_table_operations flags_to_remove=
+ ALTER_ADD_INDEX | ALTER_DROP_INDEX | ALTER_PARSER_ADD_COLUMN |
+ ALTER_PARSER_DROP_COLUMN | ALTER_COLUMN_ORDER | ALTER_RENAME_COLUMN |
+ ALTER_CHANGE_COLUMN;
+
+ if (!table->file->native_versioned())
+ flags_to_remove|= ALTER_COLUMN_UNVERSIONED;
+
+ ha_alter_info->handler_flags|= (alter_info->flags & ~flags_to_remove);
/*
Comparing new and old default values of column is cumbersome.
So instead of using such a comparison for detecting if default
@@ -7407,6 +7414,11 @@ static bool mysql_inplace_alter_table(THD *thd,
bool reopen_tables= false;
bool res;
+ /*
+ Set the truncated column values of thd as warning
+ for alter table.
+ */
+ thd->count_cuted_fields = CHECK_FIELD_WARN;
DBUG_ENTER("mysql_inplace_alter_table");
/*
@@ -7621,10 +7633,15 @@ static bool mysql_inplace_alter_table(THD *thd,
/*
Replace the old .FRM with the new .FRM, but keep the old name for now.
Rename to the new name (if needed) will be handled separately below.
+
+ TODO: remove this check of thd->is_error() (now it intercept
+ errors in some val_*() methoids and bring some single place to
+ such error interception).
*/
if (mysql_rename_table(db_type, &alter_ctx->new_db, &alter_ctx->tmp_name,
&alter_ctx->db, &alter_ctx->alias,
- FN_FROM_IS_TMP | NO_HA_TABLE))
+ FN_FROM_IS_TMP | NO_HA_TABLE) ||
+ thd->is_error())
{
// Since changes were done in-place, we can't revert them.
(void) quick_rm_table(thd, db_type,
@@ -9039,10 +9056,6 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
{
DBUG_ENTER("mysql_alter_table");
-#ifdef WITH_PARTITION_STORAGE_ENGINE
- thd->work_part_info= 0; // Used by partitioning
-#endif
-
/*
Check if we attempt to alter mysql.slow_log or
mysql.general_log table and return an error if
@@ -9115,8 +9128,7 @@ bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
DBUG_RETURN(true);
}
}
- if (alter_info->data_modifying() && !thd->slave_thread &&
- thd->variables.vers_alter_history == VERS_ALTER_HISTORY_ERROR)
+ if (alter_info->vers_prohibited(thd))
{
my_error(ER_VERS_ALTER_NOT_ALLOWED, MYF(0),
table_list->db.str, table_list->table_name.str);
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 7db4c6c3821..9f26bff3321 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -454,7 +454,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
my_error(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, MYF(0));
DBUG_RETURN(TRUE);
}
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
if (!create)
{
@@ -516,6 +515,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (err_status)
goto end;
}
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/* We should have only one table in table list. */
DBUG_ASSERT(tables->next_global == 0);
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 761349c0a95..10c2e7ebcb2 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -377,7 +377,7 @@ select_unit::create_result_table(THD *thd_arg, List<Item> *column_types,
table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- table->field[i]->flags &= ~PART_KEY_FLAG;
+ table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
if (create_table)
{
@@ -413,7 +413,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
incr_table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- incr_table->field[i]->flags &= ~PART_KEY_FLAG;
+ incr_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
TABLE *rec_table= 0;
if (! (rec_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
@@ -424,7 +424,7 @@ select_union_recursive::create_result_table(THD *thd_arg,
rec_table->keys_in_use_for_query.clear_all();
for (uint i=0; i < table->s->fields; i++)
- rec_table->field[i]->flags &= ~PART_KEY_FLAG;
+ rec_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
if (rec_tables.push_back(rec_table))
return true;
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 783c655d007..f262daad89d 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -435,7 +435,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
goto err;
}
- WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL)
+ WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL);
/*
ignore lock specs for CREATE statement
@@ -711,14 +711,14 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
lex->link_first_table_back(view, link_to_local);
DBUG_RETURN(0);
+#ifdef WITH_WSREP
+ error:
+ res= TRUE;
+#endif /* WITH_WSREP */
err:
lex->link_first_table_back(view, link_to_local);
unit->cleanup();
DBUG_RETURN(res || thd->is_error());
-#ifdef WITH_WSREP
- error:
- DBUG_RETURN(true);
-#endif /* WITH_WSREP */
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 0043f6495e7..dffc91ea465 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1213,7 +1213,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
Keywords that have different reserved status in std/oracle modes.
*/
%token <kwd> BODY_SYM /* Oracle-R */
-%token <kwd> COMMENT_SYM
%token <kwd> ELSIF_SYM /* Oracle, reserved in PL/SQL*/
%token <kwd> GOTO_SYM /* Oracle, reserved in PL/SQL*/
%token <kwd> OTHERS_SYM /* SQL-2011-N */
@@ -1276,6 +1275,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token <kwd> COLUMN_GET_SYM
%token <kwd> COLUMN_SYM /* SQL-2003-R */
%token <kwd> COLUMN_NAME_SYM /* SQL-2003-N */
+%token <kwd> COMMENT_SYM /* Oracle-R */
%token <kwd> COMMITTED_SYM /* SQL-2003-N */
%token <kwd> COMMIT_SYM /* SQL-2003-R */
%token <kwd> COMPACT_SYM
@@ -4729,9 +4729,7 @@ sp_labeled_control:
}
pop_sp_loop_label // The inner WHILE block
{
- Lex_spblock tmp;
- tmp.curs= MY_TEST($4.m_implicit_cursor);
- if (unlikely(Lex->sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
+ if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $4)))
MYSQL_YYABORT;
}
| sp_label REPEAT_SYM
@@ -4781,12 +4779,10 @@ sp_unlabeled_control:
sp_proc_stmts1
END FOR_SYM
{
- Lex_spblock tmp;
- tmp.curs= MY_TEST($3.m_implicit_cursor);
if (unlikely(Lex->sp_for_loop_finalize(thd, $3)))
MYSQL_YYABORT;
Lex->sp_pop_loop_empty_label(thd); // The inner WHILE block
- if (unlikely(Lex->sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
+ if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $3)))
MYSQL_YYABORT;
}
| REPEAT_SYM
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index d9c3ee22faf..933b9dd2429 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -607,7 +607,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
Keywords that have different reserved status in std/oracle modes.
*/
%token BODY_SYM /* Oracle-R */
-%token COMMENT_SYM
%token ELSIF_SYM /* Oracle, reserved in PL/SQL*/
%token GOTO_SYM /* Oracle, reserved in PL/SQL*/
%token OTHERS_SYM /* SQL-2011-N */
@@ -670,6 +669,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%token <kwd> COLUMN_GET_SYM
%token <kwd> COLUMN_SYM /* SQL-2003-R */
%token <kwd> COLUMN_NAME_SYM /* SQL-2003-N */
+%token <kwd> COMMENT_SYM /* Oracle-R */
%token <kwd> COMMITTED_SYM /* SQL-2003-N */
%token <kwd> COMMIT_SYM /* SQL-2003-R */
%token <kwd> COMPACT_SYM
@@ -4676,9 +4676,7 @@ sp_labeled_control:
}
pop_sp_loop_label // The inner WHILE block
{
- Lex_spblock tmp;
- tmp.curs= MY_TEST($4.m_implicit_cursor);
- if (unlikely(Lex->sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
+ if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $4)))
MYSQL_YYABORT;
}
| labels_declaration_oracle REPEAT_SYM
@@ -4728,12 +4726,10 @@ sp_unlabeled_control:
sp_proc_stmts1
END LOOP_SYM
{
- Lex_spblock tmp;
- tmp.curs= MY_TEST($3.m_implicit_cursor);
if (unlikely(Lex->sp_for_loop_finalize(thd, $3)))
MYSQL_YYABORT;
Lex->sp_pop_loop_empty_label(thd); // The inner WHILE block
- if (unlikely(Lex->sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
+ if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $3)))
MYSQL_YYABORT;
}
| REPEAT_SYM
@@ -15586,6 +15582,7 @@ keyword_sp_var_not_label:
| COLUMN_CREATE_SYM
| COLUMN_DELETE_SYM
| COLUMN_GET_SYM
+ | COMMENT_SYM
| DEALLOCATE_SYM
| EXAMINED_SYM
| EXCLUDE_SYM
diff --git a/sql/structs.h b/sql/structs.h
index d530dd73b7c..d8b95a3509a 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -720,6 +720,10 @@ public:
*this= other;
}
bool is_for_loop_cursor() const { return m_upper_bound == NULL; }
+ bool is_for_loop_explicit_cursor() const
+ {
+ return is_for_loop_cursor() && !m_implicit_cursor;
+ }
};
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 658bb0e2d1c..3ac84fb61cc 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -458,7 +458,7 @@ error_if_in_trans_or_substatement(THD *thd, int in_substatement_error,
return false;
}
-static bool check_has_super(sys_var *self, THD *thd, set_var *var)
+bool check_has_super(sys_var *self, THD *thd, set_var *var)
{
DBUG_ASSERT(self->scope() != sys_var::GLOBAL);// don't abuse check_has_super()
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -702,6 +702,8 @@ static Sys_var_struct Sys_character_set_client(
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_cs_client),
ON_UPDATE(fix_thd_charset));
+// for check changing
+export sys_var *Sys_character_set_client_ptr= &Sys_character_set_client;
static Sys_var_struct Sys_character_set_connection(
"character_set_connection", "The character set used for "
@@ -711,6 +713,8 @@ static Sys_var_struct Sys_character_set_connection(
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null),
ON_UPDATE(fix_thd_charset));
+// for check changing
+export sys_var *Sys_character_set_connection_ptr= &Sys_character_set_connection;
static Sys_var_struct Sys_character_set_results(
"character_set_results", "The character set used for returning "
@@ -718,6 +722,8 @@ static Sys_var_struct Sys_character_set_results(
SESSION_VAR(character_set_results), NO_CMD_LINE,
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_charset));
+// for check changing
+export sys_var *Sys_character_set_results_ptr= &Sys_character_set_results;
static Sys_var_struct Sys_character_set_filesystem(
"character_set_filesystem", "The filesystem character set",
@@ -1907,6 +1913,8 @@ static Sys_var_last_gtid Sys_last_gtid(
"or the empty string if none.",
READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE);
+export sys_var *Sys_last_gtid_ptr= &Sys_last_gtid; // for check changing
+
uchar *
Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base)
@@ -1917,8 +1925,9 @@ Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_CSTRING *base)
bool first= true;
str.length(0);
- if ((thd->last_commit_gtid.seq_no > 0 &&
- rpl_slave_state_tostring_helper(&str, &thd->last_commit_gtid, &first)) ||
+ rpl_gtid gtid= thd->get_last_commit_gtid();
+ if ((gtid.seq_no > 0 &&
+ rpl_slave_state_tostring_helper(&str, &gtid, &first)) ||
!(p= thd->strmake(str.ptr(), str.length())))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index 498204deb92..373df354268 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -147,9 +147,10 @@ public:
option.min_value= min_val;
option.max_value= max_val;
option.block_size= block_size;
- option.u_max_value= (uchar**)max_var_ptr();
- if (max_var_ptr())
- *max_var_ptr()= max_val;
+ if ((option.u_max_value= (uchar**) max_var_ptr()))
+ {
+ *((T*) option.u_max_value)= max_val;
+ }
global_var(T)= def_val;
SYSVAR_ASSERT(size == sizeof(T));
@@ -181,8 +182,8 @@ public:
var->save_result.ulonglong_value=
getopt_ull_limit_value(uv, &option, &unused);
- if (max_var_ptr() && (T)var->save_result.ulonglong_value > *max_var_ptr())
- var->save_result.ulonglong_value= *max_var_ptr();
+ if (max_var_ptr() && (T)var->save_result.ulonglong_value > get_max_var())
+ var->save_result.ulonglong_value= get_max_var();
fixed= fixed || var->save_result.ulonglong_value != uv;
}
@@ -198,8 +199,8 @@ public:
var->save_result.longlong_value=
getopt_ll_limit_value(v, &option, &unused);
- if (max_var_ptr() && (T)var->save_result.longlong_value > *max_var_ptr())
- var->save_result.longlong_value= *max_var_ptr();
+ if (max_var_ptr() && (T)var->save_result.longlong_value > get_max_var())
+ var->save_result.longlong_value= get_max_var();
fixed= fixed || var->save_result.longlong_value != v;
}
@@ -221,11 +222,7 @@ public:
void global_save_default(THD *thd, set_var *var)
{ var->save_result.ulonglong_value= option.def_value; }
private:
- T *max_var_ptr()
- {
- return scope() == SESSION ? (T*)(((uchar*)&max_system_variables) + offset)
- : 0;
- }
+ T get_max_var() { return *((T*) max_var_ptr()); }
uchar *default_value_ptr(THD *thd) { return (uchar*) &option.def_value; }
};
@@ -269,6 +266,9 @@ class Sys_var_typelib: public sys_var
{
protected:
TYPELIB typelib;
+ virtual bool check_maximum(THD *thd, set_var *var,
+ const char *c_val, longlong i_val)
+ { return FALSE; }
public:
Sys_var_typelib(const char *name_arg,
const char *comment, int flag_args, ptrdiff_t off,
@@ -304,17 +304,14 @@ public:
return true;
else
var->save_result.ulonglong_value--;
- }
- else
- {
- longlong tmp=var->value->val_int();
- if (tmp < 0 || tmp >= typelib.count)
- return true;
- else
- var->save_result.ulonglong_value= tmp;
+ return check_maximum(thd, var, res->ptr(), 0);
}
- return false;
+ longlong tmp=var->value->val_int();
+ if (tmp < 0 || tmp >= typelib.count)
+ return true;
+ var->save_result.ulonglong_value= tmp;
+ return check_maximum(thd, var, 0, tmp);
}
};
@@ -349,10 +346,28 @@ public:
substitute)
{
option.var_type|= GET_ENUM;
+ option.min_value= 0;
+ option.max_value= ULONG_MAX;
global_var(ulong)= def_val;
+ if ((option.u_max_value= (uchar**)max_var_ptr()))
+ {
+ *((ulong *) option.u_max_value)= ULONG_MAX;
+ }
SYSVAR_ASSERT(def_val < typelib.count);
SYSVAR_ASSERT(size == sizeof(ulong));
}
+ bool check_maximum(THD *thd, set_var *var,
+ const char *c_val, longlong i_val)
+ {
+ if (!max_var_ptr() ||
+ var->save_result.ulonglong_value <= get_max_var())
+ return FALSE;
+ var->save_result.ulonglong_value= get_max_var();
+
+ return c_val ? throw_bounds_warning(thd, name.str, c_val) :
+ throw_bounds_warning(thd, name.str, TRUE,
+ var->value->unsigned_flag, i_val);
+ }
bool session_update(THD *thd, set_var *var)
{
session_var(thd, ulong)= static_cast<ulong>(var->save_result.ulonglong_value);
@@ -375,6 +390,8 @@ public:
{ return valptr(thd, global_var(ulong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, (ulong)option.def_value); }
+
+ ulong get_max_var() { return *((ulong *) max_var_ptr()); }
};
/**
@@ -1341,12 +1358,30 @@ public:
substitute)
{
option.var_type|= GET_SET;
+ option.min_value= 0;
+ option.max_value= ~0ULL;
global_var(ulonglong)= def_val;
+ if ((option.u_max_value= (uchar**)max_var_ptr()))
+ {
+ *((ulonglong*) option.u_max_value)= ~0ULL;
+ }
SYSVAR_ASSERT(typelib.count > 0);
SYSVAR_ASSERT(typelib.count <= 64);
SYSVAR_ASSERT(def_val <= my_set_bits(typelib.count));
SYSVAR_ASSERT(size == sizeof(ulonglong));
}
+ bool check_maximum(THD *thd, set_var *var,
+ const char *c_val, longlong i_val)
+ {
+ if (!max_var_ptr() ||
+ (var->save_result.ulonglong_value & ~(get_max_var())) == 0)
+ return FALSE;
+ var->save_result.ulonglong_value&= get_max_var();
+
+ return c_val ? throw_bounds_warning(thd, name.str, c_val) :
+ throw_bounds_warning(thd, name.str, TRUE,
+ var->value->unsigned_flag, i_val);
+ }
bool do_check(THD *thd, set_var *var)
{
char buff[STRING_BUFFER_USUAL_SIZE];
@@ -1354,41 +1389,38 @@ public:
if (var->value->result_type() == STRING_RESULT)
{
- if (!(res=var->value->val_str_ascii(&str)))
+ char *error;
+ uint error_len;
+ bool not_used;
+
+ if (!(res= var->value->val_str_ascii_revert_empty_string_is_null(thd,
+ &str)))
return true;
- else
- {
- char *error;
- uint error_len;
- bool not_used;
- var->save_result.ulonglong_value=
- find_set(&typelib, res->ptr(), res->length(), NULL,
- &error, &error_len, &not_used);
- /*
- note, we only issue an error if error_len > 0.
- That is even while empty (zero-length) values are considered
- errors by find_set(), these errors are ignored here
- */
- if (unlikely(error_len))
- {
- ErrConvString err(error, error_len, res->charset());
- my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
- return true;
- }
- }
- }
- else
- {
- longlong tmp=var->value->val_int();
- if ((tmp < 0 && ! var->value->unsigned_flag)
- || (ulonglong)tmp > my_set_bits(typelib.count))
+ var->save_result.ulonglong_value=
+ find_set(&typelib, res->ptr(), res->length(), NULL,
+ &error, &error_len, &not_used);
+ /*
+ note, we only issue an error if error_len > 0.
+ That is even while empty (zero-length) values are considered
+ errors by find_set(), these errors are ignored here
+ */
+ if (error_len)
+ {
+ ErrConvString err(error, error_len, res->charset());
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name.str, err.ptr());
return true;
- else
- var->save_result.ulonglong_value= tmp;
+ }
+ return check_maximum(thd, var, res->ptr(), 0);
}
- return false;
+ longlong tmp=var->value->val_int();
+ if ((tmp < 0 && ! var->value->unsigned_flag)
+ || (ulonglong)tmp > my_set_bits(typelib.count))
+ return true;
+
+ var->save_result.ulonglong_value= tmp;
+ return check_maximum(thd, var, 0, tmp);
}
bool session_update(THD *thd, set_var *var)
{
@@ -1412,6 +1444,8 @@ public:
{ return valptr(thd, global_var(ulonglong)); }
uchar *default_value_ptr(THD *thd)
{ return valptr(thd, option.def_value); }
+
+ ulonglong get_max_var() { return *((ulonglong*) max_var_ptr()); }
};
/**
diff --git a/sql/sys_vars_shared.h b/sql/sys_vars_shared.h
index 48154c95a72..69382974175 100644
--- a/sql/sys_vars_shared.h
+++ b/sql/sys_vars_shared.h
@@ -28,6 +28,7 @@
#include <sql_priv.h>
#include "set_var.h"
+extern bool throw_bounds_warning(THD *thd, const char *name,const char *v);
extern bool throw_bounds_warning(THD *thd, const char *name,
bool fixed, bool is_unsigned, longlong v);
extern bool throw_bounds_warning(THD *thd, const char *name, bool fixed,
diff --git a/sql/table.cc b/sql/table.cc
index 73b1a6bd9b2..3d3bc3336ef 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1896,7 +1896,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
*/
uint vcol_info_length= (uint) strpos[12];
- DBUG_ASSERT(vcol_info_length); // Expect non-null expression
+ if (!vcol_info_length) // Expect non-null expression
+ goto err;
attr.frm_unpack_basic(strpos);
if (attr.frm_unpack_charset(share, strpos))
@@ -2575,6 +2576,8 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
reg_field->vcol_info= vcol_info;
share->virtual_fields++;
share->stored_fields--;
+ if (reg_field->flags & BLOB_FLAG)
+ share->virtual_not_stored_blob_fields++;
/* Correct stored_rec_length as non stored fields are last */
recpos= (uint) (reg_field->ptr - record);
if (share->stored_rec_length >= recpos)
@@ -3523,7 +3526,7 @@ partititon_err:
}
}
- outparam->mark_columns_used_by_check_constraints();
+ outparam->mark_columns_used_by_virtual_fields();
if (db_stat)
{
@@ -5260,6 +5263,8 @@ int TABLE::verify_constraints(bool ignore_failure)
if (check_constraints &&
!(in_use->variables.option_bits & OPTION_NO_CHECK_CONSTRAINT_CHECKS))
{
+ if (versioned() && !vers_end_field()->is_max())
+ return VIEW_CHECK_OK;
for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
{
/*
@@ -5271,7 +5276,7 @@ int TABLE::verify_constraints(bool ignore_failure)
{
my_error(ER_CONSTRAINT_FAILED,
MYF(ignore_failure ? ME_WARNING : 0), (*chk)->name.str,
- s->db.str, s->table_name.str);
+ s->db.str, s->error_table_name());
return ignore_failure ? VIEW_CHECK_SKIP : VIEW_CHECK_ERROR;
}
}
@@ -5951,6 +5956,8 @@ Item *create_view_field(THD *thd, TABLE_LIST *view, Item **field_ref,
Item *item= (new (thd->mem_root)
Item_direct_view_ref(thd, context, field_ref, view->alias.str,
name, view));
+ if (!item)
+ return NULL;
/*
Force creation of nullable item for the result tmp table for outer joined
views/derived tables.
@@ -6420,7 +6427,7 @@ void TABLE::mark_columns_needed_for_delete()
Field **reg_field;
for (reg_field= field ; *reg_field ; reg_field++)
{
- if ((*reg_field)->flags & PART_KEY_FLAG)
+ if ((*reg_field)->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG))
mark_column_with_deps(*reg_field);
}
need_signal= true;
@@ -6746,7 +6753,8 @@ bool TABLE::mark_virtual_columns_for_write(bool insert_fl
if (bitmap_is_set(write_set, tmp_vfield->field_index))
bitmap_updated|= mark_virtual_column_with_deps(tmp_vfield);
else if (tmp_vfield->vcol_info->stored_in_db ||
- (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG)))
+ (tmp_vfield->flags & (PART_KEY_FLAG | FIELD_IN_PART_FUNC_FLAG |
+ PART_INDIRECT_KEY_FLAG)))
{
bitmap_set_bit(write_set, tmp_vfield->field_index);
mark_virtual_column_with_deps(tmp_vfield);
@@ -6811,27 +6819,64 @@ bool TABLE::check_virtual_columns_marked_for_write()
/*
- Mark fields used by check constraints.
+ Mark fields used by check constraints into s->check_set.
+ Mark all fields used in an expression that is part of an index
+ with PART_INDIRECT_KEY_FLAG
+
This is done once for the TABLE_SHARE the first time the table is opened.
The marking must be done non-destructively to handle the case when
this could be run in parallely by two threads
*/
-void TABLE::mark_columns_used_by_check_constraints(void)
+void TABLE::mark_columns_used_by_virtual_fields(void)
{
MY_BITMAP *save_read_set;
- /* If there is no check constraints or if check_set is already initialized */
- if (!s->check_set || s->check_set_initialized)
+ Field **vfield_ptr;
+
+ /* If there is virtual fields are already initialized */
+ if (s->check_set_initialized)
return;
- save_read_set= read_set;
- read_set= s->check_set;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_lock(&s->LOCK_share);
+ if (s->check_set)
+ {
+ /* Mark fields used by check constraint */
+ save_read_set= read_set;
+ read_set= s->check_set;
+
+ for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
+ (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ read_set= save_read_set;
+ }
- for (Virtual_column_info **chk= check_constraints ; *chk ; chk++)
- (*chk)->expr->walk(&Item::register_field_in_read_map, 1, 0);
+ /*
+ mark all fields that part of a virtual indexed field with
+ PART_INDIRECT_KEY_FLAG. This is used to ensure that all fields
+ that are part of an index exits before write/delete/update.
- read_set= save_read_set;
+ As this code is only executed once per open share, it's reusing
+ existing functionality instead of adding an extra argument to
+ add_field_to_set_processor or adding another processor.
+ */
+ if (vfield)
+ {
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->flags & PART_KEY_FLAG)
+ (*vfield_ptr)->vcol_info->expr->walk(&Item::add_field_to_set_processor,
+ 1, this);
+ }
+ for (uint i= 0 ; i < s->fields ; i++)
+ {
+ if (bitmap_is_set(&tmp_set, i))
+ field[i]->flags|= PART_INDIRECT_KEY_FLAG;
+ }
+ bitmap_clear_all(&tmp_set);
+ }
s->check_set_initialized= 1;
+ if (s->tmp_table == NO_TMP_TABLE)
+ mysql_mutex_unlock(&s->LOCK_share);
}
/* Add fields used by CHECK CONSTRAINT to read map */
@@ -6879,6 +6924,52 @@ void TABLE::move_fields(Field **ptr, const uchar *to, const uchar *from)
}
+/*
+ Store all allocated virtual fields blob values
+ Used by InnoDB when calculating virtual fields for it's own internal
+ records
+*/
+
+void TABLE::remember_blob_values(String *blob_storage)
+{
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->type() == MYSQL_TYPE_BLOB &&
+ !(*vfield_ptr)->vcol_info->stored_in_db)
+ {
+ Field_blob *blob= ((Field_blob*) *vfield_ptr);
+ memcpy((void*) blob_storage, (void*) &blob->value, sizeof(blob->value));
+ blob_storage++;
+ blob->value.release();
+ }
+ }
+}
+
+
+/*
+ Restore all allocated virtual fields blob values
+ Used by InnoDB when calculating virtual fields for it's own internal
+ records
+*/
+
+void TABLE::restore_blob_values(String *blob_storage)
+{
+ Field **vfield_ptr;
+ for (vfield_ptr= vfield; *vfield_ptr; vfield_ptr++)
+ {
+ if ((*vfield_ptr)->type() == MYSQL_TYPE_BLOB &&
+ !(*vfield_ptr)->vcol_info->stored_in_db)
+ {
+ Field_blob *blob= ((Field_blob*) *vfield_ptr);
+ blob->value.free();
+ memcpy((void*) &blob->value, (void*) blob_storage, sizeof(blob->value));
+ blob_storage++;
+ }
+ }
+}
+
+
/**
@brief
Allocate space for keys
@@ -7622,7 +7713,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
update= bitmap_is_set(read_set, vf->field_index);
break;
case VCOL_UPDATE_FOR_REPLACE:
- update= ((!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= ((!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
bitmap_is_set(read_set, vf->field_index)) ||
update_all_columns);
if (update && (vf->flags & BLOB_FLAG))
@@ -7641,7 +7733,8 @@ int TABLE::update_virtual_fields(handler *h, enum_vcol_update_mode update_mode)
case VCOL_UPDATE_INDEXED:
case VCOL_UPDATE_INDEXED_FOR_UPDATE:
/* Read indexed fields that was not updated in VCOL_UPDATE_FOR_READ */
- update= (!vcol_info->stored_in_db && (vf->flags & PART_KEY_FLAG) &&
+ update= (!vcol_info->stored_in_db &&
+ (vf->flags & (PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG)) &&
!bitmap_is_set(read_set, vf->field_index));
swap_values= 1;
break;
@@ -7777,6 +7870,7 @@ void TABLE::vers_update_fields()
}
vers_end_field()->set_max();
+ bitmap_set_bit(read_set, vers_end_field()->field_index);
}
@@ -8206,7 +8300,15 @@ int TABLE_LIST::fetch_number_of_rows()
{
int error= 0;
if (jtbm_subselect)
+ {
+ if (jtbm_subselect->is_jtbm_merged)
+ {
+ table->file->stats.records= (ha_rows)jtbm_subselect->jtbm_record_count;
+ set_if_bigger(table->file->stats.records, 2);
+ table->used_stat_records= table->file->stats.records;
+ }
return 0;
+ }
if (is_materialized_derived() && !fill_me)
{
table->file->stats.records= ((select_unit*)(get_unit()->result))->records;
diff --git a/sql/table.h b/sql/table.h
index 785fd9f3427..b75fa9074a4 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -687,8 +687,11 @@ struct TABLE_SHARE
*/
uint null_bytes_for_compare;
uint fields; /* number of fields */
- uint stored_fields; /* number of stored fields, purely virtual not included */
+ /* number of stored fields, purely virtual not included */
+ uint stored_fields;
uint virtual_fields; /* number of purely virtual fields */
+ /* number of purely virtual not stored blobs */
+ uint virtual_not_stored_blob_fields;
uint null_fields; /* number of null fields */
uint blob_fields; /* number of blob fields */
uint varchar_fields; /* number of varchar fields */
@@ -1377,7 +1380,7 @@ public:
bool check_virtual_columns_marked_for_read();
bool check_virtual_columns_marked_for_write();
void mark_default_fields_for_write(bool insert_fl);
- void mark_columns_used_by_check_constraints(void);
+ void mark_columns_used_by_virtual_fields(void);
void mark_check_constraint_columns_for_read(void);
int verify_constraints(bool ignore_failure);
inline void column_bitmaps_set(MY_BITMAP *read_set_arg)
@@ -1459,6 +1462,8 @@ public:
{ return (my_ptrdiff_t) (s->default_values - record[0]); }
void move_fields(Field **ptr, const uchar *to, const uchar *from);
+ void remember_blob_values(String *blob_storage);
+ void restore_blob_values(String *blob_storage);
uint actual_n_key_parts(KEY *keyinfo);
ulong actual_key_flags(KEY *keyinfo);
diff --git a/sql/wsrep_hton.cc b/sql/wsrep_hton.cc
index 3ffd5d7706b..d4d35d752be 100644
--- a/sql/wsrep_hton.cc
+++ b/sql/wsrep_hton.cc
@@ -119,7 +119,7 @@ void wsrep_post_commit(THD* thd, bool all)
switch (thd->wsrep_exec_mode)
{
- case LOCAL_COMMIT:
+ case LOCAL_COMMIT:
{
DBUG_ASSERT(thd->wsrep_trx_meta.gtid.seqno != WSREP_SEQNO_UNDEFINED);
if (wsrep && wsrep->post_commit(wsrep, &thd->wsrep_ws_handle))
@@ -131,18 +131,30 @@ void wsrep_post_commit(THD* thd, bool all)
wsrep_cleanup_transaction(thd);
break;
}
- case LOCAL_STATE:
- {
- /*
- Non-InnoDB statements may have populated events in stmt cache => cleanup
- */
- WSREP_DEBUG("cleanup transaction for LOCAL_STATE: %s", thd->query());
- wsrep_cleanup_transaction(thd);
- break;
- }
- default: break;
+ case LOCAL_STATE:
+ {
+ /* non-InnoDB statements may have populated events in stmt cache
+ => cleanup
+ */
+ WSREP_DEBUG("cleanup transaction for LOCAL_STATE");
+ /*
+ Run post-rollback hook to clean up in the case if
+ some keys were populated for the transaction in provider
+ but during commit time there was no write set to replicate.
+ This may happen when client sets the SAVEPOINT and immediately
+ rolls back to savepoint after first operation.
+ */
+ if (all && thd->wsrep_conflict_state != MUST_REPLAY &&
+ wsrep && wsrep->post_rollback(wsrep, &thd->wsrep_ws_handle))
+ {
+ WSREP_WARN("post_rollback fail: %llu %d",
+ (long long)thd->thread_id, thd->get_stmt_da()->status());
+ }
+ wsrep_cleanup_transaction(thd);
+ break;
+ }
+ default: break;
}
-
}
/*
diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc
index 0c051d384c9..7a90373e252 100644
--- a/sql/wsrep_mysqld.cc
+++ b/sql/wsrep_mysqld.cc
@@ -13,7 +13,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */
-#include "mariadb.h"
+#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
#include <mysqld.h>
#include <sql_class.h>
#include <sql_parse.h>
@@ -38,7 +38,6 @@
#include <cstdlib>
#include "log_event.h"
#include <slave.h>
-#include "sql_plugin.h" /* wsrep_plugins_pre_init() */
wsrep_t *wsrep = NULL;
/*
@@ -313,8 +312,7 @@ wsrep_view_handler_cb (void* app_ctx,
if (memcmp(&cluster_uuid, &view->state_id.uuid, sizeof(wsrep_uuid_t)))
{
- memcpy((wsrep_uuid_t*)&cluster_uuid, &view->state_id.uuid,
- sizeof(cluster_uuid));
+ memcpy(&cluster_uuid, &view->state_id.uuid, sizeof(cluster_uuid));
wsrep_uuid_print (&cluster_uuid, cluster_uuid_str,
sizeof(cluster_uuid_str));
@@ -360,7 +358,7 @@ wsrep_view_handler_cb (void* app_ctx,
// version change
if (view->proto_ver != wsrep_protocol_version)
{
- my_bool wsrep_ready_saved= wsrep_ready;
+ my_bool wsrep_ready_saved= wsrep_ready_get();
wsrep_ready_set(FALSE);
WSREP_INFO("closing client connections for "
"protocol change %ld -> %d",
@@ -475,16 +473,34 @@ out:
return WSREP_CB_SUCCESS;
}
-void wsrep_ready_set (my_bool x)
+my_bool wsrep_ready_set (my_bool x)
{
WSREP_DEBUG("Setting wsrep_ready to %d", x);
if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
- if (wsrep_ready != x)
+ my_bool ret= (wsrep_ready != x);
+ if (ret)
{
wsrep_ready= x;
mysql_cond_signal (&COND_wsrep_ready);
}
mysql_mutex_unlock (&LOCK_wsrep_ready);
+ return ret;
+}
+
+my_bool wsrep_ready_get (void)
+{
+ if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
+ my_bool ret= wsrep_ready;
+ mysql_mutex_unlock (&LOCK_wsrep_ready);
+ return ret;
+}
+
+int wsrep_show_ready(THD *thd, SHOW_VAR *var, char *buff)
+{
+ var->type= SHOW_MY_BOOL;
+ var->value= buff;
+ *((my_bool *)buff)= wsrep_ready_get();
+ return 0;
}
// Wait until wsrep has reached ready state
@@ -503,17 +519,8 @@ void wsrep_ready_wait ()
static void wsrep_synced_cb(void* app_ctx)
{
WSREP_INFO("Synchronized with group, ready for connections");
- bool signal_main= false;
- if (mysql_mutex_lock (&LOCK_wsrep_ready)) abort();
- if (!wsrep_ready)
- {
- wsrep_ready= TRUE;
- mysql_cond_signal (&COND_wsrep_ready);
- signal_main= true;
-
- }
+ my_bool signal_main= wsrep_ready_set(TRUE);
wsrep_config_state->set(WSREP_MEMBER_SYNCED);
- mysql_mutex_unlock (&LOCK_wsrep_ready);
if (signal_main)
{
@@ -995,6 +1002,8 @@ bool wsrep_must_sync_wait (THD* thd, uint mask)
{
return (thd->variables.wsrep_sync_wait & mask) &&
thd->variables.wsrep_on &&
+ !(thd->variables.wsrep_dirty_reads &&
+ !is_update_query(thd->lex->sql_command)) &&
!thd->in_active_multi_stmt_transaction() &&
thd->wsrep_conflict_state != REPLAYING &&
thd->wsrep_sync_wait_gtid.seqno == WSREP_SEQNO_UNDEFINED;
@@ -1042,17 +1051,7 @@ bool wsrep_sync_wait (THD* thd, uint mask)
return false;
}
-/*
- * Helpers to deal with TOI key arrays
- */
-typedef struct wsrep_key_arr
-{
- wsrep_key_t* keys;
- size_t keys_len;
-} wsrep_key_arr_t;
-
-
-static void wsrep_keys_free(wsrep_key_arr_t* key_arr)
+void wsrep_keys_free(wsrep_key_arr_t* key_arr)
{
for (size_t i= 0; i < key_arr->keys_len; ++i)
{
@@ -1117,11 +1116,11 @@ static bool wsrep_prepare_key_for_isolation(const char* db,
}
/* Prepare key list from db/table and table_list */
-static bool wsrep_prepare_keys_for_isolation(THD* thd,
- const char* db,
- const char* table,
- const TABLE_LIST* table_list,
- wsrep_key_arr_t* ka)
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka)
{
ka->keys= 0;
ka->keys_len= 0;
@@ -1866,7 +1865,7 @@ bool wsrep_grant_mdl_exception(MDL_context *requestor_ctx,
if (request_thd->lex->sql_command == SQLCOM_DROP_TABLE ||
request_thd->lex->sql_command == SQLCOM_DROP_SEQUENCE)
{
- WSREP_DEBUG("DROP caused BF abort");
+ WSREP_DEBUG("DROP caused BF abort, conf %d", granted_thd->wsrep_conflict_state);
}
else if (granted_thd->wsrep_query_state == QUERY_COMMITTING)
{
diff --git a/sql/wsrep_mysqld.h b/sql/wsrep_mysqld.h
index 5a13575d904..699a4daf27a 100644
--- a/sql/wsrep_mysqld.h
+++ b/sql/wsrep_mysqld.h
@@ -228,6 +228,7 @@ void wsrep_log(void (*fun)(const char *, ...), const char *format, ...);
#define WSREP_QUERY(thd) (thd->query())
+extern my_bool wsrep_ready_get();
extern void wsrep_ready_wait();
class Ha_trx_info;
@@ -320,6 +321,18 @@ bool wsrep_create_like_table(THD* thd, TABLE_LIST* table,
bool wsrep_node_is_donor();
bool wsrep_node_is_synced();
+typedef struct wsrep_key_arr
+{
+ wsrep_key_t* keys;
+ size_t keys_len;
+} wsrep_key_arr_t;
+bool wsrep_prepare_keys_for_isolation(THD* thd,
+ const char* db,
+ const char* table,
+ const TABLE_LIST* table_list,
+ wsrep_key_arr_t* ka);
+void wsrep_keys_free(wsrep_key_arr_t* key_arr);
+
#define WSREP_BINLOG_FORMAT(my_format) \
((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \
wsrep_forced_binlog_format : my_format)
@@ -353,6 +366,5 @@ bool wsrep_node_is_synced();
#define wsrep_thr_deinit() do {} while(0)
#define wsrep_running_threads (0)
#define WSREP_BINLOG_FORMAT(my_format) my_format
-
#endif /* WITH_WSREP */
#endif /* WSREP_MYSQLD_H */
diff --git a/sql/wsrep_priv.h b/sql/wsrep_priv.h
index 97307fcc948..222a49cc2ab 100644
--- a/sql/wsrep_priv.h
+++ b/sql/wsrep_priv.h
@@ -26,7 +26,7 @@
#include <pthread.h>
#include <cstdio>
-void wsrep_ready_set (my_bool x);
+my_bool wsrep_ready_set (my_bool x);
ssize_t wsrep_sst_prepare (void** msg);
wsrep_cb_status wsrep_sst_donate_cb (void* app_ctx,
diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc
index d19bcafb8d6..d5b0344c456 100644
--- a/sql/wsrep_sst.cc
+++ b/sql/wsrep_sst.cc
@@ -29,6 +29,8 @@
#include <cstdio>
#include <cstdlib>
+#include <my_service_manager.h>
+
static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 +
sizeof(WSREP_SST_OPT_CONF) +
sizeof(WSREP_SST_OPT_CONF_SUFFIX) +
@@ -176,6 +178,9 @@ bool wsrep_before_SE()
static bool sst_complete = false;
static bool sst_needed = false;
+#define WSREP_EXTEND_TIMEOUT_INTERVAL 30
+#define WSREP_TIMEDWAIT_SECONDS 10
+
void wsrep_sst_grab ()
{
WSREP_INFO("wsrep_sst_grab()");
@@ -187,11 +192,25 @@ void wsrep_sst_grab ()
// Wait for end of SST
bool wsrep_sst_wait ()
{
- if (mysql_mutex_lock (&LOCK_wsrep_sst)) abort();
+ struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
+ uint32 total_wtime = 0;
+
+ if (mysql_mutex_lock (&LOCK_wsrep_sst))
+ abort();
+
+ WSREP_INFO("Waiting for SST to complete.");
+
while (!sst_complete)
{
- WSREP_INFO("Waiting for SST to complete.");
- mysql_cond_wait (&COND_wsrep_sst, &LOCK_wsrep_sst);
+ mysql_cond_timedwait (&COND_wsrep_sst, &LOCK_wsrep_sst, &wtime);
+
+ if (!sst_complete)
+ {
+ total_wtime += wtime.tv_sec;
+ WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
+ service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
+ "WSREP state transfer ongoing, current seqno: %ld", local_seqno);
+ }
}
if (local_seqno >= 0)
@@ -604,11 +623,11 @@ static ssize_t sst_prepare_other (const char* method,
ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
- WSREP_SST_OPT_ROLE" 'joiner' "
- WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_DATA" '%s' "
+ WSREP_SST_OPT_ROLE " 'joiner' "
+ WSREP_SST_OPT_ADDR " '%s' "
+ WSREP_SST_OPT_DATA " '%s' "
" %s "
- WSREP_SST_OPT_PARENT" '%d'"
+ WSREP_SST_OPT_PARENT " '%d'"
" %s '%s' ",
method, addr_in, mysql_real_data_home,
wsrep_defaults_file,
@@ -890,13 +909,13 @@ static int sst_donate_mysqldump (const char* addr,
int ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_mysqldump "
- WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_PORT" '%d' "
- WSREP_SST_OPT_LPORT" '%u' "
- WSREP_SST_OPT_SOCKET" '%s' "
- " '%s' "
- WSREP_SST_OPT_GTID" '%s:%lld' "
- WSREP_SST_OPT_GTID_DOMAIN_ID" '%d'"
+ WSREP_SST_OPT_ADDR " '%s' "
+ WSREP_SST_OPT_PORT " '%d' "
+ WSREP_SST_OPT_LPORT " '%u' "
+ WSREP_SST_OPT_SOCKET " '%s' "
+ " %s "
+ WSREP_SST_OPT_GTID " '%s:%lld' "
+ WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
addr, port, mysqld_port, mysqld_unix_port,
wsrep_defaults_file, uuid_str,
@@ -1253,14 +1272,14 @@ static int sst_donate_other (const char* method,
ret= snprintf (cmd_str(), cmd_len,
"wsrep_sst_%s "
- WSREP_SST_OPT_ROLE" 'donor' "
- WSREP_SST_OPT_ADDR" '%s' "
- WSREP_SST_OPT_SOCKET" '%s' "
- WSREP_SST_OPT_DATA" '%s' "
+ WSREP_SST_OPT_ROLE " 'donor' "
+ WSREP_SST_OPT_ADDR " '%s' "
+ WSREP_SST_OPT_SOCKET " '%s' "
+ WSREP_SST_OPT_DATA " '%s' "
" %s "
" %s '%s' "
- WSREP_SST_OPT_GTID" '%s:%lld' "
- WSREP_SST_OPT_GTID_DOMAIN_ID" '%d'"
+ WSREP_SST_OPT_GTID " '%s:%lld' "
+ WSREP_SST_OPT_GTID_DOMAIN_ID " '%d'"
"%s",
method, addr, mysqld_unix_port, mysql_real_data_home,
wsrep_defaults_file,
@@ -1346,10 +1365,22 @@ void wsrep_SE_init_grab()
void wsrep_SE_init_wait()
{
+ struct timespec wtime = {WSREP_TIMEDWAIT_SECONDS, 0};
+ uint32 total_wtime=0;
+
while (SE_initialized == false)
{
- mysql_cond_wait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init);
+ mysql_cond_timedwait (&COND_wsrep_sst_init, &LOCK_wsrep_sst_init, &wtime);
+
+ if (!SE_initialized)
+ {
+ total_wtime += wtime.tv_sec;
+ WSREP_DEBUG("Waiting for SST to complete. waited %u secs.", total_wtime);
+ service_manager_extend_timeout(WSREP_EXTEND_TIMEOUT_INTERVAL,
+ "WSREP SE initialization ongoing.");
+ }
}
+
mysql_mutex_unlock (&LOCK_wsrep_sst_init);
}
diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc
index d94ac240b76..7fe120beb8e 100644
--- a/sql/wsrep_var.cc
+++ b/sql/wsrep_var.cc
@@ -47,6 +47,7 @@ int wsrep_init_vars()
linking will succeed even if the server is built with a dynamically
linked InnoDB. */
ulong innodb_lock_schedule_algorithm __attribute__((weak));
+struct handlerton* innodb_hton_ptr __attribute__((weak));
bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
{
@@ -62,7 +63,10 @@ bool wsrep_on_check(sys_var *self, THD* thd, set_var* var)
{
bool new_wsrep_on= (bool)var->save_result.ulonglong_value;
- if (new_wsrep_on && innodb_lock_schedule_algorithm != 0) {
+ if (check_has_super(self, thd, var))
+ return true;
+
+ if (new_wsrep_on && innodb_hton_ptr && innodb_lock_schedule_algorithm != 0) {
my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled "
"if innodb_lock_schedule_algorithm=VATS. Please configure"
" innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0));