diff options
author | Alexander Barkov <bar@mariadb.com> | 2018-07-03 14:02:05 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2018-07-03 14:02:05 +0400 |
commit | e61568ee9305c6c93c1a9f298a7fe04532881f24 (patch) | |
tree | c80b0967460f7c4f8743831690f7369e11c73722 /sql | |
parent | 4b0cedf82d8d8ba582648dcb4a2620c146862a43 (diff) | |
parent | c3289d27eef39a47fed2ce1ff239013ed6870f39 (diff) | |
download | mariadb-git-e61568ee9305c6c93c1a9f298a7fe04532881f24.tar.gz |
Merge remote-tracking branch 'origin/10.3' into 10.4
Diffstat (limited to 'sql')
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 >id) +{ +#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 >id); + 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, >id, &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, ¬_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, ¬_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)); |