diff options
Diffstat (limited to 'sql')
88 files changed, 1559 insertions, 833 deletions
diff --git a/sql/event_data_objects.cc b/sql/event_data_objects.cc index 69d17725bea..c85192ee258 100644 --- a/sql/event_data_objects.cc +++ b/sql/event_data_objects.cc @@ -431,7 +431,7 @@ Event_job_data::load_from_row(THD *thd, TABLE *table) definer_host.str= strmake_root(&mem_root, ptr + 1, len); definer_host.length= len; - sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int(); + sql_mode= (sql_mode_t) table->field[ET_FIELD_SQL_MODE]->val_int(); DBUG_RETURN(FALSE); } @@ -637,7 +637,7 @@ Event_timed::load_from_row(THD *thd, TABLE *table) else comment.length= 0; - sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int(); + sql_mode= (sql_mode_t) table->field[ET_FIELD_SQL_MODE]->val_int(); DBUG_RETURN(FALSE); } @@ -1478,19 +1478,33 @@ end: bool save_tx_read_only= thd->tx_read_only; thd->tx_read_only= false; - if (WSREP(thd)) - { + /* + This code is processing event execution and does not have client + connection. Here, event execution will now execute a prepared + DROP EVENT statement, but thd->lex->sql_command is set to + SQLCOM_CREATE_PROCEDURE + DROP EVENT will be logged in binlog, and we have to + replicate it to make all nodes have consistent event definitions + Wsrep DDL replication is triggered inside Events::drop_event(), + and here we need to prepare the THD so that DDL replication is + possible, essentially it requires setting sql_command to + SQLCOMM_DROP_EVENT, we will switch sql_command for the duration + of DDL replication only. + */ + const enum_sql_command sql_command_save= thd->lex->sql_command; + const bool sql_command_set= WSREP(thd); + + if (sql_command_set) thd->lex->sql_command = SQLCOM_DROP_EVENT; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); - } ret= Events::drop_event(thd, &dbname, &name, FALSE); - WSREP_TO_ISOLATION_END; + if (sql_command_set) + { + WSREP_TO_ISOLATION_END; + thd->lex->sql_command = sql_command_save; + } -#ifdef WITH_WSREP - error: -#endif thd->tx_read_only= save_tx_read_only; thd->security_ctx->master_access= saved_master_access; } diff --git a/sql/events.cc b/sql/events.cc index 069fa97aa36..3ad546217a7 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -189,8 +189,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_HOUR_SECOND: { ulonglong tmp_expr= expr; @@ -206,8 +206,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_DAY_SECOND: { ulonglong tmp_expr= expr; @@ -229,8 +229,8 @@ common_1_lev_code: expr= tmp_expr - (tmp_expr/60)*60; /* the code after the switch will finish */ - } break; + } case INTERVAL_DAY_MICROSECOND: case INTERVAL_HOUR_MICROSECOND: case INTERVAL_MINUTE_MICROSECOND: @@ -244,7 +244,8 @@ common_1_lev_code: break; case INTERVAL_WEEK: expr/= 7; - /* fall through */ + close_quote= FALSE; + break; default: close_quote= FALSE; break; @@ -335,6 +336,7 @@ Events::create_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) if (lock_object_name(thd, MDL_key::EVENT, parse_data->dbname.str, parse_data->name.str)) @@ -417,6 +419,10 @@ Events::create_event(THD *thd, Event_parse_data *parse_data) thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(ret); +#ifdef WITH_WSREP + error: + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ } @@ -457,6 +463,9 @@ 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) + if (lock_object_name(thd, MDL_key::EVENT, parse_data->dbname.str, parse_data->name.str)) DBUG_RETURN(TRUE); @@ -541,6 +550,10 @@ Events::update_event(THD *thd, Event_parse_data *parse_data, thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(ret); +#ifdef WITH_WSREP +error: + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ } @@ -582,6 +595,8 @@ 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) + /* Turn off row binlogging of this statement and use statement-based so that all supporting tables are updated for DROP EVENT command. @@ -603,6 +618,10 @@ Events::drop_event(THD *thd, const LEX_CSTRING *dbname, thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(ret); +#ifdef WITH_WSREP +error: + DBUG_RETURN(TRUE); +#endif } diff --git a/sql/field.cc b/sql/field.cc index e10c82347d5..51562dd4198 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2013, Monty Program Ab. + Copyright (c) 2000, 2017, Oracle and/or its affiliates. + Copyright (c) 2008, 2017, MariaDB 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 @@ -240,7 +240,7 @@ static enum_field_types field_types_merge_rules [FIELDTYPE_NUM][FIELDTYPE_NUM]= //MYSQL_TYPE_NULL MYSQL_TYPE_TIMESTAMP MYSQL_TYPE_FLOAT, MYSQL_TYPE_VARCHAR, //MYSQL_TYPE_LONGLONG MYSQL_TYPE_INT24 - MYSQL_TYPE_FLOAT, MYSQL_TYPE_FLOAT, + MYSQL_TYPE_DOUBLE, MYSQL_TYPE_FLOAT, //MYSQL_TYPE_DATE MYSQL_TYPE_TIME MYSQL_TYPE_VARCHAR, MYSQL_TYPE_VARCHAR, //MYSQL_TYPE_DATETIME MYSQL_TYPE_YEAR @@ -2240,15 +2240,15 @@ Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff) return tmp; } -void Field::set_default() +int Field::set_default() { if (default_value) { Query_arena backup_arena; table->in_use->set_n_backup_active_arena(table->expr_arena, &backup_arena); - (void) default_value->expr->save_in_field(this, 0); + int rc= default_value->expr->save_in_field(this, 0); table->in_use->restore_active_arena(table->expr_arena, &backup_arena); - return; + return rc; } /* Copy constant value stored in s->default_values */ my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values - @@ -2257,6 +2257,7 @@ void Field::set_default() if (maybe_null_in_table()) *null_ptr= ((*null_ptr & (uchar) ~null_bit) | (null_ptr[l_offset] & null_bit)); + return 0; } @@ -2271,6 +2272,16 @@ void Field_null::sql_type(String &res) const /**************************************************************************** + Field_row, e.g. for ROW-type SP variables +****************************************************************************/ + +Field_row::~Field_row() +{ + delete m_table; +} + + +/**************************************************************************** Functions for the Field_decimal class This is an number stored as a pre-space (or pre-zero) string ****************************************************************************/ @@ -9005,13 +9016,13 @@ String *Field_set::val_str(String *val_buffer, ulonglong tmp=(ulonglong) Field_enum::val_int(); uint bitnr=0; + /* + Some callers expect *val_buffer to contain the result, + so we assign to it, rather than doing 'return &empty_set_string. + */ + *val_buffer= empty_set_string; if (tmp == 0) { - /* - Some callers expect *val_buffer to contain the result, - so we assign to it, rather than doing 'return &empty_set_string. - */ - *val_buffer= empty_set_string; return val_buffer; } @@ -9764,7 +9775,7 @@ Field_bit::unpack(uchar *to, const uchar *from, const uchar *from_end, } -void Field_bit::set_default() +int Field_bit::set_default() { if (bit_len > 0) { @@ -9772,7 +9783,7 @@ void Field_bit::set_default() uchar bits= get_rec_bits(bit_ptr + col_offset, bit_ofs, bit_len); set_rec_bits(bits, bit_ptr, bit_ofs, bit_len); } - Field::set_default(); + return Field::set_default(); } /* @@ -10301,6 +10312,21 @@ Field *make_field(TABLE_SHARE *share, uchar *UNINIT_VAR(bit_ptr); uchar UNINIT_VAR(bit_offset); + DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s", + handler->name().ptr(), field_length, interval, + FLAGSTR(pack_flag, FIELDFLAG_BINARY), + FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), + FLAGSTR(pack_flag, FIELDFLAG_NUMBER), + FLAGSTR(pack_flag, FIELDFLAG_PACK), + FLAGSTR(pack_flag, FIELDFLAG_BLOB))); + + if (handler == &type_handler_row) + { + DBUG_ASSERT(field_length == 0); + DBUG_ASSERT(f_maybe_null(pack_flag)); + return new (mem_root) Field_row(ptr, field_name); + } + if (handler->real_field_type() == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag)) { bit_ptr= null_pos; @@ -10322,13 +10348,6 @@ Field *make_field(TABLE_SHARE *share, null_bit= ((uchar) 1) << null_bit; } - DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s", - handler->name().ptr(), field_length, interval, - FLAGSTR(pack_flag, FIELDFLAG_BINARY), - FLAGSTR(pack_flag, FIELDFLAG_INTERVAL), - FLAGSTR(pack_flag, FIELDFLAG_NUMBER), - FLAGSTR(pack_flag, FIELDFLAG_PACK), - FLAGSTR(pack_flag, FIELDFLAG_BLOB))); if (f_is_alpha(pack_flag)) { diff --git a/sql/field.h b/sql/field.h index bf115b38816..eb6510bc9a4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -45,6 +45,7 @@ class Column_statistics_collected; class Item_func; class Item_bool_func; class Item_equal; +class Virtual_tmp_table; enum enum_check_fields { @@ -973,7 +974,7 @@ public: my_ptrdiff_t l_offset= (my_ptrdiff_t) (record - table->record[0]); return ptr + l_offset; } - virtual void set_default(); + virtual int set_default(); bool has_update_default_function() const { @@ -1527,6 +1528,11 @@ public: virtual Compression_method *compression_method() const { return 0; } + virtual Virtual_tmp_table **virtual_tmp_table_addr() + { + return NULL; + } + friend int cre_myisam(char * name, register TABLE *form, uint options, ulonglong auto_increment_value); friend class Copy_field; @@ -3902,7 +3908,7 @@ public: virtual uchar *pack(uchar *to, const uchar *from, uint max_length); virtual const uchar *unpack(uchar *to, const uchar *from, const uchar *from_end, uint param_data); - virtual void set_default(); + virtual int set_default(); Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr, uint32 length, @@ -3954,6 +3960,19 @@ public: }; +class Field_row: public Field_null +{ + class Virtual_tmp_table *m_table; +public: + Field_row(uchar *ptr_arg, const LEX_CSTRING *field_name_arg) + :Field_null(ptr_arg, 0, Field::NONE, field_name_arg, &my_charset_bin), + m_table(NULL) + {} + ~Field_row(); + Virtual_tmp_table **virtual_tmp_table_addr() { return &m_table; } +}; + + extern const LEX_CSTRING null_clex_str; Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root, @@ -4205,6 +4224,23 @@ public: || unireg_check == Field::TIMESTAMP_DNUN_FIELD; } + void set_type(const Column_definition &other) + { + set_handler(other.type_handler()); + length= other.length; + char_length= other.char_length; + decimals= other.decimals; + flags= other.flags; + pack_length= other.pack_length; + key_length= other.key_length; + unireg_check= other.unireg_check; + interval= other.interval; + charset= other.charset; + srid= other.srid; + geom_type= other.geom_type; + pack_flag= other.pack_flag; + } + // Replace the entire value by another definition void set_column_definition(const Column_definition *def) { @@ -4276,12 +4312,14 @@ class Spvar_definition: public Column_definition class Qualified_column_ident *m_column_type_ref; // for %TYPE class Table_ident *m_table_rowtype_ref; // for table%ROWTYPE bool m_cursor_rowtype_ref; // for cursor%ROWTYPE + uint m_cursor_rowtype_offset; // for cursor%ROWTYPE Row_definition_list *m_row_field_definitions; // for ROW public: Spvar_definition() :m_column_type_ref(NULL), m_table_rowtype_ref(NULL), m_cursor_rowtype_ref(false), + m_cursor_rowtype_offset(0), m_row_field_definitions(NULL) { } Spvar_definition(THD *thd, Field *field) @@ -4289,13 +4327,12 @@ public: m_column_type_ref(NULL), m_table_rowtype_ref(NULL), m_cursor_rowtype_ref(false), + m_cursor_rowtype_offset(0), m_row_field_definitions(NULL) { } const Type_handler *type_handler() const { - return is_row() || is_table_rowtype_ref() || is_cursor_rowtype_ref() ? - &type_handler_row : - Type_handler_hybrid_field_type::type_handler(); + return Type_handler_hybrid_field_type::type_handler(); } bool is_column_type_ref() const { return m_column_type_ref != 0; } bool is_table_rowtype_ref() const { return m_table_rowtype_ref != 0; } @@ -4315,11 +4352,20 @@ public: } void set_table_rowtype_ref(class Table_ident *ref) { + DBUG_ASSERT(ref); + set_handler(&type_handler_row); m_table_rowtype_ref= ref; } - void set_cursor_rowtype_ref(bool ref) + + uint cursor_rowtype_offset() const + { + return m_cursor_rowtype_offset; + } + void set_cursor_rowtype_ref(uint offset) { - m_cursor_rowtype_ref= ref; + set_handler(&type_handler_row); + m_cursor_rowtype_ref= true; + m_cursor_rowtype_offset= offset; } /* @@ -4347,6 +4393,8 @@ public: } void set_row_field_definitions(Row_definition_list *list) { + DBUG_ASSERT(list); + set_handler(&type_handler_row); m_row_field_definitions= list; } diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index effabc3a3c0..67132e5ee4f 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2005, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab & SkySQL Ab + Copyright (c) 2005, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, MariaDB 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 @@ -1931,7 +1931,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info, cleanup_new_partition(part_count); DBUG_RETURN(error); } - + DBUG_PRINT("info", ("Add partition %s", part_name_buff)); if ((error= prepare_new_partition(table, create_info, new_file_array[i], diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index e5db6781464..93f6f32d473 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -112,6 +112,12 @@ int ha_sequence::open(const char *name, int mode, uint flags) } else table->m_needs_reopen= true; + + /* + The following is needed to fix comparison of rows in + ha_update_first_row() for InnoDB + */ + memcpy(table->record[1], table->s->default_values, table->s->reclength); } DBUG_RETURN(error); } diff --git a/sql/handler.cc b/sql/handler.cc index 7609ed047a0..ca4f8634091 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -405,7 +405,7 @@ static int ha_finish_errors(void) } static volatile int32 need_full_discover_for_existence= 0; -static volatile int32 engines_with_discover_table_names= 0; +static volatile int32 engines_with_discover_file_names= 0; static volatile int32 engines_with_discover= 0; static int full_discover_for_existence(handlerton *, const char *, const char *) @@ -430,8 +430,8 @@ static void update_discovery_counters(handlerton *hton, int val) if (hton->discover_table_existence == full_discover_for_existence) my_atomic_add32(&need_full_discover_for_existence, val); - if (hton->discover_table_names) - my_atomic_add32(&engines_with_discover_table_names, val); + if (hton->discover_table_names && hton->tablefile_extensions[0]) + my_atomic_add32(&engines_with_discover_file_names, val); if (hton->discover_table) my_atomic_add32(&engines_with_discover, val); @@ -5229,6 +5229,7 @@ void Discovered_table_list::remove_duplicates() { LEX_CSTRING **src= tables->front(); LEX_CSTRING **dst= src; + sort(); while (++dst <= tables->back()) { LEX_CSTRING *s= *src, *d= *dst; @@ -5296,10 +5297,12 @@ int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp, int error; DBUG_ENTER("ha_discover_table_names"); - if (engines_with_discover_table_names == 0 && !reusable) + if (engines_with_discover_file_names == 0 && !reusable) { - error= ext_table_discovery_simple(dirp, result); - result->sort(); + st_discover_names_args args= {db, NULL, result, 0}; + error= ext_table_discovery_simple(dirp, result) || + plugin_foreach(thd, discover_names, + MYSQL_STORAGE_ENGINE_PLUGIN, &args); } else { @@ -5312,8 +5315,6 @@ int ha_discover_table_names(THD *thd, LEX_CSTRING *db, MY_DIR *dirp, error= extension_based_table_discovery(dirp, reg_ext, result) || plugin_foreach(thd, discover_names, MYSQL_STORAGE_ENGINE_PLUGIN, &args); - result->sort(); - if (args.possible_duplicates > 0) result->remove_duplicates(); } @@ -6078,7 +6079,7 @@ int handler::update_first_row(uchar *new_data) /* We have to do the memcmp as otherwise we may get error 169 from InnoDB */ - if (memcmp(table->record[0], table->record[1], table->s->reclength)) + if (memcmp(new_data, table->record[1], table->s->reclength)) error= update_row(table->record[1], new_data); } end_error= ha_rnd_end(); diff --git a/sql/item.cc b/sql/item.cc index ad17cd5811c..024fbd87d79 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -109,6 +109,19 @@ void Item::push_note_converted_to_positive_complement(THD *thd) } +longlong Item::val_datetime_packed_result() +{ + MYSQL_TIME ltime, tmp; + if (get_date_result(<ime, TIME_FUZZY_DATES | TIME_INVALID_DATES)) + return 0; + if (ltime.time_type != MYSQL_TIMESTAMP_TIME) + return pack_time(<ime); + if ((null_value= time_to_datetime_with_warn(current_thd, <ime, &tmp, 0))) + return 0; + return pack_time(&tmp); +} + + /** Get date/time/datetime. Optionally extend TIME result to DATETIME. @@ -1752,17 +1765,15 @@ void Item_sp_variable::make_field(THD *thd, Send_field *field) Item_splocal::Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name, uint sp_var_idx, - enum_field_types sp_var_type, + const Type_handler *handler, uint pos_in_q, uint len_in_q): Item_sp_variable(thd, sp_var_name), Rewritable_query_parameter(pos_in_q, len_in_q), + Type_handler_hybrid_field_type(handler), m_var_idx(sp_var_idx) { maybe_null= TRUE; - - sp_var_type= real_type_to_type(sp_var_type); - m_type= sp_map_item_type(sp_var_type); - set_handler_by_field_type(sp_var_type); + m_type= sp_map_item_type(handler); } @@ -1777,7 +1788,7 @@ bool Item_splocal::fix_fields(THD *thd, Item **ref) Item * Item_splocal::this_item() { - DBUG_ASSERT(m_sp == m_thd->spcont->sp); + DBUG_ASSERT(m_sp == m_thd->spcont->m_sp); DBUG_ASSERT(fixed); return m_thd->spcont->get_item(m_var_idx); } @@ -1785,7 +1796,7 @@ Item_splocal::this_item() const Item * Item_splocal::this_item() const { - DBUG_ASSERT(m_sp == m_thd->spcont->sp); + DBUG_ASSERT(m_sp == m_thd->spcont->m_sp); DBUG_ASSERT(fixed); return m_thd->spcont->get_item(m_var_idx); } @@ -1794,7 +1805,7 @@ Item_splocal::this_item() const Item ** Item_splocal::this_item_addr(THD *thd, Item **) { - DBUG_ASSERT(m_sp == thd->spcont->sp); + DBUG_ASSERT(m_sp == thd->spcont->m_sp); DBUG_ASSERT(fixed); return thd->spcont->get_item_addr(m_var_idx); } @@ -1901,7 +1912,7 @@ bool Item_splocal_row_field::fix_fields(THD *thd, Item **ref) Item * Item_splocal_row_field::this_item() { - DBUG_ASSERT(m_sp == m_thd->spcont->sp); + DBUG_ASSERT(m_sp == m_thd->spcont->m_sp); DBUG_ASSERT(fixed); return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx); } @@ -1910,7 +1921,7 @@ Item_splocal_row_field::this_item() const Item * Item_splocal_row_field::this_item() const { - DBUG_ASSERT(m_sp == m_thd->spcont->sp); + DBUG_ASSERT(m_sp == m_thd->spcont->m_sp); DBUG_ASSERT(fixed); return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx); } @@ -1919,7 +1930,7 @@ Item_splocal_row_field::this_item() const Item ** Item_splocal_row_field::this_item_addr(THD *thd, Item **) { - DBUG_ASSERT(m_sp == thd->spcont->sp); + DBUG_ASSERT(m_sp == thd->spcont->m_sp); DBUG_ASSERT(fixed); return thd->spcont->get_item(m_var_idx)->addr(m_field_idx); } @@ -2007,7 +2018,7 @@ bool Item_case_expr::fix_fields(THD *thd, Item **ref) Item * Item_case_expr::this_item() { - DBUG_ASSERT(m_sp == m_thd->spcont->sp); + DBUG_ASSERT(m_sp == m_thd->spcont->m_sp); return m_thd->spcont->get_case_expr(m_case_expr_id); } @@ -2017,7 +2028,7 @@ Item_case_expr::this_item() const Item * Item_case_expr::this_item() const { - DBUG_ASSERT(m_sp == m_thd->spcont->sp); + DBUG_ASSERT(m_sp == m_thd->spcont->m_sp); return m_thd->spcont->get_case_expr(m_case_expr_id); } @@ -2026,7 +2037,7 @@ Item_case_expr::this_item() const Item ** Item_case_expr::this_item_addr(THD *thd, Item **) { - DBUG_ASSERT(m_sp == thd->spcont->sp); + DBUG_ASSERT(m_sp == thd->spcont->m_sp); return thd->spcont->get_case_expr_addr(m_case_expr_id); } @@ -2595,6 +2606,9 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, Item **args, uint nargs, uint flags, int item_sep) { + THD *thd= current_thd; + if (thd->lex->is_ps_or_view_context_analysis()) + return false; Item **arg, *safe_args[2]= {NULL, NULL}; /* @@ -2610,7 +2624,6 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, safe_args[1]= args[item_sep]; } - THD *thd= current_thd; bool res= FALSE; uint i; @@ -7070,6 +7083,7 @@ bool Item::cache_const_expr_analyzer(uchar **arg) */ if (const_item() && !(basic_const_item() || item->basic_const_item() || + item->type() == Item::NULL_ITEM || /* Item_name_const hack */ item->type() == Item::FIELD_ITEM || item->type() == SUBSELECT_ITEM || item->type() == CACHE_ITEM || @@ -7445,7 +7459,11 @@ public: // Find which select the field is in. This is achieved by walking up // the select tree and looking for the table of interest. st_select_lex *sel; - for (sel= current_select; sel; sel= sel->outer_select()) + for (sel= current_select; + sel ; + sel= (sel->context.outer_context ? + sel->context.outer_context->select_lex: + NULL)) { List_iterator<TABLE_LIST> li(sel->leaf_tables); TABLE_LIST *tbl; @@ -8619,7 +8637,6 @@ bool Item_direct_view_ref::send(Protocol *protocol, st_value *buffer) bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) { - DBUG_ASSERT(1); /* view fild reference must be defined */ DBUG_ASSERT(*ref); /* (*ref)->check_cols() will be made in Item_direct_ref::fix_fields */ @@ -9677,14 +9694,19 @@ bool Item_cache_temporal::cache_value() { if (!example) return false; + value_cached= true; + value= example->val_datetime_packed_result(); + null_value= example->null_value; + return true; +} + +bool Item_cache_time::cache_value() +{ + if (!example) + return false; value_cached= true; - - MYSQL_TIME ltime; - if (example->get_date_result(<ime, 0)) - value=0; - else - value= pack_time(<ime); + value= example->val_time_packed_result(); null_value= example->null_value; return true; } @@ -9735,8 +9757,8 @@ void Item_cache_temporal::store_packed(longlong val_arg, Item *example_arg) Item *Item_cache_temporal::clone_item(THD *thd) { - Item_cache_temporal *item= new (thd->mem_root) - Item_cache_temporal(thd, Item_cache_temporal::type_handler()); + Item_cache *tmp= type_handler()->Item_get_cache(thd, this); + Item_cache_temporal *item= static_cast<Item_cache_temporal*>(tmp); item->store_packed(value, example); return item; } @@ -10184,7 +10206,7 @@ void Item_direct_view_ref::update_used_tables() table_map Item_direct_view_ref::used_tables() const { - DBUG_ASSERT(null_ref_table); + DBUG_ASSERT(fixed); if (get_depended_from()) return OUTER_REF_TABLE_BIT; diff --git a/sql/item.h b/sql/item.h index 0e7db0d6575..1f743913d78 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,8 +1,8 @@ #ifndef SQL_ITEM_INCLUDED #define SQL_ITEM_INCLUDED -/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB Corporation. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, MariaDB 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 @@ -1397,6 +1397,14 @@ public: ulonglong fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES | TIME_TIME_ONLY; return get_date(<ime, fuzzydate) ? 0 : pack_time(<ime); } + longlong val_datetime_packed_result(); + longlong val_time_packed_result() + { + MYSQL_TIME ltime; + ulonglong fuzzydate= TIME_FUZZY_DATES | TIME_INVALID_DATES | TIME_TIME_ONLY; + return get_date_result(<ime, fuzzydate) ? 0 : pack_time(<ime); + } + // Get a temporal value in packed DATE/DATETIME or TIME format longlong val_temporal_packed(enum_field_types f_type) { @@ -2093,17 +2101,6 @@ public: }; -class Item_spvar_args: public Item_args -{ - Virtual_tmp_table *m_table; -public: - Item_spvar_args():Item_args(), m_table(NULL) { } - ~Item_spvar_args(); - bool row_create_items(THD *thd, List<Spvar_definition> *list); - Field *get_row_field(uint i) const; -}; - - /* Class to be used to enumerate all field references in an item tree. This includes references to outside but not fields of the tables within a @@ -2271,7 +2268,7 @@ public: Routine to which this Item_splocal belongs. Used for checking if correct runtime context is used for variable handling. */ - sp_head *m_sp; + const sp_head *m_sp; #endif public: @@ -2337,7 +2334,7 @@ protected: bool append_value_for_log(THD *thd, String *str); public: Item_splocal(THD *thd, const LEX_CSTRING *sp_var_name, uint sp_var_idx, - enum_field_types sp_var_type, + const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0); bool fix_fields(THD *, Item **); @@ -2390,20 +2387,6 @@ public: }; -class Item_splocal_row: public Item_splocal -{ -public: - Item_splocal_row(THD *thd, const LEX_CSTRING *sp_var_name, - uint sp_var_idx, uint pos_in_q, uint len_in_q) - :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL, - pos_in_q, len_in_q) - { - set_handler(&type_handler_row); - } - enum Type type() const { return ROW_ITEM; } -}; - - /** An Item_splocal variant whose data type becomes known only at sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE". @@ -2415,7 +2398,7 @@ public: const LEX_CSTRING *sp_var_name, uint sp_var_idx, uint pos_in_q, uint len_in_q) - :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL, + :Item_splocal(thd, sp_var_name, sp_var_idx, &type_handler_null, pos_in_q, len_in_q) { } }; @@ -2437,9 +2420,9 @@ public: const LEX_CSTRING *sp_var_name, const LEX_CSTRING *sp_field_name, uint sp_var_idx, uint sp_field_idx, - enum_field_types sp_var_type, + const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0) - :Item_splocal(thd, sp_var_name, sp_var_idx, sp_var_type, + :Item_splocal(thd, sp_var_name, sp_var_idx, handler, pos_in_q, len_in_q), m_field_name(*sp_field_name), m_field_idx(sp_field_idx) @@ -2461,11 +2444,11 @@ public: const LEX_CSTRING *sp_var_name, const LEX_CSTRING *sp_field_name, uint sp_var_idx, - enum_field_types sp_var_type, + const Type_handler *handler, uint pos_in_q= 0, uint len_in_q= 0) :Item_splocal_row_field(thd, sp_var_name, sp_field_name, sp_var_idx, 0 /* field index will be set later */, - sp_var_type, pos_in_q, len_in_q) + handler, pos_in_q, len_in_q) { } bool fix_fields(THD *thd, Item **it); void print(String *str, enum_query_type query_type); @@ -2930,14 +2913,13 @@ public: Item_field for the ROW data type */ class Item_field_row: public Item_field, - public Item_spvar_args + public Item_args { public: Item_field_row(THD *thd, Field *field) :Item_field(thd, field), - Item_spvar_args() + Item_args() { } - Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_field_row>(thd, mem_root, this); } @@ -2955,6 +2937,8 @@ public: } return false; } + bool row_create_items(THD *thd, List<Spvar_definition> *list); + Field *get_row_field(uint i) const; }; @@ -4680,6 +4664,8 @@ public: bool fix_fields(THD *thd, Item **it); void cleanup(); + Item *get_orig_item() const { return orig_item; } + /* Methods of getting value which should be cached in the cache */ void save_val(Field *to); double val_real(); @@ -5782,8 +5768,9 @@ public: class Item_cache_temporal: public Item_cache_int { -public: +protected: Item_cache_temporal(THD *thd, const Type_handler *handler); +public: String* val_str(String *str); my_decimal *val_decimal(my_decimal *); longlong val_int(); @@ -5801,8 +5788,37 @@ public: */ Item *clone_item(THD *thd); Item *convert_to_basic_const_item(THD *thd); +}; + + +class Item_cache_time: public Item_cache_temporal +{ +public: + Item_cache_time(THD *thd) + :Item_cache_temporal(thd, &type_handler_time2) { } + bool cache_value(); + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_cache_time>(thd, mem_root, this); } +}; + + +class Item_cache_datetime: public Item_cache_temporal +{ +public: + Item_cache_datetime(THD *thd) + :Item_cache_temporal(thd, &type_handler_datetime2) { } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_cache_datetime>(thd, mem_root, this); } +}; + + +class Item_cache_date: public Item_cache_temporal +{ +public: + Item_cache_date(THD *thd) + :Item_cache_temporal(thd, &type_handler_newdate) { } Item *get_copy(THD *thd, MEM_ROOT *mem_root) - { return get_item_copy<Item_cache_temporal>(thd, mem_root, this); } + { return get_item_copy<Item_cache_date>(thd, mem_root, this); } }; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 0d57066c2d2..f35017629aa 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -569,18 +569,24 @@ bool Arg_comparator::set_cmp_func_string() bool Arg_comparator::set_cmp_func_time() { + THD *thd= current_thd; m_compare_collation= &my_charset_numeric; func= is_owner_equal_func() ? &Arg_comparator::compare_e_time : &Arg_comparator::compare_time; + a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); + b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); return false; } bool Arg_comparator::set_cmp_func_datetime() { + THD *thd= current_thd; m_compare_collation= &my_charset_numeric; func= is_owner_equal_func() ? &Arg_comparator::compare_e_datetime : &Arg_comparator::compare_datetime; + a= cache_converted_constant(thd, a, &a_cache, compare_type_handler()); + b= cache_converted_constant(thd, b, &b_cache, compare_type_handler()); return false; } @@ -683,17 +689,12 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value, const Type_handler *handler) { /* - get_datetime_value creates Item_cache internally when comparing - values for the first row. - Arg_comparator::cache_converted_constant() is never called for TIME_RESULT. - */ - DBUG_ASSERT(handler->cmp_type() != TIME_RESULT); - /* Don't need cache if doing context analysis only. */ if (!thd_arg->lex->is_ps_or_view_context_analysis() && (*value)->const_item() && - handler->cmp_type() != (*value)->cmp_type()) + handler->type_handler_for_comparison() != + (*value)->type_handler_for_comparison()) { Item_cache *cache= handler->Item_get_cache(thd_arg, *value); cache->setup(thd_arg, *value); @@ -750,7 +751,8 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, if (!thd) thd= current_thd; const Type_handler *h= Type_handler::get_handler_by_field_type(f_type); - Item_cache_temporal *cache= new (thd->mem_root) Item_cache_temporal(thd, h); + Item_cache *tmp_cache= h->Item_get_cache(thd, item); + Item_cache_temporal *cache= static_cast<Item_cache_temporal*>(tmp_cache); cache->store_packed(value, item); *cache_arg= cache; *item_arg= cache_arg; @@ -759,63 +761,57 @@ get_datetime_value(THD *thd, Item ***item_arg, Item **cache_arg, } -/* - Compare items values as dates. - - SYNOPSIS - Arg_comparator::compare_datetime() - - DESCRIPTION - Compare items values as DATE/DATETIME for both EQUAL_FUNC and from other - comparison functions. The correct DATETIME values are obtained - with help of the get_datetime_value() function. - - RETURN - -1 a < b or at least one item is null - 0 a == b - 1 a > b -*/ - -int Arg_comparator::compare_temporal(enum_field_types type) +int Arg_comparator::compare_time() { - bool a_is_null, b_is_null; - longlong a_value, b_value; - + longlong val1= (*a)->val_time_packed(); + if (!(*a)->null_value) + { + longlong val2= (*b)->val_time_packed(); + if (!(*b)->null_value) + return compare_not_null_values(val1, val2); + } if (set_null) - owner->null_value= 1; + owner->null_value= true; + return -1; +} - /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= get_datetime_value(0, &a, &a_cache, type, &a_is_null); - if (a_is_null) - return -1; - /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= get_datetime_value(0, &b, &b_cache, type, &b_is_null); - if (b_is_null) - return -1; +int Arg_comparator::compare_e_time() +{ + longlong val1= (*a)->val_time_packed(); + longlong val2= (*b)->val_time_packed(); + if ((*a)->null_value || (*b)->null_value) + return MY_TEST((*a)->null_value && (*b)->null_value); + return MY_TEST(val1 == val2); +} - /* Here we have two not-NULL values. */ - if (set_null) - owner->null_value= 0; - /* Compare values. */ - return a_value < b_value ? -1 : a_value > b_value ? 1 : 0; -} -int Arg_comparator::compare_e_temporal(enum_field_types type) +int Arg_comparator::compare_datetime() { - bool a_is_null, b_is_null; - longlong a_value, b_value; + longlong val1= (*a)->val_datetime_packed(); + if (!(*a)->null_value) + { + longlong val2= (*b)->val_datetime_packed(); + if (!(*b)->null_value) + return compare_not_null_values(val1, val2); + } + if (set_null) + owner->null_value= true; + return -1; +} - /* Get DATE/DATETIME/TIME value of the 'a' item. */ - a_value= get_datetime_value(0, &a, &a_cache, type, &a_is_null); - /* Get DATE/DATETIME/TIME value of the 'b' item. */ - b_value= get_datetime_value(0, &b, &b_cache, type, &b_is_null); - return a_is_null || b_is_null ? a_is_null == b_is_null - : a_value == b_value; +int Arg_comparator::compare_e_datetime() +{ + longlong val1= (*a)->val_datetime_packed(); + longlong val2= (*b)->val_datetime_packed(); + if ((*a)->null_value || (*b)->null_value) + return MY_TEST((*a)->null_value && (*b)->null_value); + return MY_TEST(val1 == val2); } + int Arg_comparator::compare_string() { String *res1,*res2; @@ -962,13 +958,7 @@ int Arg_comparator::compare_int_signed() { longlong val2= (*b)->val_int(); if (!(*b)->null_value) - { - if (set_null) - owner->null_value= 0; - if (val1 < val2) return -1; - if (val1 == val2) return 0; - return 1; - } + return compare_not_null_values(val1, val2); } if (set_null) owner->null_value= 1; @@ -2112,38 +2102,40 @@ bool Item_func_between::fix_length_and_dec_numeric(THD *thd) } -longlong Item_func_between::val_int_cmp_temporal() +bool Item_func_between::fix_length_and_dec_temporal(THD *thd) { - THD *thd= current_thd; - longlong value, a, b; - Item *cache, **ptr; - bool value_is_null, a_is_null, b_is_null; + if (!thd->lex->is_ps_or_view_context_analysis()) + { + for (uint i= 0; i < 3; i ++) + { + if (args[i]->const_item() && + args[i]->type_handler_for_comparison() != m_comparator.type_handler()) + { + Item_cache *cache= m_comparator.type_handler()->Item_get_cache(thd, args[i]); + if (!cache || cache->setup(thd, args[i])) + return true; + thd->change_item_tree(&args[i], cache); + } + } + } + return false; +} - ptr= &args[0]; - enum_field_types f_type= m_comparator.type_handler()->field_type(); - value= get_datetime_value(thd, &ptr, &cache, f_type, &value_is_null); - if (ptr != &args[0]) - thd->change_item_tree(&args[0], *ptr); - if ((null_value= value_is_null)) +longlong Item_func_between::val_int_cmp_temporal() +{ + enum_field_types f_type= m_comparator.type_handler()->field_type(); + longlong value= args[0]->val_temporal_packed(f_type), a, b; + if ((null_value= args[0]->null_value)) return 0; - - ptr= &args[1]; - a= get_datetime_value(thd, &ptr, &cache, f_type, &a_is_null); - if (ptr != &args[1]) - thd->change_item_tree(&args[1], *ptr); - - ptr= &args[2]; - b= get_datetime_value(thd, &ptr, &cache, f_type, &b_is_null); - if (ptr != &args[2]) - thd->change_item_tree(&args[2], *ptr); - - if (!a_is_null && !b_is_null) + a= args[1]->val_temporal_packed(f_type); + b= args[2]->val_temporal_packed(f_type); + if (!args[1]->null_value && !args[2]->null_value) return (longlong) ((value >= a && value <= b) != negated); - if (a_is_null && b_is_null) + if (args[1]->null_value && args[2]->null_value) null_value= true; - else if (a_is_null) - null_value= value <= b; // not null if false range. + else if (args[1]->null_value) + null_value= value <= b; // not null if false range. else null_value= value >= a; return (longlong) (!null_value && negated); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index f0862608463..62066ef61e5 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -60,9 +60,14 @@ class Arg_comparator: public Sql_alloc int set_cmp_func(Item_func_or_sum *owner_arg, Item **a1, Item **a2); - int compare_temporal(enum_field_types type); - int compare_e_temporal(enum_field_types type); - + int compare_not_null_values(longlong val1, longlong val2) + { + if (set_null) + owner->null_value= false; + if (val1 < val2) return -1; + if (val1 == val2) return 0; + return 1; + } public: /* Allow owner function to use string buffers. */ String value1, value2; @@ -112,10 +117,10 @@ public: int compare_e_row(); // compare args[0] & args[1] int compare_real_fixed(); int compare_e_real_fixed(); - int compare_datetime() { return compare_temporal(MYSQL_TYPE_DATETIME); } - int compare_e_datetime() { return compare_e_temporal(MYSQL_TYPE_DATETIME); } - int compare_time() { return compare_temporal(MYSQL_TYPE_TIME); } - int compare_e_time() { return compare_e_temporal(MYSQL_TYPE_TIME); } + int compare_datetime(); + int compare_e_datetime(); + int compare_time(); + int compare_e_time(); int compare_json_str_basic(Item *j, Item *s); int compare_json_str(); int compare_str_json(); @@ -899,6 +904,7 @@ public: { return agg_arg_charsets_for_comparison(cmp_collation, args, 3); } + bool fix_length_and_dec_temporal(THD *); bool fix_length_and_dec_numeric(THD *); virtual void print(String *str, enum_query_type query_type); bool eval_not_null_tables(void *opt_arg); diff --git a/sql/item_create.cc b/sql/item_create.cc index 6edeade0244..5d6d9742c7a 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -2876,6 +2876,20 @@ protected: }; +class Create_func_substr_oracle : public Create_native_func +{ +public: + virtual Item *create_native(THD *thd, LEX_CSTRING *name, + List<Item> *item_list); + + static Create_func_substr_oracle s_singleton; + +protected: + Create_func_substr_oracle() {} + virtual ~Create_func_substr_oracle() {} +}; + + class Create_func_subtime : public Create_func_arg2 { public: @@ -6466,6 +6480,40 @@ Create_func_substr_index::create_3_arg(THD *thd, Item *arg1, Item *arg2, Item *a } +Create_func_substr_oracle Create_func_substr_oracle::s_singleton; + +Item* +Create_func_substr_oracle::create_native(THD *thd, LEX_CSTRING *name, + List<Item> *item_list) +{ + Item *func= NULL; + int arg_count= item_list ? item_list->elements : 0; + + switch (arg_count) { + case 2: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + func= new (thd->mem_root) Item_func_substr_oracle(thd, param_1, param_2); + break; + } + case 3: + { + Item *param_1= item_list->pop(); + Item *param_2= item_list->pop(); + Item *param_3= item_list->pop(); + func= new (thd->mem_root) Item_func_substr_oracle(thd, param_1, param_2, param_3); + break; + } + default: + my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name->str); + break; + } + + return func; +} + + Create_func_subtime Create_func_subtime::s_singleton; Item* @@ -7119,6 +7167,8 @@ static Native_func_registry func_array[] = { { C_STRING_WITH_LEN("ST_WITHIN") }, GEOM_BUILDER(Create_func_within)}, { { C_STRING_WITH_LEN("ST_X") }, GEOM_BUILDER(Create_func_x)}, { { C_STRING_WITH_LEN("ST_Y") }, GEOM_BUILDER(Create_func_y)}, + { { C_STRING_WITH_LEN("SUBSTR_ORACLE") }, + BUILDER(Create_func_substr_oracle)}, { { C_STRING_WITH_LEN("SUBSTRING_INDEX") }, BUILDER(Create_func_substr_index)}, { { C_STRING_WITH_LEN("SUBTIME") }, BUILDER(Create_func_subtime)}, { { C_STRING_WITH_LEN("TAN") }, BUILDER(Create_func_tan)}, diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 3047595b58c..fe089e6283d 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -66,9 +66,9 @@ String *Item_func_geometry_from_text::val_str(String *str) srid= (uint32)args[1]->val_int(); str->set_charset(&my_charset_bin); + str->length(0); if (str->reserve(SRID_SIZE, 512)) return 0; - str->length(0); str->q_append(srid); if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0))) return 0; @@ -1323,6 +1323,8 @@ static int setup_relate_func(Geometry *g1, Geometry *g2, } else func->repeat_expression(shape_a); + if (func->reserve_op_buffer(1)) + return 1; func->add_operation(op_matrix(nc%3), 1); if (do_store_shapes) { @@ -1493,11 +1495,13 @@ longlong Item_func_spatial_precise_rel::val_int() Gcalc_function::op_intersection, 2); func.add_operation(Gcalc_function::op_internals, 1); shape_a= func.get_next_expression_pos(); - if ((null_value= g1.store_shapes(&trn))) + if ((null_value= g1.store_shapes(&trn)) || + func.reserve_op_buffer(1)) break; func.add_operation(Gcalc_function::op_internals, 1); shape_b= func.get_next_expression_pos(); - if ((null_value= g2.store_shapes(&trn))) + if ((null_value= g2.store_shapes(&trn)) || + func.reserve_op_buffer(1)) break; func.add_operation(Gcalc_function::v_find_t | Gcalc_function::op_intersection, 2); @@ -1732,6 +1736,8 @@ int Item_func_buffer::Transporter::single_point(double x, double y) { if (buffer_op == Gcalc_function::op_difference) { + if (m_fn->reserve_op_buffer(1)) + return 1; m_fn->add_operation(Gcalc_function::op_false, 0); return 0; } diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index f804f83f122..7edafa3dc33 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -581,7 +581,8 @@ String *Item_func_json_quote::val_str(String *str) void Item_func_json_unquote::fix_length_and_dec() { - collation.set(&my_charset_utf8_general_ci); + collation.set(&my_charset_utf8_general_ci, + DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); max_length= args[0]->max_length; maybe_null= 1; } @@ -1011,6 +1012,8 @@ static int check_contains(json_engine_t *js, json_engine_t *value) case JSON_VALUE_ARRAY: if (value->value_type != JSON_VALUE_ARRAY) { + loc_js= *value; + set_js= FALSE; while (json_scan_next(js) == 0 && js->state != JST_ARRAY_END) { int c_level, v_scalar; @@ -1021,6 +1024,11 @@ static int check_contains(json_engine_t *js, json_engine_t *value) if (!(v_scalar= json_value_scalar(js))) c_level= json_get_level(js); + if (set_js) + *value= loc_js; + else + set_js= TRUE; + if (check_contains(js, value)) { if (json_skip_level(js)) @@ -1452,7 +1460,8 @@ void Item_func_json_array::fix_length_and_dec() if (arg_count == 0) { - collation.set(&my_charset_utf8_general_ci); + collation.set(&my_charset_utf8_general_ci, + DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII); tmp_val.set_charset(&my_charset_utf8_general_ci); max_length= 2; return; @@ -2126,6 +2135,7 @@ longlong Item_func_json_length::val_int() json_engine_t je; uint length= 0; uint array_counters[JSON_DEPTH_LIMIT]; + int err; if ((null_value= args[0]->null_value)) return 0; @@ -2167,7 +2177,7 @@ longlong Item_func_json_length::val_int() if (json_value_scalar(&je)) return 1; - while (json_scan_next(&je) == 0 && + while (!(err= json_scan_next(&je)) && je.state != JST_OBJ_END && je.state != JST_ARRAY_END) { switch (je.state) @@ -2186,6 +2196,12 @@ longlong Item_func_json_length::val_int() }; } + if (!err) + { + /* Parse to the end of the JSON just to check it's valid. */ + while (json_scan_next(&je) == 0) {} + } + if (!je.s.error) return length; diff --git a/sql/item_row.cc b/sql/item_row.cc index 8b7cc814694..3b8bd8d3e59 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -24,7 +24,6 @@ #include "sql_class.h" // THD, set_var.h: THD #include "set_var.h" - void Item_row::illegal_method_call(const char *method) { DBUG_ENTER("Item_row::illegal_method_call"); diff --git a/sql/item_row.h b/sql/item_row.h index 9c92e19caab..83e9743fede 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -47,13 +47,10 @@ public: Item_row(THD *thd, List<Item> &list): Item(thd), Item_args(thd, list), not_null_tables_cache(0), with_null(0) { } - Item_row(THD *thd, Item_row *item): - Item(thd), - Item_args(item), - Used_tables_and_const_cache(item), - not_null_tables_cache(0), - with_null(0) - {} + Item_row(THD *thd, Item_row *row): + Item(thd), Item_args(thd, static_cast<Item_args*>(row)), Used_tables_and_const_cache(), + not_null_tables_cache(0), with_null(0) + { } enum Type type() const { return ROW_ITEM; }; const Type_handler *type_handler() const { return &type_handler_row; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d9b375e7be1..90bfb11e822 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1777,7 +1777,7 @@ String *Item_func_substr::val_str(String *str) DBUG_ASSERT(fixed == 1); String *res = args[0]->val_str(str); /* must be longlong to avoid truncation */ - longlong start= args[1]->val_int(); + longlong start= get_position(); /* Assumes that the maximum length of a String is < INT_MAX32. */ /* Limit so that code sees out-of-bound value properly. */ longlong length= arg_count == 3 ? args[2]->val_int() : INT_MAX32; @@ -1827,7 +1827,7 @@ void Item_func_substr::fix_length_and_dec() DBUG_ASSERT(collation.collation != NULL); if (args[1]->const_item()) { - int32 start= (int32) args[1]->val_int(); + int32 start= (int32) get_position(); if (args[1]->null_value) max_length= 0; else if (start < 0) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 1c35588f884..c322136bef2 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -505,9 +505,12 @@ public: class Item_func_substr :public Item_str_func { String tmp_value; +protected: + virtual longlong get_position() { return args[1]->val_int(); } public: Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} - Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {} + 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(); const char *func_name() const { return "substr"; } @@ -515,6 +518,20 @@ public: { return get_item_copy<Item_func_substr>(thd, mem_root, this); } }; +class Item_func_substr_oracle :public Item_func_substr +{ +protected: + longlong get_position() + { longlong pos= args[1]->val_int(); return pos == 0 ? 1 : pos; } +public: + Item_func_substr_oracle(THD *thd, Item *a, Item *b): + 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) {} + const char *func_name() const { return "substr_oracle"; } + Item *get_copy(THD *thd, MEM_ROOT *mem_root) + { return get_item_copy<Item_func_substr_oracle>(thd, mem_root, this); } +}; class Item_func_substr_index :public Item_str_func { diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 84e1aae1ad5..1f2949903b4 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1433,6 +1433,10 @@ Item_in_subselect::Item_in_subselect(THD *thd, Item * left_exp, DBUG_ENTER("Item_in_subselect::Item_in_subselect"); DBUG_PRINT("info", ("in_strategy: %u", (uint)in_strategy)); left_expr_orig= left_expr= left_exp; + /* prepare to possible disassembling the item in convert_subq_to_sj() */ + if (left_exp->type() == Item::ROW_ITEM) + left_expr_orig= new (thd->mem_root) + Item_row(thd, static_cast<Item_row*>(left_exp)); func= &eq_creator; init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= UINT_MAX; @@ -1456,6 +1460,10 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp, { DBUG_ENTER("Item_allany_subselect::Item_allany_subselect"); left_expr_orig= left_expr= left_exp; + /* prepare to possible disassembling the item in convert_subq_to_sj() */ + if (left_exp->type() == Item::ROW_ITEM) + left_expr_orig= new (thd->mem_root) + Item_row(thd, static_cast<Item_row*>(left_exp)); func= func_creator(all_arg); init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this)); max_columns= 1; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index d6e42efd11c..b047dc4ea4d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3593,7 +3593,7 @@ bool Item_func_group_concat::setup(THD *thd) syntax of this function). If there is no ORDER BY clause, we don't create this tree. */ - init_tree(tree, (uint) MY_MIN(thd->variables.max_heap_table_size, + init_tree(tree, (size_t)MY_MIN(thd->variables.max_heap_table_size, thd->variables.sortbuff_size/16), 0, tree_key_length, group_concat_key_cmp_with_order, NULL, (void*) this, diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index d00120018b8..3a7684fe7b4 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -1825,9 +1825,18 @@ overflow: ltime->hour= TIME_MAX_HOUR+1; check_time_range(ltime, decimals, &unused); - make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, - err->ptr(), err->length(), - MYSQL_TIMESTAMP_TIME, NullS); + if (!err) + { + ErrConvInteger err2(sec, unsigned_flag); + make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, + &err2, MYSQL_TIMESTAMP_TIME, NullS); + } + else + { + ErrConvString err2(err); + make_truncated_value_warning(current_thd, Sql_condition::WARN_LEVEL_WARN, + &err2, MYSQL_TIMESTAMP_TIME, NullS); + } return 0; } diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 94794c6789d..9c102e8a666 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -574,8 +574,6 @@ public: bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date) { DBUG_ASSERT(0); return 1; } my_decimal *val_decimal(my_decimal *decimal_value) { return val_decimal_from_date(decimal_value); } - int save_in_field(Field *field, bool no_conversions) - { return save_date_in_field(field, no_conversions); } }; diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index ba24ebe76c5..ee307ba2194 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -176,7 +176,7 @@ public: { nodebeg= (MY_XML_NODE*) pxml->ptr(); nodeend= (MY_XML_NODE*) (pxml->ptr() + pxml->length()); - numnodes= nodeend - nodebeg; + numnodes= (uint)(nodeend - nodebeg); } void prepare(String *nodeset) { @@ -615,7 +615,7 @@ public: if ((node->parent == flt->num) && (node->type == MY_XML_NODE_TEXT)) { - fake->set_value(node->beg, node->end - node->beg, + fake->set_value(node->beg, (uint)(node->end - node->beg), collation.collation); if (args[1]->val_int()) return 1; @@ -817,7 +817,7 @@ String *Item_nodeset_func_predicate::val_nodeset(String *str) Item_func *comp_func= (Item_func*)args[1]; uint pos= 0, size; prepare(str); - size= fltend - fltbeg; + size= (uint)(fltend - fltbeg); for (MY_XPATH_FLT *flt= fltbeg; flt < fltend; flt++) { nodeset_func->context_cache.length(0); @@ -836,7 +836,7 @@ String *Item_nodeset_func_elementbyindex::val_nodeset(String *nodeset) Item_nodeset_func *nodeset_func= (Item_nodeset_func*) args[0]; prepare(nodeset); MY_XPATH_FLT *flt; - uint pos, size= fltend - fltbeg; + uint pos, size= (uint)(fltend - fltbeg); for (pos= 0, flt= fltbeg; flt < fltend; flt++) { nodeset_func->context_cache.length(0); @@ -995,7 +995,7 @@ static Item *create_comparator(MY_XPATH *xpath, else if (a->type() == Item::XPATH_NODESET && b->type() == Item::XPATH_NODESET) { - uint len= xpath->query.end - context->beg; + uint len= (uint)(xpath->query.end - context->beg); set_if_smaller(len, 32); my_printf_error(ER_UNKNOWN_ERROR, "XPATH error: " @@ -1399,7 +1399,7 @@ MY_XPATH_FUNC * my_xpath_function(const char *beg, const char *end) { MY_XPATH_FUNC *k, *function_names; - uint length= end-beg; + uint length= (uint)(end-beg); switch (length) { case 1: return 0; @@ -1961,7 +1961,7 @@ static int my_xpath_parse_PrimaryExpr_literal(MY_XPATH *xpath) return 0; xpath->item= new (xpath->thd->mem_root) Item_string(xpath->thd, xpath->prevtok.beg + 1, - xpath->prevtok.end - xpath->prevtok.beg - 2, + (uint)(xpath->prevtok.end - xpath->prevtok.beg - 2), xpath->cs); return 1; } @@ -2499,13 +2499,13 @@ static int my_xpath_parse_Number(MY_XPATH *xpath) if (!my_xpath_parse_term(xpath, MY_XPATH_LEX_DOT)) { xpath->item= new (thd->mem_root) Item_int(thd, xpath->prevtok.beg, - xpath->prevtok.end - xpath->prevtok.beg); + (uint)(xpath->prevtok.end - xpath->prevtok.beg)); return 1; } my_xpath_parse_term(xpath, MY_XPATH_LEX_DIGITS); xpath->item= new (thd->mem_root) Item_float(thd, beg, - xpath->prevtok.end - beg); + (uint)(xpath->prevtok.end - beg)); return 1; } @@ -2621,7 +2621,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath) (spv= spc->find_variable(&name, false))) { Item_splocal *splocal= new (thd->mem_root) - Item_splocal(thd, &name, spv->offset, spv->sql_type(), 0); + Item_splocal(thd, &name, spv->offset, spv->type_handler(), 0); #ifdef DBUG_ASSERT_EXISTS if (splocal) splocal->m_sp= lex->sphead; @@ -2632,7 +2632,7 @@ my_xpath_parse_VariableReference(MY_XPATH *xpath) { xpath->item= NULL; DBUG_ASSERT(xpath->query.end > dollar_pos); - uint len= xpath->query.end - dollar_pos; + uint len= (uint)(xpath->query.end - dollar_pos); set_if_smaller(len, 32); my_printf_error(ER_UNKNOWN_ERROR, "Unknown XPATH variable at: '%.*s'", MYF(0), len, dollar_pos); @@ -2660,7 +2660,7 @@ my_xpath_parse_NodeTest_QName(MY_XPATH *xpath) if (!my_xpath_parse_QName(xpath)) return 0; DBUG_ASSERT(xpath->context); - uint len= xpath->prevtok.end - xpath->prevtok.beg; + uint len= (uint)(xpath->prevtok.end - xpath->prevtok.beg); xpath->context= nametestfunc(xpath, xpath->axis, xpath->context, xpath->prevtok.beg, len); return 1; @@ -2759,7 +2759,7 @@ bool Item_xml_str_func::fix_fields(THD *thd, Item **ref) if (!rc) { - uint clen= xpath.query.end - xpath.lasttok.beg; + uint clen= (uint)(xpath.query.end - xpath.lasttok.beg); set_if_smaller(clen, 32); my_printf_error(ER_UNKNOWN_ERROR, "XPATH syntax error: '%.*s'", MYF(0), clen, xpath.lasttok.beg); diff --git a/sql/log.cc b/sql/log.cc index 450f677d363..008cc0b59aa 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -3044,7 +3044,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time, if (thd->spcont) if (my_b_printf(&log_file, "# Stored_routine: %s\n", - ErrConvDQName(thd->spcont->sp).ptr()) == (uint) -1) + ErrConvDQName(thd->spcont->m_sp).ptr()) == (uint) -1) tmp_errno= errno; if ((thd->variables.log_slow_verbosity & LOG_SLOW_VERBOSITY_QUERY_PLAN) && diff --git a/sql/log_event.cc b/sql/log_event.cc index 841478b511b..f1ceaec6456 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1131,7 +1131,7 @@ int append_query_string(CHARSET_INFO *csinfo, String *to, *ptr++= '\''; } - to->length(orig_len + ptr - beg); + to->length((uint32)(orig_len + ptr - beg)); return 0; } #endif @@ -8681,21 +8681,6 @@ User_var_log_event(const char* buf, uint event_len, we keep the flags set to UNDEF_F. */ size_t bytes_read= ((val + val_len) - buf_start); -#ifdef DBUG_ASSERT_EXISTS - bool old_pre_checksum_fd= description_event->is_version_before_checksum( - &description_event->server_version_split); -#endif - DBUG_ASSERT((bytes_read == data_written - - (old_pre_checksum_fd || - (description_event->checksum_alg == - BINLOG_CHECKSUM_ALG_OFF)) ? - 0 : BINLOG_CHECKSUM_LEN) - || - (bytes_read == data_written -1 - - (old_pre_checksum_fd || - (description_event->checksum_alg == - BINLOG_CHECKSUM_ALG_OFF)) ? - 0 : BINLOG_CHECKSUM_LEN)); if ((data_written - bytes_read) > 0) { flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + @@ -10041,7 +10026,7 @@ Execute_load_query_log_event::do_apply_event(rpl_group_info *rgi) p= strmake(p, STRING_WITH_LEN(" INTO ")); p= strmake(p, query+fn_pos_end, q_len-fn_pos_end); - error= Query_log_event::do_apply_event(rgi, buf, p-buf); + error= Query_log_event::do_apply_event(rgi, buf, (uint32)(p-buf)); /* Forging file name for deletion in same buffer */ *fname_end= 0; @@ -10493,7 +10478,7 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length) { size_t const block_size= 1024; - ulong cur_size= m_rows_cur - m_rows_buf; + size_t cur_size= m_rows_cur - m_rows_buf; DBUG_EXECUTE_IF("simulate_too_big_row_case1", cur_size= UINT_MAX32 - (block_size * 10); length= UINT_MAX32 - (block_size * 10);); @@ -10506,21 +10491,21 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) DBUG_EXECUTE_IF("simulate_too_big_row_case4", cur_size= UINT_MAX32 - (block_size * 10); length= (block_size * 10) - block_size + 1;); - ulong remaining_space= UINT_MAX32 - cur_size; + size_t remaining_space= UINT_MAX32 - cur_size; /* Check that the new data fits within remaining space and we can add block_size without wrapping. */ - if (length > remaining_space || + if (cur_size > UINT_MAX32 || length > remaining_space || ((length + block_size) > remaining_space)) { sql_print_error("The row data is greater than 4GB, which is too big to " "write to the binary log."); DBUG_RETURN(ER_BINLOG_ROW_LOGGING_FAILED); } - ulong const new_alloc= + size_t const new_alloc= block_size * ((cur_size + length + block_size - 1) / block_size); - uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc, + uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, new_alloc, MYF(MY_ALLOW_ZERO_PTR|MY_WME)); if (unlikely(!new_buf)) DBUG_RETURN(HA_ERR_OUT_OF_MEM); @@ -11253,11 +11238,11 @@ bool Rows_log_event::write_compressed() uchar *m_rows_cur_tmp = m_rows_cur; bool ret = true; uint32 comlen, alloc_size; - comlen= alloc_size= binlog_get_compress_len(m_rows_cur_tmp - m_rows_buf_tmp); + comlen= alloc_size= binlog_get_compress_len((uint32)(m_rows_cur_tmp - m_rows_buf_tmp)); m_rows_buf = (uchar *)my_safe_alloca(alloc_size); if(m_rows_buf && !binlog_buf_compress((const char *)m_rows_buf_tmp, (char *)m_rows_buf, - m_rows_cur_tmp - m_rows_buf_tmp, &comlen)) + (uint32)(m_rows_cur_tmp - m_rows_buf_tmp), &comlen)) { m_rows_cur= comlen + m_rows_buf; ret= Log_event::write(); @@ -12493,7 +12478,7 @@ Rows_log_event::write_row(rpl_group_info *rgi, the size of the first row and use that value to initialize storage engine for bulk insertion */ DBUG_ASSERT(!(m_curr_row > m_curr_row_end)); - ulong estimated_rows= 0; + ha_rows estimated_rows= 0; if (m_curr_row < m_curr_row_end) estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row); else if (m_curr_row == m_curr_row_end) @@ -12712,7 +12697,7 @@ int Rows_log_event::update_sequence() longlong round= table->field[ROUND_FIELD_NO]->val_int(); dbug_tmp_restore_column_map(table->read_set, old_map); - return table->s->sequence->set_value(table, nextval, round, 0); + return table->s->sequence->set_value(table, nextval, round, 0) > 0; } /* @@ -12731,6 +12716,7 @@ Write_rows_log_event::do_exec_row(rpl_group_info *rgi) DBUG_ASSERT(m_table != NULL); const char *tmp= thd->get_proc_info(); const char *message= "Write_rows_log_event::write_row()"; + int error; #ifdef WSREP_PROC_INFO my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, @@ -12740,7 +12726,7 @@ Write_rows_log_event::do_exec_row(rpl_group_info *rgi) #endif /* WSREP_PROC_INFO */ thd_proc_info(thd, message); - int error= write_row(rgi, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT); + error= write_row(rgi, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT); thd_proc_info(thd, tmp); if (error && !thd->is_error()) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4fcdc37c912..ad27c58f67f 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -8867,8 +8867,8 @@ static int mysql_init_variables(void) /* Set directory paths */ mysql_real_data_home_len= - strmake_buf(mysql_real_data_home, - get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home; + (uint)(strmake_buf(mysql_real_data_home, + get_relative_path(MYSQL_DATADIR)) - mysql_real_data_home); /* Replication parameters */ master_info_file= (char*) "master.info", relay_log_info_file= (char*) "relay-log.info"; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 404c5a1f6d3..3180c509737 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -499,9 +499,9 @@ int SEL_IMERGE::or_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree) if (trees_next == trees_end) { const int realloc_ratio= 2; /* Double size for next round */ - uint old_elements= (trees_end - trees); - uint old_size= sizeof(SEL_TREE**) * old_elements; - uint new_size= old_size * realloc_ratio; + size_t old_elements= (trees_end - trees); + size_t old_size= sizeof(SEL_TREE**) * old_elements; + size_t new_size= old_size * realloc_ratio; SEL_TREE **new_trees; if (!(new_trees= (SEL_TREE**)alloc_root(param->mem_root, new_size))) return -1; @@ -846,10 +846,10 @@ SEL_TREE::SEL_TREE(SEL_TREE *arg, bool without_merges, SEL_IMERGE::SEL_IMERGE(SEL_IMERGE *arg, uint cnt, RANGE_OPT_PARAM *param) : Sql_alloc() { - uint elements= (arg->trees_end - arg->trees); + size_t elements= (arg->trees_end - arg->trees); if (elements > PREALLOCED_TREES) { - uint size= elements * sizeof (SEL_TREE **); + size_t size= elements * sizeof (SEL_TREE **); if (!(trees= (SEL_TREE **)alloc_root(param->mem_root, size))) goto mem_err; } @@ -951,7 +951,7 @@ int imerge_list_or_list(RANGE_OPT_PARAM *param, uint rc; bool is_last_check_pass= FALSE; SEL_IMERGE *imerge= im1->head(); - uint elems= imerge->trees_next-imerge->trees; + uint elems= (uint)(imerge->trees_next-imerge->trees); MEM_ROOT *mem_root= current_thd->mem_root; im1->empty(); @@ -1051,7 +1051,7 @@ int imerge_list_or_tree(RANGE_OPT_PARAM *param, SEL_TREE *or_tree= new (mem_root) SEL_TREE (tree, FALSE, param); if (or_tree) { - uint elems= imerge->trees_next-imerge->trees; + uint elems= (uint)(imerge->trees_next-imerge->trees); rc= imerge->or_sel_tree_with_checks(param, elems, or_tree, TRUE, &is_last_check_pass); if (!is_last_check_pass) @@ -2897,7 +2897,7 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond) uint keynr; uint max_quick_key_parts= 0; MY_BITMAP *used_fields= &table->cond_set; - double table_records= table->stat_records(); + double table_records= (double)table->stat_records(); DBUG_ENTER("calculate_cond_selectivity_for_table"); table->cond_selectivity= 1.0; @@ -3994,8 +3994,8 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree) store_length_array, range_par->min_key, range_par->max_key, - tmp_min_key - range_par->min_key, - tmp_max_key - range_par->max_key, + (uint)(tmp_min_key - range_par->min_key), + (uint)(tmp_max_key - range_par->max_key), flag, &ppar->part_iter); if (!res) @@ -4643,6 +4643,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, double roru_index_costs; ha_rows roru_total_records; double roru_intersect_part= 1.0; + size_t n_child_scans; DBUG_ENTER("get_best_disjunct_quick"); DBUG_PRINT("info", ("Full table scan cost: %g", read_time)); @@ -4659,7 +4660,7 @@ TABLE_READ_PLAN *get_best_disjunct_quick(PARAM *param, SEL_IMERGE *imerge, } } - uint n_child_scans= imerge->trees_next - imerge->trees; + n_child_scans= imerge->trees_next - imerge->trees; if (!n_child_scans) DBUG_RETURN(NULL); @@ -4877,8 +4878,8 @@ skip_to_ror_scan: (TIME_FOR_COMPARE_ROWID * M_LN2) + get_sweep_read_cost(param, roru_total_records); - DBUG_PRINT("info", ("ROR-union: cost %g, %d members", roru_total_cost, - n_child_scans)); + DBUG_PRINT("info", ("ROR-union: cost %g, %zu members", + roru_total_cost, n_child_scans)); TRP_ROR_UNION* roru; if (roru_total_cost < read_time) { @@ -5203,7 +5204,7 @@ bool prepare_search_best_index_intersect(PARAM *param, INDEX_SCAN_INFO **scan_ptr; INDEX_SCAN_INFO *cpk_scan= NULL; TABLE *table= param->table; - uint n_index_scans= tree->index_scans_end - tree->index_scans; + uint n_index_scans= (uint)(tree->index_scans_end - tree->index_scans); if (!n_index_scans) return 1; @@ -5846,7 +5847,7 @@ TRP_INDEX_INTERSECT *get_best_index_intersect(PARAM *param, SEL_TREE *tree, } } - count= tree->index_scans_end - tree->index_scans; + count= (uint)(tree->index_scans_end - tree->index_scans); for (i= 0; i < count; i++) { index_scan= tree->index_scans[i]; @@ -6506,7 +6507,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree, intersect_scans_best);); *are_all_covering= intersect->is_covering; - uint best_num= intersect_scans_best - intersect_scans; + uint best_num= (uint)(intersect_scans_best - intersect_scans); ror_intersect_cpy(intersect, intersect_best); /* @@ -6688,7 +6689,7 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, TRP_ROR_INTERSECT *trp; if (!(trp= new (param->mem_root) TRP_ROR_INTERSECT)) DBUG_RETURN(trp); - uint best_num= (ror_scan_mark - tree->ror_scans); + uint best_num= (uint)(ror_scan_mark - tree->ror_scans); if (!(trp->first_scan= (ROR_SCAN_INFO**)alloc_root(param->mem_root, sizeof(ROR_SCAN_INFO*)* best_num))) @@ -8557,6 +8558,34 @@ bool sel_trees_can_be_ored(RANGE_OPT_PARAM* param, } /* + Check whether the key parts inf_init..inf_end-1 of one index can compose + an infix for the key parts key_init..key_end-1 of another index +*/ + +static +bool is_key_infix(KEY_PART *key_init, KEY_PART *key_end, + KEY_PART *inf_init, KEY_PART *inf_end) +{ + KEY_PART *key_part, *inf_part; + for (key_part= key_init; key_part < key_end; key_part++) + { + if (key_part->field->eq(inf_init->field)) + break; + } + if (key_part == key_end) + return false; + for (key_part++, inf_part= inf_init + 1; + key_part < key_end && inf_part < inf_end; + key_part++, inf_part++) + { + if (!key_part->field->eq(inf_part->field)) + return false; + } + return inf_part == inf_end; +} + + +/* Check whether range parts of two trees must be ored for some indexes SYNOPSIS @@ -8612,14 +8641,9 @@ bool sel_trees_must_be_ored(RANGE_OPT_PARAM* param, KEY_PART *key2_init= param->key[idx2]+tree2->keys[idx2]->part; KEY_PART *key2_end= param->key[idx2]+tree2->keys[idx2]->max_part_no; - KEY_PART *part1, *part2; - for (part1= key1_init, part2= key2_init; - part1 < key1_end && part2 < key2_end; - part1++, part2++) - { - if (!part1->field->eq(part2->field)) - DBUG_RETURN(FALSE); - } + if (!is_key_infix(key1_init, key1_end, key2_init, key2_end) && + !is_key_infix(key2_init, key2_end, key1_init, key1_end)) + DBUG_RETURN(FALSE); } } @@ -11476,7 +11500,7 @@ int QUICK_RANGE_SELECT::get_next_prefix(uint prefix_length, DBUG_RETURN(0); } - uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer); + uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer); if (count == 0) { /* Ranges have already been used up before. None is left for read. */ @@ -11521,7 +11545,7 @@ int QUICK_RANGE_SELECT_GEOM::get_next() DBUG_RETURN(result); } - uint count= ranges.elements - (cur_range - (QUICK_RANGE**) ranges.buffer); + uint count= ranges.elements - (uint)(cur_range - (QUICK_RANGE**) ranges.buffer); if (count == 0) { /* Ranges have already been used up before. None is left for read. */ @@ -11975,7 +11999,7 @@ void QUICK_SELECT_I::add_key_and_length(String *key_names, bool *first) { char buf[64]; - uint length; + size_t length; KEY *key_info= head->key_info + index; if (*first) @@ -12529,7 +12553,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time) { cur_group_prefix_len+= cur_part->store_length; ++cur_group_key_parts; - max_key_part= cur_part - cur_index_info->key_part + 1; + max_key_part= (uint)(cur_part - cur_index_info->key_part) + 1; used_key_parts_map.set_bit(max_key_part); } else @@ -13252,7 +13276,7 @@ get_field_keypart(KEY *index, Field *field) part < end; part++) { if (field->eq(part->field)) - return part - index->key_part + 1; + return (uint)(part - index->key_part + 1); } return 0; } diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc index b3350191d13..ace6208fd77 100644 --- a/sql/opt_range_mrr.cc +++ b/sql/opt_range_mrr.cc @@ -199,9 +199,9 @@ walk_right_n_up: { { RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i]; - uint min_key_length= cur->min_key - seq->param->min_key; - uint max_key_length= cur->max_key - seq->param->max_key; - uint len= cur->min_key - cur[-1].min_key; + size_t min_key_length= cur->min_key - seq->param->min_key; + size_t max_key_length= cur->max_key - seq->param->max_key; + size_t len= cur->min_key - cur[-1].min_key; if (!(min_key_length == max_key_length && !memcmp(cur[-1].min_key, cur[-1].max_key, len) && !key_tree->min_flag && !key_tree->max_flag)) @@ -238,7 +238,7 @@ walk_up_n_right: /* Ok got a tuple */ RANGE_SEQ_ENTRY *cur= &seq->stack[seq->i]; - uint min_key_length= cur->min_key - seq->param->min_key; + uint min_key_length= (uint)(cur->min_key - seq->param->min_key); range->ptr= (char*)(intptr)(key_tree->part); if (cur->min_key_flag & GEOM_FLAG) @@ -256,13 +256,13 @@ walk_up_n_right: range->range_flag= cur->min_key_flag | cur->max_key_flag; range->start_key.key= seq->param->min_key; - range->start_key.length= cur->min_key - seq->param->min_key; + range->start_key.length= (uint)(cur->min_key - seq->param->min_key); range->start_key.keypart_map= make_prev_keypart_map(cur->min_key_parts); range->start_key.flag= (cur->min_key_flag & NEAR_MIN ? HA_READ_AFTER_KEY : HA_READ_KEY_EXACT); range->end_key.key= seq->param->max_key; - range->end_key.length= cur->max_key - seq->param->max_key; + range->end_key.length= (uint)(cur->max_key - seq->param->max_key); range->end_key.flag= (cur->max_key_flag & NEAR_MAX ? HA_READ_BEFORE_KEY : HA_READ_AFTER_KEY); range->end_key.keypart_map= make_prev_keypart_map(cur->max_key_parts); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 5335001683c..6dc5e08152c 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1589,6 +1589,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) sj-nest. */ st_select_lex *subq_lex= subq_pred->unit->first_select(); + DBUG_ASSERT(subq_lex->next_select() == NULL); nested_join->join_list.empty(); List_iterator_fast<TABLE_LIST> li(subq_lex->top_join_list); TABLE_LIST *tl; @@ -1692,7 +1693,8 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) if (subq_pred->left_expr->cols() == 1) { - nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr, + /* add left = select_list_element */ + nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr, thd->mem_root); /* Create Item_func_eq. Note that @@ -1706,26 +1708,62 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) Item_func_eq *item_eq= new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, subq_lex->ref_pointer_array[0]); + if (!item_eq) + DBUG_RETURN(TRUE); if (subq_pred->left_expr_orig != subq_pred->left_expr) thd->change_item_tree(item_eq->arguments(), subq_pred->left_expr); item_eq->in_equality_no= 0; sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq); } - else + else if (subq_pred->left_expr->type() == Item::ROW_ITEM) { + /* + disassemple left expression and add + left1 = select_list_element1 and left2 = select_list_element2 ... + */ for (uint i= 0; i < subq_pred->left_expr->cols(); i++) { - nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr-> - element_index(i), + nested_join->sj_outer_expr_list.push_back(subq_pred->left_expr->addr(i), thd->mem_root); - Item_func_eq *item_eq= + Item_func_eq *item_eq= new (thd->mem_root) - Item_func_eq(thd, subq_pred->left_expr->element_index(i), + Item_func_eq(thd, subq_pred->left_expr_orig->element_index(i), subq_lex->ref_pointer_array[i]); + if (!item_eq) + DBUG_RETURN(TRUE); + DBUG_ASSERT(subq_pred->left_expr->element_index(i)->fixed); + if (subq_pred->left_expr_orig->element_index(i) != + subq_pred->left_expr->element_index(i)) + thd->change_item_tree(item_eq->arguments(), + subq_pred->left_expr->element_index(i)); item_eq->in_equality_no= i; sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq); } } + else + { + /* + add row operation + left = (select_list_element1, select_list_element2, ...) + */ + Item_row *row= new (thd->mem_root) Item_row(thd, subq_lex->pre_fix); + /* fix fields on subquery was call so they should be the same */ + DBUG_ASSERT(subq_pred->left_expr->cols() == row->cols()); + if (!row) + DBUG_RETURN(TRUE); + nested_join->sj_outer_expr_list.push_back(&subq_pred->left_expr); + Item_func_eq *item_eq= + new (thd->mem_root) Item_func_eq(thd, subq_pred->left_expr_orig, row); + if (!item_eq) + DBUG_RETURN(TRUE); + for (uint i= 0; i < row->cols(); i++) + { + if (row->element_index(i) != subq_lex->ref_pointer_array[i]) + thd->change_item_tree(row->addr(i), subq_lex->ref_pointer_array[i]); + } + item_eq->in_equality_no= 0; + sj_nest->sj_on_expr= and_items(thd, sj_nest->sj_on_expr, item_eq); + } /* Fix the created equality and AND @@ -3274,8 +3312,8 @@ void restore_prev_sj_state(const table_map remaining_tables, ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, table_map remaining_tables) { - List_iterator<Item> li(sj_nest->nested_join->sj_outer_expr_list); - Item *item; + List_iterator<Item_ptr> li(sj_nest->nested_join->sj_outer_expr_list); + Item **item; uint i= 0; ulonglong res= 0; while ((item= li++)) @@ -3286,7 +3324,7 @@ ulonglong get_bound_sj_equalities(TABLE_LIST *sj_nest, class and see if there is an element that is bound? (this is an optional feature) */ - if (!(item->used_tables() & remaining_tables)) + if (!(item[0]->used_tables() & remaining_tables)) { res |= 1ULL << i; } diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc index 6cdf0e0f26a..72b28473e15 100644 --- a/sql/opt_sum.cc +++ b/sql/opt_sum.cc @@ -768,12 +768,12 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo, key_part_map org_key_part_used= *key_part_used; if (eq_type || between || max_fl == less_fl) { - uint length= (key_ptr-ref->key_buff)+part->store_length; + uint length= (uint)(key_ptr-ref->key_buff)+part->store_length; if (ref->key_length < length) { /* Ultimately ref->key_length will contain the length of the search key */ ref->key_length= length; - ref->key_parts= (part - keyinfo->key_part) + 1; + ref->key_parts= (uint)(part - keyinfo->key_part) + 1; } if (!*prefix_len && part+1 == field_part) *prefix_len= length; diff --git a/sql/opt_table_elimination.cc b/sql/opt_table_elimination.cc index 1d6fb4dabfe..390afc575ca 100644 --- a/sql/opt_table_elimination.cc +++ b/sql/opt_table_elimination.cc @@ -849,7 +849,7 @@ bool check_func_dependency(JOIN *join, */ uint and_level=0; build_eq_mods_for_cond(join->thd, &dac, &last_eq_mod, &and_level, cond); - if (!(dac.n_equality_mods= last_eq_mod - dac.equality_mods)) + if (!(dac.n_equality_mods= (uint)(last_eq_mod - dac.equality_mods))) return FALSE; /* No useful conditions */ List<Dep_module> bound_modules; @@ -1062,7 +1062,7 @@ bool Dep_analysis_context::setup_equality_modules_deps(List<Dep_module> eq_mod < equality_mods + n_equality_mods; eq_mod++) { - deps_recorder.expr_offset= eq_mod - equality_mods; + deps_recorder.expr_offset= (uint)(eq_mod - equality_mods); deps_recorder.visited_other_tables= FALSE; eq_mod->unbound_args= 0; @@ -1080,7 +1080,7 @@ bool Dep_analysis_context::setup_equality_modules_deps(List<Dep_module> Dep_value_field* field_val; while ((field_val= it++)) { - uint offs= field_val->bitmap_offset + eq_mod - equality_mods; + uint offs= (uint)(field_val->bitmap_offset + eq_mod - equality_mods); bitmap_set_bit(&expr_deps, offs); } } @@ -1159,7 +1159,7 @@ void build_eq_mods_for_cond(THD *thd, Dep_analysis_context *ctx, if (cond->type() == Item_func::COND_ITEM) { List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list()); - uint orig_offset= *eq_mod - ctx->equality_mods; + size_t orig_offset= *eq_mod - ctx->equality_mods; /* AND/OR */ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) diff --git a/sql/parse_file.cc b/sql/parse_file.cc index ebb08a23009..aedb7a4f0af 100644 --- a/sql/parse_file.cc +++ b/sql/parse_file.cc @@ -255,7 +255,7 @@ sql_create_definition_file(const LEX_CSTRING *dir, File handler; IO_CACHE file; char path[FN_REFLEN+1]; // +1 to put temporary file name for sure - int path_end; + size_t path_end; File_option *param; DBUG_ENTER("sql_create_definition_file"); DBUG_PRINT("enter", ("Dir: %s, file: %s, base %p", diff --git a/sql/partition_info.cc b/sql/partition_info.cc index a52c7873817..6fdbdfce893 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -1674,7 +1674,7 @@ void partition_info::print_no_partition_found(TABLE *table_arg, myf errflag) bool partition_info::set_part_expr(THD *thd, char *start_token, Item *item_ptr, char *end_token, bool is_subpart) { - uint expr_len= end_token - start_token; + size_t expr_len= end_token - start_token; char *func_string= (char*) thd->memdup(start_token, expr_len); if (!func_string) @@ -2347,7 +2347,7 @@ bool partition_info::fix_column_value_functions(THD *thd, { uchar *val_ptr; uint len= field->pack_length(); - ulonglong save_sql_mode; + sql_mode_t save_sql_mode; bool save_got_warning; if (!(column_item= get_column_item(column_item, diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc index 9ff5004414c..6da3f15cfb9 100644 --- a/sql/rpl_record.cc +++ b/sql/rpl_record.cc @@ -80,7 +80,7 @@ pack_row(TABLE *table, MY_BITMAP const* cols, unsigned int null_mask= 1U; for ( ; (field= *p_field) ; p_field++) { - if (bitmap_is_set(cols, p_field - table->field)) + if (bitmap_is_set(cols, (uint)(p_field - table->field))) { my_ptrdiff_t offset; if (field->is_null(rec_offset)) @@ -262,7 +262,7 @@ unpack_row(rpl_group_info *rgi, No need to bother about columns that does not exist: they have gotten default values when being emptied above. */ - if (bitmap_is_set(cols, field_ptr - begin_ptr)) + if (bitmap_is_set(cols, (uint)(field_ptr - begin_ptr))) { if ((null_mask & 0xFF) == 0) { @@ -434,7 +434,7 @@ unpack_row(rpl_group_info *rgi, if (master_reclength) { if (*field_ptr) - *master_reclength = (*field_ptr)->ptr - table->record[0]; + *master_reclength = (ulong)((*field_ptr)->ptr - table->record[0]); else *master_reclength = table->s->reclength; } diff --git a/sql/rpl_record_old.cc b/sql/rpl_record_old.cc index 4180557f018..523049cf959 100644 --- a/sql/rpl_record_old.cc +++ b/sql/rpl_record_old.cc @@ -134,7 +134,7 @@ unpack_row_old(rpl_group_info *rgi, { Field *const f= *field_ptr; - if (bitmap_is_set(cols, field_ptr - begin_ptr)) + if (bitmap_is_set(cols, (uint)(field_ptr - begin_ptr))) { f->move_field_offset(offset); ptr= f->unpack(f->ptr, ptr, row_buffer_end, 0); @@ -149,14 +149,14 @@ unpack_row_old(rpl_group_info *rgi, } } else - bitmap_clear_bit(rw_set, field_ptr - begin_ptr); + bitmap_clear_bit(rw_set, (uint)(field_ptr - begin_ptr)); } *row_end = ptr; if (master_reclength) { if (*field_ptr) - *master_reclength = (*field_ptr)->ptr - table->record[0]; + *master_reclength = (ulong)((*field_ptr)->ptr - table->record[0]); else *master_reclength = table->s->reclength; } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 0204121c553..e414a674af6 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -7675,8 +7675,11 @@ ER_SLAVE_SAME_ID ER_FLASHBACK_NOT_SUPPORTED eng "Flashback does not support %s %s" -# MARIAROCKS-TODO: Should we add RocksDB error messages here or use some other -# solution? + + +# +# MyRocks error messages +# ER_KEYS_OUT_OF_ORDER eng "Keys are out order during bulk load" @@ -7710,39 +7713,40 @@ ER_UNSUPPORTED_COLLATION ER_METADATA_INCONSISTENCY eng "Table '%s' does not exist, but metadata information exists inside MyRocks. This is a sign of data inconsistency. Please check if '%s.frm' exists, and try to restore it if it does not exist." -ER_KEY_CREATE_DURING_ALTER - eng "MyRocks failed creating new key definitions during alter." - -ER_SK_POPULATE_DURING_ALTER - eng "MyRocks failed populating secondary key during alter." - ER_CF_DIFFERENT eng "Column family ('%s') flag (%d) is different from an existing flag (%d). Assign a new CF flag, or do not change existing CF flag." +ER_RDB_TTL_DURATION_FORMAT + eng "TTL duration (%s) in MyRocks must be an unsigned non-null 64-bit integer." + ER_RDB_STATUS_GENERAL - eng "Status error %d received from RocksDB: %s" + eng "Status error %d received from RocksDB: %s" ER_RDB_STATUS_MSG - eng "%s, Status error %d received from RocksDB: %s" - -ER_NET_OK_PACKET_TOO_LARGE - eng "OK packet too large" + eng "%s, Status error %d received from RocksDB: %s" ER_RDB_TTL_UNSUPPORTED - eng "TTL support is currently disabled when table has secondary indexes or hidden PK." + eng "TTL support is currently disabled when table has a hidden PK." ER_RDB_TTL_COL_FORMAT eng "TTL column (%s) in MyRocks must be an unsigned non-null 64-bit integer, exist inside the table, and have an accompanying ttl duration." -ER_RDB_TTL_DURATION_FORMAT - eng "TTL duration (%s) in MyRocks must be an unsigned non-null 64-bit integer." - ER_PER_INDEX_CF_DEPRECATED eng "The per-index column family option has been deprecated" +ER_KEY_CREATE_DURING_ALTER + eng "MyRocks failed creating new key definitions during alter." + +ER_SK_POPULATE_DURING_ALTER + eng "MyRocks failed populating secondary key during alter." + +# MyRocks messages end ER_SUM_FUNC_WITH_WINDOW_FUNC_AS_ARG eng "Window functions can not be used as arguments to group functions." +ER_NET_OK_PACKET_TOO_LARGE + eng "OK packet too large" + ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION eng "Illegal parameter data types %s and %s for operation '%s'" ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION diff --git a/sql/slave.cc b/sql/slave.cc index 46932e36e95..94e35bec4f8 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3433,7 +3433,6 @@ static int init_slave_thread(THD* thd, Master_info *mi, thd->connection_name= mi->connection_name; thd->variables.sql_log_slow= !MY_TEST(thd->variables.log_slow_disabled_statements & LOG_SLOW_DISABLE_SLAVE); set_slave_thread_options(thd); - thd->client_capabilities = CLIENT_LOCAL_FILES; if (thd_type == SLAVE_THD_SQL) THD_STAGE_INFO(thd, stage_waiting_for_the_next_event_in_relay_log); diff --git a/sql/sp.cc b/sql/sp.cc index e2884f49d99..e02283d1f17 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -173,7 +173,8 @@ TABLE_FIELD_TYPE proc_table_fields[MYSQL_PROC_FIELD_COUNT] = "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES'," "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES'," "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER'," - "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") }, + "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH'," + "'EMPTY_STRING_IS_NULL')") }, { NULL, 0 } }, { @@ -688,7 +689,7 @@ Sp_handler::db_find_routine(THD *thd, // Get additional information modified= table->field[MYSQL_PROC_FIELD_MODIFIED]->val_int(); created= table->field[MYSQL_PROC_FIELD_CREATED]->val_int(); - sql_mode= (ulong) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(); + sql_mode= (sql_mode_t) table->field[MYSQL_PROC_FIELD_SQL_MODE]->val_int(); creation_ctx= Stored_routine_creation_ctx::load_from_db(thd, name, table); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0bc269c414c..df9471880d9 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -70,8 +70,12 @@ static void reset_start_time_for_sp(THD *thd) Item::Type -sp_map_item_type(enum enum_field_types type) +sp_map_item_type(const Type_handler *handler) { + if (handler == &type_handler_row) + return Item::ROW_ITEM; + enum_field_types type= real_type_to_type(handler->real_field_type()); + switch (type) { case MYSQL_TYPE_BIT: case MYSQL_TYPE_TINY: @@ -994,7 +998,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) sp_rcontext *ctx= thd->spcont; bool err_status= FALSE; uint ip= 0; - ulonglong save_sql_mode; + sql_mode_t save_sql_mode; bool save_abort_on_warning; Query_arena *old_arena; /* per-instruction arena */ @@ -1444,7 +1448,7 @@ sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value, bool switch_security_ctx) { if (!(m_flags & HAS_COLUMN_TYPE_REFS)) - return sp_rcontext::create(thd, m_pcont, ret_value, *defs); + return sp_rcontext::create(thd, this, m_pcont, ret_value, *defs); sp_rcontext *res= NULL; #ifndef NO_EMBEDDED_ACCESS_CHECKS Security_context *save_security_ctx; @@ -1453,7 +1457,7 @@ sp_rcontext *sp_head::rcontext_create(THD *thd, Field *ret_value, return NULL; #endif if (!defs->resolve_type_refs(thd)) - res= sp_rcontext::create(thd, m_pcont, ret_value, *defs); + res= sp_rcontext::create(thd, this, m_pcont, ret_value, *defs); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (switch_security_ctx) m_security_ctx.restore_security_context(thd, save_security_ctx); @@ -1590,9 +1594,6 @@ sp_head::execute_trigger(THD *thd, goto err_with_cleanup; } - /* Needed by slow log */ - nctx->sp= this; - thd->spcont= nctx; err_status= execute(thd, FALSE); @@ -1713,9 +1714,6 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, */ thd->restore_active_arena(&call_arena, &backup_arena); - /* Needed by slow log */ - nctx->sp= this; - /* Pass arguments. */ for (arg_no= 0; arg_no < argcount; arg_no++) { @@ -1918,7 +1916,6 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) DBUG_RETURN(TRUE); } - octx->sp= 0; thd->spcont= octx; /* set callers_arena to thd, for upper-level function to work */ @@ -1931,7 +1928,6 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) thd->spcont= save_spcont; DBUG_RETURN(TRUE); } - nctx->sp= this; if (params > 0) { @@ -2566,10 +2562,18 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) *full_access= ((!check_table_access(thd, SELECT_ACL, &tables, FALSE, 1, TRUE) && (tables.grant.privilege & SELECT_ACL) != 0) || + /* Check if user owns the routine. */ (!strcmp(sp->m_definer.user.str, thd->security_ctx->priv_user) && !strcmp(sp->m_definer.host.str, - thd->security_ctx->priv_host))); + thd->security_ctx->priv_host)) || + /* Check if current role or any of the sub-granted roles + own the routine. */ + (sp->m_definer.host.length == 0 && + (!strcmp(sp->m_definer.user.str, + thd->security_ctx->priv_role) || + check_role_is_granted(thd->security_ctx->priv_role, NULL, + sp->m_definer.user.str)))); if (!*full_access) return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str, sp->m_handler); @@ -4812,11 +4816,11 @@ bool sp_head::spvar_fill_row(THD *thd, sp_variable *spvar, Row_definition_list *defs) { + spvar->field_def.set_row_field_definitions(defs); spvar->field_def.field_name= spvar->name; if (fill_spvar_definition(thd, &spvar->field_def)) return true; row_fill_field_definitions(thd, defs); - spvar->field_def.set_row_field_definitions(defs); return false; } diff --git a/sql/sp_head.h b/sql/sp_head.h index c3ace46a789..734c0dea3e3 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -40,7 +40,7 @@ */ Item::Type -sp_map_item_type(enum enum_field_types type); +sp_map_item_type(const Type_handler *handler); uint sp_get_flags_for_command(LEX *lex); diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 9c879099410..990ad35cb57 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -60,8 +60,6 @@ public: Spvar_definition field_def; /// Field-type of the SP-variable. - enum_field_types sql_type() const { return field_def.real_field_type(); } - const Type_handler *type_handler() const { return field_def.type_handler(); } public: diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 70ab5a576b3..6716aa54170 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -35,10 +35,12 @@ /////////////////////////////////////////////////////////////////////////// -sp_rcontext::sp_rcontext(const sp_pcontext *root_parsing_ctx, +sp_rcontext::sp_rcontext(const sp_head *owner, + const sp_pcontext *root_parsing_ctx, Field *return_value_fld, bool in_sub_stmt) :end_partial_result_set(false), + m_sp(owner), m_root_parsing_ctx(root_parsing_ctx), m_var_table(NULL), m_return_value_fld(return_value_fld), @@ -59,11 +61,13 @@ sp_rcontext::~sp_rcontext() sp_rcontext *sp_rcontext::create(THD *thd, + const sp_head *owner, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, Row_definition_list &field_def_lst) { - sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(root_parsing_ctx, + sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(owner, + root_parsing_ctx, return_value_fld, thd->in_sub_stmt); if (!ctx) @@ -352,10 +356,13 @@ bool sp_rcontext::init_var_items(THD *thd, } -bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list) +bool Item_field_row::row_create_items(THD *thd, List<Spvar_definition> *list) { DBUG_ASSERT(list); - if (!(m_table= create_virtual_tmp_table(thd, *list))) + DBUG_ASSERT(field); + Virtual_tmp_table **ptable= field->virtual_tmp_table_addr(); + DBUG_ASSERT(ptable); + if (!(ptable[0]= create_virtual_tmp_table(thd, *list))) return true; if (alloc_arguments(thd, list->elements)) @@ -366,23 +373,19 @@ bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list) for (arg_count= 0; (def= it++); arg_count++) { if (!(args[arg_count]= new (thd->mem_root) - Item_field(thd, m_table->field[arg_count]))) + Item_field(thd, ptable[0]->field[arg_count]))) return true; } return false; } -Field *Item_spvar_args::get_row_field(uint i) const +Field *Item_field_row::get_row_field(uint i) const { - DBUG_ASSERT(m_table); - return m_table->field[i]; -} - - -Item_spvar_args::~Item_spvar_args() -{ - delete m_table; + DBUG_ASSERT(field); + Virtual_tmp_table **ptable= field->virtual_tmp_table_addr(); + DBUG_ASSERT(ptable); + return ptable[0]->field[i]; } @@ -685,13 +688,13 @@ int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx, int sp_rcontext::set_variable_row(THD *thd, uint var_idx, List<Item> &items) { DBUG_ENTER("sp_rcontext::set_variable_row"); - DBUG_ASSERT(thd->spcont->get_item(var_idx)->cols() == items.elements); + DBUG_ASSERT(get_item(var_idx)->cols() == items.elements); List_iterator<Item> it(items); Item *item; for (uint i= 0 ; (item= it++) ; i++) { int rc; - if ((rc= thd->spcont->set_variable_row_field(thd, var_idx, i, &item))) + if ((rc= set_variable_row_field(thd, var_idx, i, &item))) DBUG_RETURN(rc); } DBUG_RETURN(0); diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 66df0359d28..658972ece40 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -70,6 +70,7 @@ public: /// /// @return valid sp_rcontext object or NULL in case of OOM-error. static sp_rcontext *create(THD *thd, + const sp_head *owner, const sp_pcontext *root_parsing_ctx, Field *return_value_fld, Row_definition_list &defs); @@ -77,7 +78,8 @@ public: ~sp_rcontext(); private: - sp_rcontext(const sp_pcontext *root_parsing_ctx, + sp_rcontext(const sp_head *owner, + const sp_pcontext *root_parsing_ctx, Field *return_value_fld, bool in_sub_stmt); @@ -179,7 +181,8 @@ public: /// The stored program for which this runtime context is created. Used for /// checking if correct runtime context is used for variable handling. - sp_head *sp; + /// Also used by slow log. + const sp_head *m_sp; ///////////////////////////////////////////////////////////////////////// // SP-variables. diff --git a/sql/spatial.cc b/sql/spatial.cc index 8d595541eef..19035a4e882 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -2565,7 +2565,7 @@ uint Gis_multi_polygon::init_from_opresult(String *bin, n_poly++; } bin->write_at_position(np_pos, n_poly); - return opres - opres_orig; + return (uint)(opres - opres_orig); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ae7dc336720..7e31d448bdf 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -9238,6 +9238,16 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc) mysql_mutex_unlock(&acl_cache->lock); } +static int check_role_is_granted_callback(ACL_USER_BASE *grantee, void *data) +{ + LEX_CSTRING *rolename= static_cast<LEX_CSTRING *>(data); + if (rolename->length == grantee->user.length && + !strcmp(rolename->str, grantee->user.str)) + return -1; // End search, we've found our role. + + /* Keep looking, we haven't found our role yet. */ + return 0; +} /* Modify a privilege table. @@ -11258,7 +11268,6 @@ bool check_grant(THD *, ulong, TABLE_LIST *, bool, uint, bool) } #endif /*NO_EMBEDDED_ACCESS_CHECKS */ - SHOW_VAR acl_statistics[] = { #ifndef NO_EMBEDDED_ACCESS_CHECKS {"column_grants", (char*)show_column_grants, SHOW_SIMPLE_FUNC}, @@ -11274,6 +11283,43 @@ SHOW_VAR acl_statistics[] = { {NullS, NullS, SHOW_LONG}, }; +/* Check if a role is granted to a user/role. We traverse the role graph + and return true if we find a match. + + hostname == NULL means we are looking for a role as a starting point, + otherwise a user. +*/ +bool check_role_is_granted(const char *username, + const char *hostname, + const char *rolename) +{ + DBUG_ENTER("check_role_is_granted"); + bool result= false; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + ACL_USER_BASE *root; + mysql_mutex_lock(&acl_cache->lock); + if (hostname) + root= find_user_exact(username, hostname); + else + root= find_acl_role(username); + + LEX_CSTRING role_lex; + role_lex.str= rolename; + role_lex.length= strlen(rolename); + + if (root && /* No grantee, nothing to search. */ + traverse_role_graph_down(root, &role_lex, check_role_is_granted_callback, + NULL) == -1) + { + /* We have found the role during our search. */ + result= true; + } + + /* We haven't found the role or we had no initial grantee to start from. */ + mysql_mutex_unlock(&acl_cache->lock); +#endif + DBUG_RETURN(result); +} int fill_schema_enabled_roles(THD *thd, TABLE_LIST *tables, COND *cond) { @@ -12402,7 +12448,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) char *end= user + packet_length; /* Safe because there is always a trailing \0 at the end of the packet */ char *passwd= strend(user) + 1; - uint user_len= passwd - user - 1; + uint user_len= (uint)(passwd - user - 1); char *db= passwd; char db_buff[SAFE_NAME_LEN + 1]; // buffer to store db in utf8 char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 @@ -13662,4 +13708,3 @@ maria_declare_plugin(mysql_password) MariaDB_PLUGIN_MATURITY_STABLE /* Maturity */ } maria_declare_plugin_end; - diff --git a/sql/sql_acl.h b/sql/sql_acl.h index dacddd603dd..e3dba20422d 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -408,6 +408,14 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, extern SHOW_VAR acl_statistics[]; +/* Check if a role is granted to a user/role. + + If hostname == NULL, search for a role as the starting grantee. +*/ +bool check_role_is_granted(const char *username, + const char *hostname, + const char *rolename); + #ifndef DBUG_OFF extern ulong role_global_merges, role_db_merges, role_table_merges, role_column_merges, role_routine_merges; diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index c81ca438bcc..4ed8234aa64 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -67,7 +67,6 @@ static bool admin_recreate_table(THD *thd, TABLE_LIST *table_list) if (thd->get_stmt_da()->is_ok()) thd->get_stmt_da()->reset_diagnostics_area(); table_list->table= NULL; - result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK; DBUG_RETURN(result_code); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e59007d3e5a..7fd6599df51 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3046,6 +3046,46 @@ thr_lock_type read_lock_type_for_table(THD *thd, /* + Extend the prelocking set with tables and routines used by a routine. + + @param[in] thd Thread context. + @param[in] rt Element of prelocking set to be processed. + @param[in] ot_ctx Context of open_table used to recover from + locking failures. + @retval false Success. + @retval true Failure (Conflicting metadata lock, OOM, other errors). +*/ +static bool +sp_acquire_mdl(THD *thd, Sroutine_hash_entry *rt, Open_table_context *ot_ctx) +{ + DBUG_ENTER("sp_acquire_mdl"); + /* + Since we acquire only shared lock on routines we don't + need to care about global intention exclusive locks. + */ + DBUG_ASSERT(rt->mdl_request.type == MDL_SHARED); + + /* + Waiting for a conflicting metadata lock to go away may + lead to a deadlock, detected by MDL subsystem. + If possible, we try to resolve such deadlocks by releasing all + metadata locks and restarting the pre-locking process. + To prevent the error from polluting the diagnostics area + in case of successful resolution, install a special error + handler for ER_LOCK_DEADLOCK error. + */ + MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); + + thd->push_internal_handler(&mdl_deadlock_handler); + bool result= thd->mdl_context.acquire_lock(&rt->mdl_request, + ot_ctx->get_timeout()); + thd->pop_internal_handler(); + + DBUG_RETURN(result); +} + + +/* Handle element of prelocking set other than table. E.g. cache routine and, if prelocking strategy prescribes so, extend the prelocking set with tables and routines used by it. @@ -3099,29 +3139,7 @@ open_and_process_routine(THD *thd, Query_tables_list *prelocking_ctx, if (rt != (Sroutine_hash_entry*)prelocking_ctx->sroutines_list.first || mdl_type != MDL_key::PROCEDURE) { - /* - Since we acquire only shared lock on routines we don't - need to care about global intention exclusive locks. - */ - DBUG_ASSERT(rt->mdl_request.type == MDL_SHARED); - - /* - Waiting for a conflicting metadata lock to go away may - lead to a deadlock, detected by MDL subsystem. - If possible, we try to resolve such deadlocks by releasing all - metadata locks and restarting the pre-locking process. - To prevent the error from polluting the diagnostics area - in case of successful resolution, install a special error - handler for ER_LOCK_DEADLOCK error. - */ - MDL_deadlock_handler mdl_deadlock_handler(ot_ctx); - - thd->push_internal_handler(&mdl_deadlock_handler); - bool result= thd->mdl_context.acquire_lock(&rt->mdl_request, - ot_ctx->get_timeout()); - thd->pop_internal_handler(); - - if (result) + if (sp_acquire_mdl(thd, rt, ot_ctx)) DBUG_RETURN(TRUE); DEBUG_SYNC(thd, "after_shared_lock_pname"); @@ -3320,9 +3338,14 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, /* If this TABLE_LIST object has an associated open TABLE object (TABLE_LIST::table is not NULL), that TABLE object must be a pre-opened - temporary table. + temporary table or SEQUENCE (see sequence_insert()). */ - DBUG_ASSERT(is_temporary_table(tables)); + DBUG_ASSERT(is_temporary_table(tables) || tables->table->s->sequence); + if (tables->sequence && tables->table->s->table_type != TABLE_TYPE_SEQUENCE) + { + my_error(ER_NOT_SEQUENCE, MYF(0), tables->db, tables->alias); + DBUG_RETURN(true); + } } else if (tables->open_type == OT_TEMPORARY_ONLY) { @@ -5479,7 +5502,7 @@ find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, if (field_ptr && *field_ptr) { - *cached_field_index_ptr= field_ptr - table->field; + *cached_field_index_ptr= (uint)(field_ptr - table->field); field= *field_ptr; } else @@ -7038,13 +7061,15 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &fields, enum_mark_columns mark_used_columns, - List<Item> *sum_func_list, bool allow_sum_func) + List<Item> *sum_func_list, List<Item> *pre_fix, + bool allow_sum_func) { reg2 Item *item; enum_mark_columns save_mark_used_columns= thd->mark_used_columns; nesting_map save_allow_sum_func= thd->lex->allow_sum_func; List_iterator<Item> it(fields); bool save_is_item_list_lookup; + bool make_pre_fix= (pre_fix && (pre_fix->elements == 0)); DBUG_ENTER("setup_fields"); DBUG_PRINT("enter", ("ref_pointer_array: %p", ref_pointer_array.array())); @@ -7094,6 +7119,9 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, thd->lex->current_select->cur_pos_in_select_list= 0; while ((item= it++)) { + if (make_pre_fix) + pre_fix->push_back(item, thd->stmt_arena->mem_root); + if ((!item->fixed && item->fix_fields(thd, it.ref())) || (item= *(it.ref()))->check_cols(1)) { diff --git a/sql/sql_base.h b/sql/sql_base.h index 7a8d27c9147..bb33af66590 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -159,7 +159,8 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, List<Item> *sum_func_list, uint wild_num); bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array, List<Item> &item, enum_mark_columns mark_used_columns, - List<Item> *sum_func_list, bool allow_sum_func); + List<Item> *sum_func_list, List<Item> *pre_fix, + bool allow_sum_func); void unfix_fields(List<Item> &items); bool fill_record(THD * thd, TABLE *table_arg, List<Item> &fields, List<Item> &values, bool ignore_errors, bool update); @@ -366,7 +367,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Ref_ptr_array ref_pointer_array, bool res; thd->lex->select_lex.no_wrap_view_item= TRUE; res= setup_fields(thd, ref_pointer_array, item, mark_used_columns, - sum_func_list, allow_sum_func); + sum_func_list, NULL, allow_sum_func); thd->lex->select_lex.no_wrap_view_item= FALSE; return res; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index e09b1788441..2dc977c9b5d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -4280,7 +4280,7 @@ my_bool Query_cache::move_by_type(uchar **border, *pprev = block->pprev, *pnext = block->pnext, *new_block =(Query_cache_block *) *border; - uint tablename_offset = block->table()->table() - block->table()->db(); + size_t tablename_offset = block->table()->table() - block->table()->db(); char *data = (char*) block->data(); uchar *key; size_t key_length; @@ -4589,7 +4589,7 @@ uint Query_cache::filename_2_table_key (char *key, const char *path, filename= tablename + dirname_length(tablename + 2) + 2; /* Find start of databasename */ for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ; - *db_length= (filename - dbname) - 1; + *db_length= (uint32)(filename - dbname) - 1; DBUG_PRINT("qcache", ("table '%-.*s.%s'", *db_length, dbname, filename)); DBUG_RETURN((uint) (strmake(strmake(key, dbname, diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 5c8a378eacd..889acc57b76 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2406,9 +2406,11 @@ bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs) } -Item_string *THD::make_string_literal(const char *str, size_t length, - uint repertoire) +Item *THD::make_string_literal(const char *str, size_t length, + uint repertoire) { + if (!length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL)) + return new (mem_root) Item_null(this, 0, variables.collation_connection); if (!charset_is_collation_connection && (repertoire != MY_REPERTOIRE_ASCII || !my_charset_is_ascii_based(variables.collation_connection))) @@ -2426,6 +2428,57 @@ Item_string *THD::make_string_literal(const char *str, size_t length, } +Item *THD::make_string_literal_nchar(const Lex_string_with_metadata_st &str) +{ + DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info)); + if (!str.length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL)) + return new (mem_root) Item_null(this, 0, national_charset_info); + + return new (mem_root) Item_string(this, str.str, str.length, + national_charset_info, + DERIVATION_COERCIBLE, + str.repertoire()); +} + + +Item *THD::make_string_literal_charset(const Lex_string_with_metadata_st &str, + CHARSET_INFO *cs) +{ + if (!str.length && (variables.sql_mode & MODE_EMPTY_STRING_IS_NULL)) + return new (mem_root) Item_null(this, 0, cs); + return new (mem_root) Item_string_with_introducer(this, + str.str, str.length, cs); +} + + +Item *THD::make_string_literal_concat(Item *item, const LEX_CSTRING &str) +{ + if (item->type() == Item::NULL_ITEM) + { + DBUG_ASSERT(variables.sql_mode & MODE_EMPTY_STRING_IS_NULL); + if (str.length) + { + CHARSET_INFO *cs= variables.collation_connection; + uint repertoire= my_string_repertoire(cs, str.str, str.length); + return new (mem_root) Item_string(this, str.str, str.length, cs, + DERIVATION_COERCIBLE, repertoire); + } + return item; + } + + DBUG_ASSERT(item->type() == Item::STRING_ITEM); + DBUG_ASSERT(item->basic_const_item()); + static_cast<Item_string*>(item)->append(str.str, str.length); + if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED)) + { + // If the string has been pure ASCII so far, check the new part. + CHARSET_INFO *cs= variables.collation_connection; + item->collation.repertoire|= my_string_repertoire(cs, str.str, str.length); + } + return item; +} + + /* Update some cache variables when character set changes */ diff --git a/sql/sql_class.h b/sql/sql_class.h index bc72fc25a18..fda56c8cc3a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -139,6 +139,7 @@ enum enum_binlog_row_image { #define MODE_HIGH_NOT_PRECEDENCE (1ULL << 29) #define MODE_NO_ENGINE_SUBSTITUTION (1ULL << 30) #define MODE_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) +#define MODE_EMPTY_STRING_IS_NULL (1ULL << 32) /* Bits for different old style modes */ #define OLD_MODE_NO_DUP_KEY_WARNINGS_WITH_IGNORE (1 << 0) @@ -3548,14 +3549,17 @@ public: @param length - length of the string @param repertoire - the repertoire of the string */ - Item_string *make_string_literal(const char *str, size_t length, - uint repertoire); - Item_string *make_string_literal(const Lex_string_with_metadata_st &str) + Item *make_string_literal(const char *str, size_t length, + uint repertoire); + Item *make_string_literal(const Lex_string_with_metadata_st &str) { uint repertoire= str.repertoire(variables.character_set_client); return make_string_literal(str.str, str.length, repertoire); } - + Item *make_string_literal_nchar(const Lex_string_with_metadata_st &str); + Item *make_string_literal_charset(const Lex_string_with_metadata_st &str, + CHARSET_INFO *cs); + Item *make_string_literal_concat(Item *item1, const LEX_CSTRING &str); void add_changed_table(TABLE *table); void add_changed_table(const char *key, long key_length); CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length); diff --git a/sql/sql_const.h b/sql/sql_const.h index 8d5f56de6b0..a5756aa1f39 100644 --- a/sql/sql_const.h +++ b/sql/sql_const.h @@ -45,7 +45,18 @@ #define MAX_MBWIDTH 3 /* Max multibyte sequence */ #define MAX_FILENAME_MBWIDTH 5 #define MAX_FIELD_CHARLENGTH 255 -#define MAX_FIELD_VARCHARLENGTH 65535 +/* + In MAX_FIELD_VARCHARLENGTH we reserve extra bytes for the overhead: + - 2 bytes for the length + - 1 byte for NULL bits + to avoid the "Row size too large" error for these three corner definitions: + CREATE TABLE t1 (c VARBINARY(65533)); + CREATE TABLE t1 (c VARBINARY(65534)); + CREATE TABLE t1 (c VARBINARY(65535)); + Like VARCHAR(65536), they will be converted to BLOB automatically + in non-sctict mode. +*/ +#define MAX_FIELD_VARCHARLENGTH (65535-2-1) #define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */ #define CONVERT_IF_BIGGER_TO_BLOB 512 /* Threshold *in characters* */ diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index 2047c7c8762..ad37ef36e2c 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1007,7 +1007,7 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) been done yet. */ if (with_elem && sl->master_unit() == with_elem->spec) - break; + break; With_clause *with_clause=sl->get_with_clause(); if (with_clause) { @@ -1055,13 +1055,21 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem) } with= with_elem; if (!with_elem->is_referenced() || with_elem->is_recursive) + { derived= with_elem->spec; + if (derived->get_master() != select_lex && + !is_with_table_recursive_reference()) + { + derived->move_as_slave(select_lex); + } + } else { if(!(derived= with_elem->clone_parsed_spec(thd, this))) return true; derived->with_element= with_elem; } + derived->first_select()->linkage= DERIVED_TABLE_TYPE; with_elem->inc_references(); return false; } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 4db216a3a41..d41e9acfdc8 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1006,7 +1006,7 @@ update_binlog: These DDL methods and logging are protected with the exclusive metadata lock on the schema. */ - if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len)) + if (write_to_binlog(thd, query, (uint)(query_pos -1 - query), db, db_len)) { error= true; goto exit; @@ -1024,7 +1024,7 @@ update_binlog: These DDL methods and logging are protected with the exclusive metadata lock on the schema. */ - if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len)) + if (write_to_binlog(thd, query, (uint)(query_pos -1 - query), db, db_len)) { error= true; goto exit; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 32ff44d9343..c880374f9ab 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -821,7 +821,7 @@ l DBUG_RETURN(TRUE); if ((wild_num && setup_wild(thd, table_list, field_list, NULL, wild_num)) || setup_fields(thd, Ref_ptr_array(), - field_list, MARK_COLUMNS_READ, NULL, 0) || + field_list, MARK_COLUMNS_READ, NULL, NULL, 0) || setup_conds(thd, table_list, select_lex->leaf_tables, conds) || setup_ftfuncs(select_lex)) DBUG_RETURN(TRUE); diff --git a/sql/sql_do.cc b/sql/sql_do.cc index a25bdef3d9d..f556dc282ed 100644 --- a/sql/sql_do.cc +++ b/sql/sql_do.cc @@ -29,7 +29,7 @@ bool mysql_do(THD *thd, List<Item> &values) List_iterator<Item> li(values); Item *value; DBUG_ENTER("mysql_do"); - if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_NONE, 0, NULL, 0)) DBUG_RETURN(TRUE); while ((value = li++)) (void) value->is_null(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index e592a873ef0..b12b470209c 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -268,7 +268,8 @@ static int check_insert_fields(THD *thd, TABLE_LIST *table_list, if (table_list->is_view()) unfix_fields(fields); - res= setup_fields(thd, Ref_ptr_array(), fields, MARK_COLUMNS_WRITE, 0, 0); + res= setup_fields(thd, Ref_ptr_array(), + fields, MARK_COLUMNS_WRITE, 0, NULL, 0); /* Restore the current context. */ ctx_state.restore_state(context, table_list); @@ -380,7 +381,7 @@ static int check_update_fields(THD *thd, TABLE_LIST *insert_table_list, /* Check the fields we are going to modify */ if (setup_fields(thd, Ref_ptr_array(), - update_fields, MARK_COLUMNS_WRITE, 0, 0)) + update_fields, MARK_COLUMNS_WRITE, 0, NULL, 0)) return -1; if (insert_table_list->is_view() && @@ -806,7 +807,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto abort; } - if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_READ, 0, NULL, 0)) goto abort; switch_to_nullable_trigger_fields(*values, table); } @@ -1531,13 +1533,13 @@ bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, context->resolve_in_table_list_only(table_list); res= (setup_fields(thd, Ref_ptr_array(), - *values, MARK_COLUMNS_READ, 0, 0) || + *values, MARK_COLUMNS_READ, 0, NULL, 0) || check_insert_fields(thd, context->table_list, fields, *values, !insert_into_view, 0, &map)); if (!res) res= setup_fields(thd, Ref_ptr_array(), - update_values, MARK_COLUMNS_READ, 0, 0); + update_values, MARK_COLUMNS_READ, 0, NULL, 0); if (!res && duplic == DUP_UPDATE) { @@ -3527,7 +3529,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) */ lex->current_select= &lex->select_lex; - res= (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0) || + res= (setup_fields(thd, Ref_ptr_array(), + values, MARK_COLUMNS_READ, 0, NULL, 0) || check_insert_fields(thd, table_list, *fields, values, !insert_into_view, 1, &map)); @@ -3580,7 +3583,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) ctx_state.get_first_name_resolution_table(); res= res || setup_fields(thd, Ref_ptr_array(), *info.update_values, - MARK_COLUMNS_READ, 0, 0); + MARK_COLUMNS_READ, 0, NULL, 0); if (!res) { /* diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 9a7b8f2af21..2f1a81cc2ec 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -407,7 +407,7 @@ void JOIN_CACHE::create_flag_fields() } /* Theoretically the new value of flag_fields can be less than the old one */ - flag_fields= copy-field_descr; + flag_fields= (uint)(copy-field_descr); } @@ -1375,7 +1375,7 @@ uint JOIN_CACHE::write_record_data(uchar * link, bool *is_full) } /* Save the offset of the field to put it later at the end of the record */ if (copy->referenced_field_no) - copy->offset= cp-curr_rec_pos; + copy->offset= (uint)(cp-curr_rec_pos); switch (copy->type) { case CACHE_BLOB: @@ -1779,7 +1779,7 @@ uint JOIN_CACHE::read_flag_fields() memcpy(copy->str, pos, copy->length); pos+= copy->length; } - return (pos-init_pos); + return (uint)(pos-init_pos); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b8d51a5783f..ce43a45b872 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2386,6 +2386,30 @@ st_select_lex_node *st_select_lex_node:: insert_chain_before( return this; } + +/* + Detach the node from its master and attach it to a new master +*/ + +void st_select_lex_node::move_as_slave(st_select_lex_node *new_master) +{ + exclude_from_tree(); + if (new_master->slave) + { + st_select_lex_node *curr= new_master->slave; + for ( ; curr->next ; curr= curr->next) ; + prev= &curr->next; + } + else + { + prev= &new_master->slave; + new_master->slave= this; + } + next= 0; + master= new_master; +} + + /* Exclude a node from the tree lex structure, but leave it in the global list of nodes. @@ -4495,7 +4519,8 @@ void st_select_lex::set_explain_type(bool on_the_fly) pos_in_table_list=NULL for e.g. post-join aggregation JOIN_TABs. */ if (tab->table && tab->table->pos_in_table_list && - tab->table->pos_in_table_list->with) + tab->table->pos_in_table_list->with && + tab->table->pos_in_table_list->with->is_recursive) { uses_cte= true; break; @@ -5208,15 +5233,73 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars) thd->variables.collation_database); } + +bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars, + Item *dflt_value_item) +{ + if (!dflt_value_item && + !(dflt_value_item= new (thd->mem_root) Item_null(thd))) + return true; + + for (uint i= 0 ; i < (uint) nvars ; i++) + { + sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); + bool last= i + 1 == (uint) nvars; + spvar->default_value= dflt_value_item; + /* The last instruction is responsible for freeing LEX. */ + sp_instr_set *is= new (this->thd->mem_root) + sp_instr_set(sphead->instructions(), + spcont, spvar->offset, dflt_value_item, + this, last); + if (is == NULL || sphead->add_instr(is)) + return true; + } + return false; +} + + +bool +LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars, + const Column_definition &ref, + Row_definition_list *fields, + Item *default_value) +{ + for (uint i= 0 ; i < (uint) nvars; i++) + { + sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); + spvar->field_def.set_type(ref); + if (fields) + { + DBUG_ASSERT(ref.type_handler() == &type_handler_row); + spvar->field_def.set_row_field_definitions(fields); + } + spvar->field_def.field_name= spvar->name; + } + if (sp_variable_declarations_set_default(thd, nvars, default_value)) + return true; + spcont->declare_var_boundary(0); + return sphead->restore_lex(thd); +} + + bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars, const Column_definition *cdef, - Row_definition_list *row, Item *dflt_value_item) { - if (!dflt_value_item && - !(dflt_value_item= new (thd->mem_root) Item_null(thd))) + DBUG_ASSERT(cdef); + Column_definition tmp(*cdef); + if (sphead->fill_spvar_definition(thd, &tmp)) return true; + return sp_variable_declarations_copy_type_finalize(thd, nvars, tmp, NULL, + dflt_value_item); +} + +bool LEX::sp_variable_declarations_row_finalize(THD *thd, int nvars, + Row_definition_list *row, + Item *dflt_value_item) +{ + DBUG_ASSERT(row); /* Prepare all row fields. Note, we do it only one time outside of the below loop. @@ -5229,37 +5312,19 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars, ... END; */ - if (row && sphead->row_fill_field_definitions(thd, row)) + if (sphead->row_fill_field_definitions(thd, row)) return true; for (uint i= 0 ; i < (uint) nvars ; i++) { sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); - bool last= i + 1 == (uint) nvars; - - if (!spvar) - return true; - - spvar->default_value= dflt_value_item; - - if (cdef) - { - if (!last) - spvar->field_def.set_column_definition(cdef); - } - if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name)) - return true; spvar->field_def.set_row_field_definitions(row); - - /* The last instruction is responsible for freeing LEX. */ - sp_instr_set *is= new (this->thd->mem_root) - sp_instr_set(sphead->instructions(), - spcont, spvar->offset, dflt_value_item, - this, last); - if (is == NULL || sphead->add_instr(is)) + if (sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name)) return true; } + if (sp_variable_declarations_set_default(thd, nvars, dflt_value_item)) + return true; spcont->declare_var_boundary(0); return sphead->restore_lex(thd); } @@ -5283,57 +5348,76 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars, const sp_pcursor *pcursor= ref->table.str && ref->db.str ? NULL : spcont->find_cursor(&ref->m_column, &coffp, false); + if (pcursor) + return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars, + coffp, def); + /* + When parsing a qualified identifier chain, the parser does not know yet + if it's going to be a qualified column name (for %TYPE), + or a qualified table name (for %ROWTYPE). So it collects the chain + into Qualified_column_ident. + Now we know that it was actually a qualified table name (%ROWTYPE). + Create a new Table_ident from Qualified_column_ident, + shifting fields as follows: + - ref->m_column becomes table_ref->table + - ref->table becomes table_ref->db + */ + return sp_variable_declarations_table_rowtype_finalize(thd, nvars, + ref->table, + ref->m_column, + def); +} + - if (!def && !(def= new (thd->mem_root) Item_null(thd))) +bool +LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars, + const LEX_CSTRING &db, + const LEX_CSTRING &table, + Item *def) +{ + Table_ident *table_ref; + if (!(table_ref= new (thd->mem_root) Table_ident(thd, &db, &table, false))) + return true; + // Loop through all variables in the same declaration + for (uint i= 0 ; i < (uint) nvars; i++) + { + sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); + spvar->field_def.set_table_rowtype_ref(table_ref); + sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name); + } + if (sp_variable_declarations_set_default(thd, nvars, def)) return true; + // Make sure sp_rcontext is created using the invoker security context: + sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS; + spcont->declare_var_boundary(0); + return sphead->restore_lex(thd); +} + + +bool +LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars, + uint offset, + Item *def) +{ + const sp_pcursor *pcursor= spcont->find_cursor(offset); // Loop through all variables in the same declaration for (uint i= 0 ; i < (uint) nvars; i++) { - bool last= i + 1 == (uint) nvars; sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); - if (pcursor) - { - spvar->field_def.set_cursor_rowtype_ref(true); - sp_instr_cursor_copy_struct *instr= - new (thd->mem_root) sp_instr_cursor_copy_struct(sphead->instructions(), - spcont, pcursor->lex(), - spvar->offset); - if (instr == NULL || sphead->add_instr(instr)) - return true; - } - else - { - /* - When parsing a qualified identifier chain, the parser does not know yet - if it's going to be a qualified column name (for %TYPE), - or a qualified table name (for %ROWTYPE). So it collects the chain - into Qualified_column_ident. - Now we know that it was actually a qualified table name (%ROWTYPE). - Create a new Table_ident from Qualified_column_ident, - shifting fields as follows: - - ref->m_column becomes table_ref->table - - ref->table becomes table_ref->db - */ - Table_ident *table_ref; - if (!(table_ref= new (thd->mem_root) Table_ident(thd, - &ref->table, - &ref->m_column, - false))) - return true; - spvar->field_def.set_table_rowtype_ref(table_ref); - } + 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(), + spvar->offset); + if (instr == NULL || sphead->add_instr(instr)) + return true; + sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name); - spvar->default_value= def; - /* The last instruction is responsible for freeing LEX. */ - sp_instr_set *is= new (this->thd->mem_root) - sp_instr_set(sphead->instructions(), - spcont, spvar->offset, def, - this, last); - if (is == NULL || sphead->add_instr(is)) - return true; } + if (sp_variable_declarations_set_default(thd, nvars, def)) + return true; // Make sure sp_rcontext is created using the invoker security context: sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS; spcont->declare_var_boundary(0); @@ -5341,11 +5425,28 @@ LEX::sp_variable_declarations_rowtype_finalize(THD *thd, int nvars, } +/* + Add declarations for table column and SP variable anchor types: + - DECLARE spvar1 TYPE OF db1.table1.column1; + - DECLARE spvar1 TYPE OF table1.column1; + - DECLARE spvar1 TYPE OF spvar0; +*/ bool LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars, Qualified_column_ident *ref, Item *def) { + return ref->db.length == 0 && ref->table.length == 0 ? + sp_variable_declarations_vartype_finalize(thd, nvars, ref->m_column, def) : + sp_variable_declarations_column_type_finalize(thd, nvars, ref, def); +} + + +bool +LEX::sp_variable_declarations_column_type_finalize(THD *thd, int nvars, + Qualified_column_ident *ref, + Item *def) +{ for (uint i= 0 ; i < (uint) nvars; i++) { sp_variable *spvar= spcont->get_last_context_variable((uint) nvars - 1 - i); @@ -5353,7 +5454,55 @@ LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars, spvar->field_def.field_name= spvar->name; } sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS; - return sp_variable_declarations_finalize(thd, nvars, NULL, NULL, def); + if (sp_variable_declarations_set_default(thd, nvars, def)) + return true; + spcont->declare_var_boundary(0); + return sphead->restore_lex(thd); +} + + +bool +LEX::sp_variable_declarations_vartype_finalize(THD *thd, int nvars, + const LEX_CSTRING &ref, + Item *default_value) +{ + sp_variable *t; + if (!spcont || !(t= spcont->find_variable(&ref, false))) + { + my_error(ER_SP_UNDECLARED_VAR, MYF(0), ref.str); + return true; + } + + if (t->field_def.is_cursor_rowtype_ref()) + { + uint offset= t->field_def.cursor_rowtype_offset(); + return sp_variable_declarations_cursor_rowtype_finalize(thd, nvars, + offset, + default_value); + } + + if (t->field_def.is_column_type_ref()) + { + Qualified_column_ident *tmp= t->field_def.column_type_ref(); + return sp_variable_declarations_column_type_finalize(thd, nvars, tmp, + default_value); + } + + if (t->field_def.is_table_rowtype_ref()) + { + const Table_ident *tmp= t->field_def.table_rowtype_ref(); + return sp_variable_declarations_table_rowtype_finalize(thd, nvars, + tmp->db, + tmp->table, + default_value); + } + + // A reference to a scalar or a row variable with an explicit data type + return sp_variable_declarations_copy_type_finalize(thd, nvars, + t->field_def, + t->field_def. + row_field_definitions(), + default_value); } @@ -5421,7 +5570,7 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd, if (!(spvar->default_value= new (thd->mem_root) Item_null(thd))) return NULL; - spvar->field_def.set_cursor_rowtype_ref(true); + spvar->field_def.set_cursor_rowtype_ref(coffset); if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset, param_lex, parameters)) @@ -5445,7 +5594,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop) { sp_variable *src= i == 0 ? loop.m_index : loop.m_upper_bound; args[i]= new (thd->mem_root) - Item_splocal(thd, &src->name, src->offset, src->sql_type()); + Item_splocal(thd, &src->name, src->offset, src->type_handler()); if (args[i] == NULL) return true; #ifdef DBUG_ASSERT_EXISTS @@ -5579,7 +5728,7 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop) { Item_splocal *splocal= new (thd->mem_root) Item_splocal(thd, &loop.m_index->name, loop.m_index->offset, - loop.m_index->sql_type()); + loop.m_index->type_handler()); if (splocal == NULL) return true; #ifdef DBUG_ASSERT_EXISTS @@ -6350,7 +6499,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd, { if (!(item= new (thd->mem_root) Item_splocal_row_field_by_name(thd, a, b, spv->offset, - MYSQL_TYPE_NULL, + &type_handler_null, pos.pos(), pos.length()))) return NULL; } @@ -6364,7 +6513,7 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd, if (!(item= new (thd->mem_root) Item_splocal_row_field(thd, a, b, spv->offset, row_field_offset, - def->real_field_type(), + def->type_handler(), pos.pos(), pos.length()))) return NULL; } @@ -6533,7 +6682,7 @@ Item *LEX::create_item_limit(THD *thd, Query_fragment pos(thd, sphead, start, end); Item_splocal *item; if (!(item= new (thd->mem_root) Item_splocal(thd, a, - spv->offset, spv->sql_type(), + spv->offset, spv->type_handler(), pos.pos(), pos.length()))) return NULL; #ifdef DBUG_ASSERT_EXISTS @@ -6652,11 +6801,8 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name, spv->offset, pos.pos(), pos.length()) : - spv->field_def.is_row() || spv->field_def.is_table_rowtype_ref() ? - new (thd->mem_root) Item_splocal_row(thd, name, spv->offset, - pos.pos(), pos.length()) : new (thd->mem_root) Item_splocal(thd, name, - spv->offset, spv->sql_type(), + spv->offset, spv->type_handler(), pos.pos(), pos.length()); if (splocal == NULL) return NULL; @@ -7186,6 +7332,22 @@ bool LEX::add_grant_command(THD *thd, enum_sql_command sql_command_arg, } +Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b, Item *c) +{ + return (thd->variables.sql_mode & MODE_ORACLE) ? + new (thd->mem_root) Item_func_substr_oracle(thd, a, b, c) : + new (thd->mem_root) Item_func_substr(thd, a, b, c); +} + + +Item *LEX::make_item_func_substr(THD *thd, Item *a, Item *b) +{ + return (thd->variables.sql_mode & MODE_ORACLE) ? + new (thd->mem_root) Item_func_substr_oracle(thd, a, b) : + new (thd->mem_root) Item_func_substr(thd, a, b); +} + + Item *LEX::make_item_func_replace(THD *thd, Item *org, Item *find, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5f1f4a397d4..7619353d922 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -612,6 +612,7 @@ public: } st_select_lex_node *insert_chain_before(st_select_lex_node **ptr_pos_to_insert, st_select_lex_node *end_chain_node); + void move_as_slave(st_select_lex_node *new_master); friend class st_select_lex_unit; friend bool mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *sel); friend bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, @@ -848,6 +849,7 @@ public: Group_list_ptrs *group_list_ptrs; List<Item> item_list; /* list of fields & expressions */ + List<Item> pre_fix; /* above list before fix_fields */ bool is_item_list_lookup; /* Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake @@ -3175,26 +3177,34 @@ public: void sp_variable_declarations_init(THD *thd, int nvars); bool sp_variable_declarations_finalize(THD *thd, int nvars, const Column_definition *cdef, - Row_definition_list *row, Item *def); - bool sp_variable_declarations_finalize(THD *thd, int nvars, - const Column_definition *cdef, - Item *def) - { - return sp_variable_declarations_finalize(thd, nvars, cdef, NULL, def); - } + bool sp_variable_declarations_set_default(THD *thd, int nvars, Item *def); bool sp_variable_declarations_row_finalize(THD *thd, int nvars, Row_definition_list *row, - Item *def) - { - return sp_variable_declarations_finalize(thd, nvars, NULL, row, def); - } + Item *def); bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars, Qualified_column_ident *col, Item *def); bool sp_variable_declarations_rowtype_finalize(THD *thd, int nvars, Qualified_column_ident *, Item *def); + bool sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars, + uint offset, + Item *def); + bool sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars, + const LEX_CSTRING &db, + const LEX_CSTRING &table, + Item *def); + bool sp_variable_declarations_column_type_finalize(THD *thd, int nvars, + Qualified_column_ident *ref, + Item *def); + bool sp_variable_declarations_vartype_finalize(THD *thd, int nvars, + const LEX_CSTRING &name, + Item *def); + bool sp_variable_declarations_copy_type_finalize(THD *thd, int nvars, + const Column_definition &ref, + Row_definition_list *fields, + Item *def); bool sp_handler_declaration_init(THD *thd, int type); bool sp_handler_declaration_finalize(THD *thd, int type); @@ -3336,7 +3346,8 @@ public: const char *end); Item *make_item_func_replace(THD *thd, Item *org, Item *find, Item *replace); - + Item *make_item_func_substr(THD *thd, Item *a, Item *b, Item *c); + Item *make_item_func_substr(THD *thd, Item *a, Item *b); /* Create a my_var instance for a ROW field variable that was used as an OUT SP parameter: CALL p1(var.field); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 6cd0b76c66d..cf676d5f706 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -387,21 +387,23 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, in this case. */ if (setup_fields(thd, Ref_ptr_array(), - set_fields, MARK_COLUMNS_WRITE, 0, 0) || - setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) + set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) || + setup_fields(thd, Ref_ptr_array(), + set_values, MARK_COLUMNS_READ, 0, NULL, 0)) DBUG_RETURN(TRUE); } else { // Part field list /* TODO: use this conds for 'WITH CHECK OPTIONS' */ if (setup_fields(thd, Ref_ptr_array(), - fields_vars, MARK_COLUMNS_WRITE, 0, 0) || + fields_vars, MARK_COLUMNS_WRITE, 0, NULL, 0) || setup_fields(thd, Ref_ptr_array(), - set_fields, MARK_COLUMNS_WRITE, 0, 0) || + set_fields, MARK_COLUMNS_WRITE, 0, NULL, 0) || check_that_all_fields_are_given_values(thd, table, table_list)) DBUG_RETURN(TRUE); /* Fix the expressions in SET clause */ - if (setup_fields(thd, Ref_ptr_array(), set_values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + set_values, MARK_COLUMNS_READ, 0, NULL, 0)) DBUG_RETURN(TRUE); } switch_to_nullable_trigger_fields(fields_vars, table); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0c68615f911..2f886d91780 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1424,8 +1424,7 @@ out: @retval FALSE The statement isn't updating any relevant tables. */ -static my_bool deny_updates_if_read_only_option(THD *thd, - TABLE_LIST *all_tables) +static bool deny_updates_if_read_only_option(THD *thd, TABLE_LIST *all_tables) { DBUG_ENTER("deny_updates_if_read_only_option"); @@ -1447,10 +1446,20 @@ static my_bool deny_updates_if_read_only_option(THD *thd, if (lex->sql_command == SQLCOM_UPDATE_MULTI) DBUG_RETURN(FALSE); - /* a table-to-create is not in the temp table list, needs a special check */ + /* + a table-to-be-created is not in the temp table list yet, + so CREATE TABLE needs a special treatment + */ if (lex->sql_command == SQLCOM_CREATE_TABLE) DBUG_RETURN(!lex->tmp_table()); + /* + a table-to-be-dropped might not exist (DROP TEMPORARY TABLE IF EXISTS), + cannot use the temp table list either. + */ + if (lex->sql_command == SQLCOM_DROP_TABLE && lex->tmp_table()) + DBUG_RETURN(FALSE); + /* Check if we created or dropped databases */ if ((sql_command_flags[lex->sql_command] & CF_DB_CHANGE)) DBUG_RETURN(TRUE); @@ -4065,7 +4074,7 @@ mysql_execute_command(THD *thd) #ifdef WITH_PARTITION_STORAGE_ENGINE { partition_info *part_info= thd->lex->part_info; - if (part_info && !(part_info= thd->lex->part_info->get_clone(thd))) + if (part_info && !(part_info= part_info->get_clone(thd))) { res= -1; goto end_with_restore_list; @@ -4541,7 +4550,7 @@ end_with_restore_list: if (up_result != 2) break; } - /* Fall through */ + /* fall through */ case SQLCOM_UPDATE_MULTI: { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -4653,7 +4662,7 @@ end_with_restore_list: DBUG_PRINT("debug", ("Just after generate_incident()")); } #endif - /* fall through */ + /* fall through */ case SQLCOM_INSERT: { WSREP_SYNC_WAIT(thd, WSREP_SYNC_WAIT_BEFORE_INSERT_REPLACE); @@ -5275,7 +5284,6 @@ end_with_restore_list: if (res) break; - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: { @@ -5309,7 +5317,6 @@ end_with_restore_list: &lex->spname->m_name); break; case SQLCOM_DROP_EVENT: - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); if (!(res= Events::drop_event(thd, &lex->spname->m_db, &lex->spname->m_name, lex->if_exists()))) @@ -5437,11 +5444,10 @@ end_with_restore_list: } if (first_table) { - if (lex->type == TYPE_ENUM_PROCEDURE || - lex->type == TYPE_ENUM_FUNCTION) + const Sp_handler *sph= Sp_handler::handler((stored_procedure_type) + lex->type); + if (sph) { - const Sp_handler *sph= Sp_handler::handler((stored_procedure_type) - lex->type); uint grants= lex->all_privileges ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL) : lex->grant; @@ -6049,7 +6055,6 @@ end_with_restore_list: Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands as specified through the thd->lex->create_view->mode flag. */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); res= mysql_create_view(thd, first_table, thd->lex->create_view->mode); break; } @@ -6065,7 +6070,6 @@ end_with_restore_list: case SQLCOM_CREATE_TRIGGER: { /* Conditionally writes to binlog. */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); res= mysql_create_or_drop_trigger(thd, all_tables, 1); break; @@ -6073,7 +6077,6 @@ end_with_restore_list: case SQLCOM_DROP_TRIGGER: { /* Conditionally writes to binlog. */ - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); res= mysql_create_or_drop_trigger(thd, all_tables, 0); break; } @@ -6138,13 +6141,11 @@ end_with_restore_list: my_ok(thd); break; case SQLCOM_INSTALL_PLUGIN: - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); if (! (res= mysql_install_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); break; case SQLCOM_UNINSTALL_PLUGIN: - WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL); if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 3fc49dc42ca..fadd7009822 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2005, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. +/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. + Copyright (c) 2009, 2017, SkySQL Ab. 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 @@ -6561,7 +6561,8 @@ uint fast_alter_partition_table(THD *thd, TABLE *table, lpt->alter_info= alter_info; lpt->create_info= create_info; lpt->db_options= create_info->table_options; - if (create_info->row_type == ROW_TYPE_DYNAMIC) + if (create_info->row_type != ROW_TYPE_FIXED && + create_info->row_type != ROW_TYPE_DEFAULT) lpt->db_options|= HA_OPTION_PACK_RECORD; lpt->table= table; lpt->key_info_buffer= 0; @@ -8073,6 +8074,7 @@ int create_partition_name(char *out, size_t outlen, const char *in1, } else transl_part= in2; + if (name_variant == NORMAL_PART_NAME) end= strxnmov(out, outlen-1, in1, "#P#", transl_part, NullS); else if (name_variant == TEMP_PART_NAME) @@ -8087,25 +8089,19 @@ int create_partition_name(char *out, size_t outlen, const char *in1, return 0; } - -/* - Create subpartition name - - SYNOPSIS - create_subpartition_name() - out:out The buffer for the created partition name string - must be *at least* of FN_REFLEN+1 bytes - in1 First part - in2 Second part - in3 Third part - name_variant Normal, temporary or renamed partition name - - RETURN VALUE - 0 if ok, error if name too long - - DESCRIPTION - This method is used to calculate the subpartition name, service routine to - the del_ren_cre_table method. +/** + Create subpartition name. This method is used to calculate the + subpartition name, service routine to the del_ren_cre_table method. + The output buffer size should be FN_REFLEN + 1(terminating '\0'). + + @param [out] out Created partition name string + @param in1 First part + @param in2 Second part + @param in3 Third part + @param name_variant Normal, temporary or renamed partition name + + @retval true Error. + @retval false Success. */ int create_subpartition_name(char *out, size_t outlen, @@ -8117,6 +8113,7 @@ int create_subpartition_name(char *out, size_t outlen, tablename_to_filename(in2, transl_part_name, FN_REFLEN); tablename_to_filename(in3, transl_subpart_name, FN_REFLEN); + if (name_variant == NORMAL_PART_NAME) end= strxnmov(out, outlen-1, in1, "#P#", transl_part_name, "#SP#", transl_subpart_name, NullS); diff --git a/sql/sql_partition.h b/sql/sql_partition.h index b0dede7487e..992229afb05 100644 --- a/sql/sql_partition.h +++ b/sql/sql_partition.h @@ -1,7 +1,8 @@ #ifndef SQL_PARTITION_INCLUDED #define SQL_PARTITION_INCLUDED -/* Copyright (c) 2006, 2013, Oracle and/or its affiliates. +/* Copyright (c) 2006, 2017, Oracle and/or its affiliates. + Copyright (c) 2011, 2017, MariaDB 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 diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index a4e6546e38a..9478db8e6d5 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -228,7 +228,6 @@ static DYNAMIC_ARRAY plugin_array; static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM]; static MEM_ROOT plugin_mem_root; static bool reap_needed= false; -static int plugin_array_version=0; static bool initialized= 0; ulong dlopen_count; @@ -323,7 +322,6 @@ static void unlock_variables(THD *thd, struct system_variables *vars); static void cleanup_variables(struct system_variables *vars); static void plugin_vars_free_values(sys_var *vars); static void restore_ptr_backup(uint n, st_ptr_backup *backup); -static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin); static void intern_plugin_unlock(LEX *lex, plugin_ref plugin); static void reap_plugins(void); @@ -951,15 +949,17 @@ SHOW_COMP_OPTION plugin_status(const char *name, size_t len, int type) If LEX is passed non-NULL, an automatic unlock of the plugin will happen in the LEX destructor. */ -static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc) +static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc, + uint state_mask= PLUGIN_IS_READY | + PLUGIN_IS_UNINITIALIZED | + PLUGIN_IS_DELETED) { st_plugin_int *pi= plugin_ref_to_int(rc); DBUG_ENTER("intern_plugin_lock"); mysql_mutex_assert_owner(&LOCK_plugin); - if (pi->state & (PLUGIN_IS_READY | PLUGIN_IS_UNINITIALIZED | - PLUGIN_IS_DELETED)) + if (pi->state & state_mask) { plugin_ref plugin; #ifdef DBUG_OFF @@ -1174,7 +1174,6 @@ static bool plugin_add(MEM_ROOT *tmp_root, if (!(tmp_plugin_ptr= plugin_insert_or_reuse(&tmp))) goto err; - plugin_array_version++; if (my_hash_insert(&plugin_hash[plugin->type], (uchar*)tmp_plugin_ptr)) tmp_plugin_ptr->state= PLUGIN_IS_FREED; init_alloc_root(&tmp_plugin_ptr->mem_root, 4096, 4096, MYF(0)); @@ -1274,7 +1273,6 @@ static void plugin_del(struct st_plugin_int *plugin) my_hash_delete(&plugin_hash[plugin->plugin->type], (uchar*)plugin); plugin_dl_del(plugin->plugin_dl); plugin->state= PLUGIN_IS_FREED; - plugin_array_version++; free_root(&plugin->mem_root, MYF(0)); } else @@ -1893,11 +1891,11 @@ static bool plugin_load_list(MEM_ROOT *tmp_root, const char *list) switch ((*(p++)= *(list++))) { case '\0': list= NULL; /* terminate the loop */ -#ifndef __WIN__ /* fall through */ + case ';': +#ifndef __WIN__ case ':': /* can't use this as delimiter as it may be drive letter */ #endif - case ';': str->str[str->length]= '\0'; if (str == &name) // load all plugins in named module { @@ -2158,12 +2156,16 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name, bool error; int argc=orig_argc; char **argv=orig_argv; + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = + { MYSQL_AUDIT_GENERAL_CLASSMASK }; DBUG_ENTER("mysql_install_plugin"); tables.init_one_table("mysql", 5, "plugin", 6, "plugin", 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) + /* need to open before acquiring LOCK_plugin or it will deadlock */ if (! (table = open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) @@ -2196,8 +2198,6 @@ bool mysql_install_plugin(THD *thd, const LEX_CSTRING *name, See also mysql_uninstall_plugin() and initialize_audit_plugin() */ - unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = - { MYSQL_AUDIT_GENERAL_CLASSMASK }; if (mysql_audit_general_enabled()) mysql_audit_acquire_plugins(thd, event_class_mask); @@ -2229,6 +2229,10 @@ err: if (argv) free_defaults(argv); DBUG_RETURN(error); +#ifdef WITH_WSREP +error: + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ } @@ -2295,6 +2299,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, TABLE_LIST tables; LEX_CSTRING dl= *dl_arg; bool error= false; + unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = + { MYSQL_AUDIT_GENERAL_CLASSMASK }; DBUG_ENTER("mysql_uninstall_plugin"); tables.init_one_table("mysql", 5, "plugin", 6, "plugin", TL_WRITE); @@ -2302,6 +2308,8 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, if (!opt_noacl && check_table_access(thd, DELETE_ACL, &tables, FALSE, 1, FALSE)) DBUG_RETURN(TRUE); + 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, MYSQL_LOCK_IGNORE_TIMEOUT))) DBUG_RETURN(TRUE); @@ -2327,8 +2335,6 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, See also mysql_install_plugin() and initialize_audit_plugin() */ - unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE] = - { MYSQL_AUDIT_GENERAL_CLASSMASK }; if (mysql_audit_general_enabled()) mysql_audit_acquire_plugins(thd, event_class_mask); @@ -2359,70 +2365,65 @@ bool mysql_uninstall_plugin(THD *thd, const LEX_CSTRING *name, mysql_mutex_unlock(&LOCK_plugin); DBUG_RETURN(error); +#ifdef WITH_WSREP +error: + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ } bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func, int type, uint state_mask, void *arg) { - uint idx, total; - struct st_plugin_int *plugin, **plugins; - int version=plugin_array_version; + uint idx, total= 0; + struct st_plugin_int *plugin; + plugin_ref *plugins; + my_bool res= FALSE; DBUG_ENTER("plugin_foreach_with_mask"); if (!initialized) DBUG_RETURN(FALSE); - state_mask= ~state_mask; // do it only once - mysql_mutex_lock(&LOCK_plugin); - total= type == MYSQL_ANY_PLUGIN ? plugin_array.elements - : plugin_hash[type].records; /* Do the alloca out here in case we do have a working alloca: - leaving the nested stack frame invalidates alloca allocation. + leaving the nested stack frame invalidates alloca allocation. */ - plugins=(struct st_plugin_int **)my_alloca(total*sizeof(plugin)); if (type == MYSQL_ANY_PLUGIN) { - for (idx= 0; idx < total; idx++) + plugins= (plugin_ref*) my_alloca(plugin_array.elements * sizeof(plugin_ref)); + for (idx= 0; idx < plugin_array.elements; idx++) { plugin= *dynamic_element(&plugin_array, idx, struct st_plugin_int **); - plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; + if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin), + state_mask))) + total++; } } else { HASH *hash= plugin_hash + type; - for (idx= 0; idx < total; idx++) + plugins= (plugin_ref*) my_alloca(hash->records * sizeof(plugin_ref)); + for (idx= 0; idx < hash->records; idx++) { plugin= (struct st_plugin_int *) my_hash_element(hash, idx); - plugins[idx]= !(plugin->state & state_mask) ? plugin : NULL; + if ((plugins[total]= intern_plugin_lock(0, plugin_int_to_ref(plugin), + state_mask))) + total++; } } mysql_mutex_unlock(&LOCK_plugin); for (idx= 0; idx < total; idx++) { - if (unlikely(version != plugin_array_version)) - { - mysql_mutex_lock(&LOCK_plugin); - for (uint i=idx; i < total; i++) - if (plugins[i] && plugins[i]->state & state_mask) - plugins[i]=0; - mysql_mutex_unlock(&LOCK_plugin); - } - plugin= plugins[idx]; /* It will stop iterating on first engine error when "func" returns TRUE */ - if (plugin && func(thd, plugin_int_to_ref(plugin), arg)) - goto err; + if ((res= func(thd, plugins[idx], arg))) + break; } + plugin_unlock_list(0, plugins, total); my_afree(plugins); - DBUG_RETURN(FALSE); -err: - my_afree(plugins); - DBUG_RETURN(TRUE); + DBUG_RETURN(res); } @@ -3550,7 +3551,6 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var) options->max_value= getopt_double2ulonglong((opt)->max_val); \ options->block_size= (long) (opt)->blk_sz; - void plugin_opt_set_limits(struct my_option *options, const struct st_mysql_sys_var *opt) { diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 7fc6141bcea..775717fe62b 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -725,13 +725,36 @@ void set_param_date(Item_param *param, uchar **pos, ulong len) #endif /*!EMBEDDED_LIBRARY*/ -static void set_param_str(Item_param *param, uchar **pos, ulong len) +static void set_param_str_or_null(Item_param *param, uchar **pos, ulong len, + bool empty_string_is_null) { ulong length= get_param_length(pos, len); - if (length > len) - length= len; - param->set_str((const char *)*pos, length); - *pos+= length; + if (length == 0 && empty_string_is_null) + param->set_null(); + else + { + if (length > len) + length= len; + param->set_str((const char *) *pos, length); + *pos+= length; + } +} + + +static void set_param_str(Item_param *param, uchar **pos, ulong len) +{ + set_param_str_or_null(param, pos, len, false); +} + + +/* + set_param_str_empty_is_null : bind empty string as null value + when sql_mode=MODE_EMPTY_STRING_IS_NULL +*/ +static void set_param_str_empty_is_null(Item_param *param, uchar **pos, + ulong len) +{ + set_param_str_or_null(param, pos, len, true); } @@ -806,7 +829,10 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, param->value.cs_info.final_character_set_of_str_value= String::needs_conversion(0, fromcs, tocs, &dummy_offset) ? tocs : fromcs; - param->set_param_func= set_param_str; + + param->set_param_func= + (thd->variables.sql_mode & MODE_EMPTY_STRING_IS_NULL) ? + set_param_str_empty_is_null : set_param_str; /* Exact value of max_length is not known unless data is converted to charset of connection, so we have to set it later. @@ -1365,7 +1391,8 @@ static bool mysql_test_insert(Prepared_statement *stmt, my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter); goto error; } - if (setup_fields(thd, Ref_ptr_array(), *values, MARK_COLUMNS_NONE, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), + *values, MARK_COLUMNS_NONE, 0, NULL, 0)) goto error; } } @@ -1459,7 +1486,7 @@ static int mysql_test_update(Prepared_statement *stmt, #endif thd->lex->select_lex.no_wrap_view_item= TRUE; res= setup_fields(thd, Ref_ptr_array(), - select->item_list, MARK_COLUMNS_READ, 0, 0); + select->item_list, MARK_COLUMNS_READ, 0, NULL, 0); thd->lex->select_lex.no_wrap_view_item= FALSE; if (res) goto error; @@ -1471,7 +1498,7 @@ static int mysql_test_update(Prepared_statement *stmt, table_list->register_want_access(SELECT_ACL); #endif if (setup_fields(thd, Ref_ptr_array(), - stmt->lex->value_list, MARK_COLUMNS_NONE, 0, 0) || + stmt->lex->value_list, MARK_COLUMNS_NONE, 0, NULL, 0) || check_unique_table(thd, table_list)) goto error; /* TODO: here we should send types of placeholders to the client. */ @@ -1646,7 +1673,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, DT_PREPARE | DT_CREATE)) DBUG_RETURN(TRUE); DBUG_RETURN(setup_fields(thd, Ref_ptr_array(), - *values, MARK_COLUMNS_NONE, 0, 0)); + *values, MARK_COLUMNS_NONE, 0, NULL, 0)); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 49e3d60795d..839b98dc785 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2680,7 +2680,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo, Gtid_list_log_event glev(&info->until_binlog_state, 0); if (reset_transmit_packet(info, info->flags, &ev_offset, &info->errmsg) || - fake_gtid_list_event(info, &glev, &info->errmsg, my_b_tell(log))) + fake_gtid_list_event(info, &glev, &info->errmsg, (uint32)my_b_tell(log))) { info->error= ER_UNKNOWN_ERROR; return 1; @@ -2690,7 +2690,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo, if (info->until_gtid_state && is_until_reached(info, &ev_offset, event_type, &info->errmsg, - my_b_tell(log))) + (uint32)my_b_tell(log))) { if (info->errmsg) { @@ -2745,7 +2745,7 @@ static int send_one_binlog_file(binlog_send_info *info, if (end_pos <= 1) { /** end of file or error */ - return end_pos; + return (int)end_pos; } /** diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 394492f6a1d..53d445177f7 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -809,7 +809,7 @@ JOIN::prepare(TABLE_LIST *tables_init, thd->lex->current_select->context_analysis_place; thd->lex->current_select->context_analysis_place= SELECT_LIST; if (setup_fields(thd, ref_ptrs, fields_list, MARK_COLUMNS_READ, - &all_fields, 1)) + &all_fields, &select_lex->pre_fix, 1)) DBUG_RETURN(-1); thd->lex->current_select->context_analysis_place= save_place; @@ -6144,7 +6144,7 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint, { TABLE *table= s->table; double sel= table->cond_selectivity; - double table_records= table->stat_records(); + double table_records= (double)table->stat_records(); dbl_records= table_records * sel; return dbl_records; } @@ -6170,7 +6170,7 @@ double matching_candidates_in_table(JOIN_TAB *s, bool with_found_constraint, if (s->table->quick_condition_rows != s->found_records) records= s->table->quick_condition_rows; - dbl_records= records; + dbl_records= (double)records; return dbl_records; } @@ -6861,7 +6861,7 @@ static void choose_initial_table_order(JOIN *join) if ((emb_subq= get_emb_subq(*tab))) break; } - uint n_subquery_tabs= tabs_end - tab; + uint n_subquery_tabs= (uint)(tabs_end - tab); if (!n_subquery_tabs) DBUG_VOID_RETURN; @@ -6889,7 +6889,7 @@ static void choose_initial_table_order(JOIN *join) last_tab_for_subq < subq_tabs_end && get_emb_subq(*last_tab_for_subq) == cur_subq_nest; last_tab_for_subq++) {} - uint n_subquery_tables= last_tab_for_subq - subq_tab; + uint n_subquery_tables= (uint)(last_tab_for_subq - subq_tab); /* Walk the original array and find where this subquery would have been @@ -6907,7 +6907,7 @@ static void choose_initial_table_order(JOIN *join) if (!need_tables) { /* Move away the top-level tables that are after top_level_tab */ - uint top_tail_len= last_top_level_tab - top_level_tab - 1; + size_t top_tail_len= last_top_level_tab - top_level_tab - 1; memmove(top_level_tab + 1 + n_subquery_tables, top_level_tab + 1, sizeof(JOIN_TAB*)*top_tail_len); last_top_level_tab += n_subquery_tables; @@ -7653,7 +7653,7 @@ double JOIN::get_examined_rows() JOIN_TAB *tab= first_breadth_first_tab(); JOIN_TAB *prev_tab= tab; - examined_rows= tab->get_examined_rows(); + examined_rows= (double)tab->get_examined_rows(); while ((tab= next_breadth_first_tab(first_breadth_first_tab(), top_join_tab_count, tab))) @@ -7951,7 +7951,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, } if (keyparts > 1) { - ref_keyuse_steps[keyparts-2]= keyuse - prev_ref_keyuse; + ref_keyuse_steps[keyparts-2]= (uint16)(keyuse - prev_ref_keyuse); prev_ref_keyuse= keyuse; } } @@ -8192,9 +8192,11 @@ best_extension_by_limited_search(JOIN *join, best_access_path(join, s, remaining_tables, idx, disable_jbuf, record_count, join->positions + idx, &loose_scan_pos); - /* Compute the cost of extending the plan with 's' */ - - current_record_count= record_count * position->records_read; + /* Compute the cost of extending the plan with 's', avoid overflow */ + if (position->records_read < DBL_MAX / record_count) + current_record_count= record_count * position->records_read; + else + current_record_count= DBL_MAX; current_read_time=read_time + position->read_time + current_record_count / (double) TIME_FOR_COMPARE; @@ -9313,8 +9315,8 @@ bool JOIN::get_best_combination() j= j->bush_root_tab; } - top_join_tab_count= join_tab_ranges.head()->end - - join_tab_ranges.head()->start; + top_join_tab_count= (uint)(join_tab_ranges.head()->end - + join_tab_ranges.head()->start); update_depend_map(this); DBUG_RETURN(0); @@ -10891,7 +10893,7 @@ static uint make_join_orderinfo(JOIN *join) if (join->need_tmp) return join->table_count; tab= join->get_sort_by_join_tab(); - return tab ? tab-join->join_tab : join->table_count; + return tab ? (uint)(tab-join->join_tab) : join->table_count; } /* @@ -11908,8 +11910,8 @@ make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after) str.append(" final_pushdown_cond"); print_where(tab->select_cond, str.c_ptr_safe(), QT_ORDINARY);); } - uint n_top_tables= join->join_tab_ranges.head()->end - - join->join_tab_ranges.head()->start; + uint n_top_tables= (uint)(join->join_tab_ranges.head()->end - + join->join_tab_ranges.head()->start); join->join_tab[n_top_tables - 1].next_select=0; /* Set by do_select */ @@ -12133,7 +12135,7 @@ ha_rows JOIN_TAB::get_examined_rows() SQL_SELECT *sel= filesort? filesort->select : this->select; if (sel && sel->quick && use_quick != 2) - examined_rows= sel->quick->records; + examined_rows= (double)sel->quick->records; else if (type == JT_NEXT || type == JT_ALL || type == JT_HASH || type ==JT_HASH_NEXT) { @@ -12143,19 +12145,19 @@ ha_rows JOIN_TAB::get_examined_rows() @todo This estimate is wrong, a LIMIT query may examine much more rows than the LIMIT itself. */ - examined_rows= limit; + examined_rows= (double)limit; } else { if (table->is_filled_at_execution()) - examined_rows= records; + examined_rows= (double)records; else { /* handler->info(HA_STATUS_VARIABLE) has been called in make_join_statistics() */ - examined_rows= table->stat_records(); + examined_rows= (double)table->stat_records(); } } } @@ -13984,7 +13986,7 @@ static int compare_fields_by_table_order(Item *field1, tab2= tab2->bush_root_tab; } - cmp= tab1 - tab2; + cmp= (int)(tab1 - tab2); if (!cmp) { @@ -15008,10 +15010,23 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top, nested_join= table->nested_join; if (table->sj_on_expr && !in_sj) { - /* - If this is a semi-join that is not contained within another semi-join, - leave it intact (otherwise it is flattened) - */ + /* + If this is a semi-join that is not contained within another semi-join + leave it intact (otherwise it is flattened) + */ + /* + Make sure that any semi-join appear in + the join->select_lex->sj_nests list only once + */ + List_iterator_fast<TABLE_LIST> sj_it(join->select_lex->sj_nests); + TABLE_LIST *sj_nest; + while ((sj_nest= sj_it++)) + { + if (table == sj_nest) + break; + } + if (sj_nest) + continue; join->select_lex->sj_nests.push_back(table, join->thd->mem_root); /* @@ -17146,7 +17161,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, share->default_values= table->record[1]+alloc_length; } copy_func[0]=0; // End marker - param->func_count= copy_func - param->items_to_copy; + param->func_count= (uint)(copy_func - param->items_to_copy); setup_tmp_table_column_bitmaps(table, bitmaps); @@ -17830,7 +17845,7 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo, Emulate behaviour by making column not-nullable when creating the table. */ - uint cols= (*recinfo-start_recinfo); + uint cols= (uint)(*recinfo-start_recinfo); start_recinfo[cols-1].null_bit= 0; } } @@ -21055,7 +21070,7 @@ static int test_if_order_by_key(JOIN *join, (1) this is an extended key (2) we've reached its end */ - key_parts= (key_part - table->key_info[idx].key_part); + key_parts= (uint)(key_part - table->key_info[idx].key_part); if (have_pk_suffix && reverse == 0 && // all were =const so far key_parts == table->key_info[idx].ext_key_parts && @@ -24696,7 +24711,7 @@ void JOIN_TAB::save_explain_data(Explain_table_access *eta, } else { - double examined_rows= get_examined_rows(); + double examined_rows= (double)get_examined_rows(); eta->rows_set= true; eta->rows= (ha_rows) examined_rows; @@ -26081,8 +26096,8 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, Start from quick select's rows and cost. These are always cheaper than full index scan/cost. */ - double best_rows= table->quick_rows[keynr]; - double best_cost= table->quick_costs[keynr]; + double best_rows= (double)table->quick_rows[keynr]; + double best_cost= (double)table->quick_costs[keynr]; /* Check if ref(const) access was possible on this index. @@ -26116,7 +26131,7 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, if (ref_rows > 0) { - double tmp= ref_rows; + double tmp= (double)ref_rows; /* Reuse the cost formula from best_access_path: */ set_if_smaller(tmp, (double) tab->join->thd->variables.max_seeks_for_key); if (table->covering_keys.is_set(keynr)) @@ -26127,7 +26142,7 @@ static bool get_range_limit_read_cost(const JOIN_TAB *tab, if (tmp < best_cost) { best_cost= tmp; - best_rows= ref_rows; + best_rows= (double)ref_rows; } } } @@ -26240,7 +26255,7 @@ test_if_cheaper_ordering(const JOIN_TAB *tab, ORDER *order, TABLE *table, if (join) { - uint tablenr= tab - join->join_tab; + uint tablenr= (uint)(tab - join->join_tab); read_time= join->best_positions[tablenr].read_time; for (uint i= tablenr+1; i < join->table_count; i++) fanout*= join->best_positions[i].records_read; // fanout is always >= 1 diff --git a/sql/sql_sequence.cc b/sql/sql_sequence.cc index 53c9c160593..1af37fe1fad 100644 --- a/sql/sql_sequence.cc +++ b/sql/sql_sequence.cc @@ -335,7 +335,6 @@ bool sequence_insert(THD *thd, LEX *lex, TABLE_LIST *table_list) trans_commit_implicit(thd); if (!temporary_table) close_thread_tables(thd); - thd->mdl_context.release_transactional_locks(); DBUG_RETURN(error); } @@ -596,12 +595,6 @@ int sequence_definition::write(TABLE *table, bool all_fields) else table->rpl_write_set= &table->s->all_set; - /* - The following is needed to fix comparison of rows in - ha_update_first_row() for InnoDB - */ - memcpy(table->record[1],table->s->default_values, table->s->reclength); - /* Update table */ save_write_set= table->write_set; save_read_set= table->read_set; @@ -759,12 +752,12 @@ void SEQUENCE_LAST_VALUE::set_version(TABLE *table) @param in table Sequence table @param in next_val Next free value - @param in next_round Round for 'next_value' (in cace of cycles) + @param in next_round Round for 'next_value' (in case of cycles) @param in is_used 1 if next_val is already used @retval 0 ok, value adjusted - 1 value was less than current value or - error when storing value + -1 value was less than current value + 1 error when storing value @comment A new value is set only if "nextval,next_round" is less than @@ -774,10 +767,10 @@ void SEQUENCE_LAST_VALUE::set_version(TABLE *table) contain the highest used value when the slave is promoted to a master. */ -bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round, +int SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round, bool is_used) { - bool error= 1; + int error= -1; bool needs_to_be_stored= 0; longlong org_reserved_until= reserved_until; longlong org_next_free_value= next_free_value; @@ -789,13 +782,13 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round, next_val= increment_value(next_val); if (round > next_round) - goto end; + goto end; // error = -1 if (round == next_round) { if (real_increment > 0 ? next_val < next_free_value : next_val > next_free_value) - goto end; + goto end; // error = -1 if (next_val == next_free_value) { error= 0; @@ -803,7 +796,13 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round, } } else if (cycle == 0) - goto end; // round < next_round && no cycles + { + // round < next_round && no cycles, which is impossible + my_error(ER_SEQUENCE_RUN_OUT, MYF(0), table->s->db.str, + table->s->table_name.str); + error= 1; + goto end; + } else needs_to_be_stored= 1; @@ -820,6 +819,7 @@ bool SEQUENCE::set_value(TABLE *table, longlong next_val, ulonglong next_round, reserved_until= org_reserved_until; next_free_value= org_next_free_value; round= org_round; + error= 1; goto end; } } diff --git a/sql/sql_sequence.h b/sql/sql_sequence.h index b61e4ffe40d..2d609d8591b 100644 --- a/sql/sql_sequence.h +++ b/sql/sql_sequence.h @@ -105,8 +105,8 @@ public: all_values_used= 0; } longlong next_value(TABLE *table, bool second_round, int *error); - bool set_value(TABLE *table, longlong next_value, ulonglong round_arg, - bool is_used); + int set_value(TABLE *table, longlong next_value, ulonglong round_arg, + bool is_used); longlong increment_value(longlong value) { if (real_increment > 0) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index de928fe9e85..cd08959cc26 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -142,6 +142,12 @@ bool get_lookup_field_values(THD *, COND *, TABLE_LIST *, LOOKUP_FIELD_VALUES *) ** List all table types supported ***************************************************************************/ + +static bool is_show_command(THD *thd) +{ + return sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND; +} + static int make_version_string(char *buf, int buf_length, uint version) { return my_snprintf(buf, buf_length, "%d.%d", version>>8,version&0xff); @@ -281,7 +287,7 @@ int fill_plugins(THD *thd, TABLE_LIST *tables, COND *cond) TABLE *table= tables->table; if (plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN, - ~PLUGIN_IS_FREED, table)) + ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), table)) DBUG_RETURN(1); DBUG_RETURN(0); @@ -989,13 +995,20 @@ find_files(THD *thd, Dynamic_array<LEX_CSTRING*> *files, LEX_CSTRING *db, if (tl.add_file(file->name)) goto err; } - tl.sort(); } else { if (ha_discover_table_names(thd, db, dirp, &tl, false)) goto err; } +#if 1 // TODO: MDEV-13049: #if MYSQL_VERSION_ID < 100300 + /* incomplete optimization, but a less drastic change in GA version */ + if (!thd->lex->select_lex.order_list.elements && + !thd->lex->select_lex.group_list.elements) +#else + if (is_show_command(thd)) +#endif + tl.sort(); DBUG_PRINT("info",("found: %zu files", files->elements())); my_dirend(dirp); @@ -3460,7 +3473,7 @@ static bool show_status_array(THD *thd, const char *wild, prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1); if (*prefix) *prefix_end++= '_'; - len=name_buffer + sizeof(name_buffer) - prefix_end; + len=(int)(name_buffer + sizeof(name_buffer) - prefix_end); #ifdef WITH_WSREP bool is_wsrep_var= FALSE; @@ -3803,6 +3816,15 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) return 0; } } + else if (item->type() == Item::ROW_ITEM) + { + Item_row *item_row= static_cast<Item_row*>(item); + for (uint i= 0; i < item_row->cols(); i++) + { + if (!uses_only_table_name_fields(item_row->element_index(i), table)) + return 0; + } + } else if (item->type() == Item::FIELD_ITEM) { Item_field *item_field= (Item_field*)item; @@ -3822,6 +3844,11 @@ bool uses_only_table_name_fields(Item *item, TABLE_LIST *table) item_field->field_name.length))) return 0; } + else if (item->type() == Item::EXPR_CACHE_ITEM) + { + Item_cache_wrapper *tmp= static_cast<Item_cache_wrapper*>(item); + return uses_only_table_name_fields(tmp->get_orig_item(), table); + } else if (item->type() == Item::REF_ITEM) return uses_only_table_name_fields(item->real_item(), table); @@ -4216,7 +4243,7 @@ make_table_name_list(THD *thd, Dynamic_array<LEX_CSTRING*> *table_names, */ if (res == FIND_FILES_DIR) { - if (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) + if (is_show_command(thd)) return 1; thd->clear_error(); return 2; @@ -5435,7 +5462,7 @@ static void store_column_type(TABLE *table, Field *field, CHARSET_INFO *cs, */ tmp_buff= strchr(column_type.c_ptr_safe(), ' '); table->field[offset]->store(column_type.ptr(), - (tmp_buff ? tmp_buff - column_type.ptr() : + (tmp_buff ? (uint)(tmp_buff - column_type.ptr()) : column_type.length()), cs); is_blob= (field->type() == MYSQL_TYPE_BLOB); @@ -5757,7 +5784,8 @@ int fill_schema_engines(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_ENTER("fill_schema_engines"); if (plugin_foreach_with_mask(thd, iter_schema_engines, MYSQL_STORAGE_ENGINE_PLUGIN, - ~PLUGIN_IS_FREED, tables->table)) + ~(PLUGIN_IS_FREED | PLUGIN_IS_DYING), + tables->table)) DBUG_RETURN(1); DBUG_RETURN(0); } @@ -6017,11 +6045,8 @@ bool store_schema_proc(THD *thd, TABLE *table, TABLE *proc_table, check_some_routine_access(thd, db.str, name.str, sph)) return 0; - if ((lex->sql_command == SQLCOM_SHOW_STATUS_PROC && - sph->type() == TYPE_ENUM_PROCEDURE) || - (lex->sql_command == SQLCOM_SHOW_STATUS_FUNC && - sph->type() == TYPE_ENUM_FUNCTION) || - (sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0) + if (!is_show_command(thd) || + sph == Sp_handler::handler(lex->sql_command)) { restore_record(table, s->default_values); if (!wild || !wild[0] || !wild_case_compare(system_charset_info, @@ -6147,6 +6172,10 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(1); } + /* Disable padding temporarily so it doesn't break the query */ + ulonglong sql_mode_was = thd->variables.sql_mode; + thd->variables.sql_mode &= ~MODE_PAD_CHAR_TO_FULL_LENGTH; + if (proc_table->file->ha_index_init(0, 1)) { res= 1; @@ -6182,6 +6211,7 @@ err: (void) proc_table->file->ha_index_end(); close_system_tables(thd, &open_tables_state_backup); + thd->variables.sql_mode = sql_mode_was; DBUG_RETURN(res); } @@ -6405,7 +6435,7 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables, table->field[5]->store(STRING_WITH_LEN("NO"), cs); } - definer_len= (strxmov(definer, tables->definer.user.str, "@", + definer_len= (uint)(strxmov(definer, tables->definer.user.str, "@", tables->definer.host.str, NullS) - definer); table->field[6]->store(definer, definer_len, cs); if (tables->view_suid) @@ -7769,7 +7799,7 @@ TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list) tmp_table_param->field_count= field_count; tmp_table_param->schema_table= 1; SELECT_LEX *select_lex= thd->lex->current_select; - bool keep_row_order= sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND; + bool keep_row_order= is_show_command(thd); if (!(table= create_tmp_table(thd, tmp_table_param, field_list, (ORDER*) 0, 0, 0, (select_lex->options | thd->variables.option_bits | diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 0048e525cad..2cb47634fe4 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -849,7 +849,7 @@ public: else { stat_field->set_notnull(); - stat_field->store(table->collected_stats->cardinality); + stat_field->store(table->collected_stats->cardinality,true); } } @@ -1060,7 +1060,7 @@ public: switch (i) { case COLUMN_STAT_MIN_VALUE: if (table_field->type() == MYSQL_TYPE_BIT) - stat_field->store(table_field->collected_stats->min_value->val_int()); + stat_field->store(table_field->collected_stats->min_value->val_int(),true); else { table_field->collected_stats->min_value->val_str(&val); @@ -1069,7 +1069,7 @@ public: break; case COLUMN_STAT_MAX_VALUE: if (table_field->type() == MYSQL_TYPE_BIT) - stat_field->store(table_field->collected_stats->max_value->val_int()); + stat_field->store(table_field->collected_stats->max_value->val_int(),true); else { table_field->collected_stats->max_value->val_str(&val); @@ -1636,7 +1636,7 @@ public: of the parameters to be passed to the constructor of the Unique object. */ - Count_distinct_field(Field *field, uint max_heap_table_size) + Count_distinct_field(Field *field, size_t max_heap_table_size) { table_field= field; tree_key_length= field->pack_length(); @@ -1734,7 +1734,7 @@ class Count_distinct_field_bit: public Count_distinct_field { public: - Count_distinct_field_bit(Field *field, uint max_heap_table_size) + Count_distinct_field_bit(Field *field, size_t max_heap_table_size) { table_field= field; tree_key_length= sizeof(ulonglong); @@ -1830,7 +1830,7 @@ public: if ((calc_state= (Prefix_calc_state *) thd->alloc(sizeof(Prefix_calc_state)*key_parts))) { - uint keyno= key_info-table->key_info; + uint keyno= (uint)(key_info-table->key_info); for (i= 0, state= calc_state; i < key_parts; i++, state++) { /* @@ -2444,7 +2444,7 @@ int alloc_histograms_for_table_share(THD* thd, TABLE_SHARE *table_share, inline void Column_statistics_collected::init(THD *thd, Field *table_field) { - uint max_heap_table_size= thd->variables.max_heap_table_size; + size_t max_heap_table_size= (size_t)thd->variables.max_heap_table_size; TABLE *table= table_field->table; uint pk= table->s->primary_key; @@ -3725,14 +3725,14 @@ double get_column_avg_frequency(Field * field) */ if (!table->s->field) { - res= table->stat_records(); + res= (double)table->stat_records(); return res; } Column_statistics *col_stats= field->read_stats; if (!col_stats) - res= table->stat_records(); + res= (double)table->stat_records(); else res= col_stats->get_avg_frequency(); return res; @@ -3771,7 +3771,7 @@ double get_column_range_cardinality(Field *field, double res; TABLE *table= field->table; Column_statistics *col_stats= field->read_stats; - double tab_records= table->stat_records(); + double tab_records= (double)table->stat_records(); if (!col_stats) return tab_records; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 724389592e3..7371889cc7f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -230,7 +230,7 @@ uint explain_filename(THD* thd, { db_name= table_name; /* calculate the length */ - db_name_len= tmp_p - db_name; + db_name_len= (int)(tmp_p - db_name); tmp_p++; table_name= tmp_p; } @@ -252,7 +252,7 @@ uint explain_filename(THD* thd, case 's': if ((tmp_p[1] == 'P' || tmp_p[1] == 'p') && tmp_p[2] == '#') { - part_name_len= tmp_p - part_name - 1; + part_name_len= (int)(tmp_p - part_name - 1); subpart_name= tmp_p + 3; tmp_p+= 3; } @@ -284,7 +284,7 @@ uint explain_filename(THD* thd, } if (part_name) { - table_name_len= part_name - table_name - 3; + table_name_len= (int)(part_name - table_name - 3); if (subpart_name) subpart_name_len= strlen(subpart_name); else @@ -357,7 +357,7 @@ uint explain_filename(THD* thd, to_p= strnmov(to_p, " */", end_p - to_p); } DBUG_PRINT("exit", ("to '%s'", to)); - DBUG_RETURN(to_p - to); + DBUG_RETURN((uint)(to_p - to)); } @@ -553,7 +553,7 @@ uint build_table_filename(char *buff, size_t bufflen, const char *db, pos= strxnmov(pos, end - pos, tbbuff, ext, NullS); DBUG_PRINT("exit", ("buff: '%s'", buff)); - DBUG_RETURN(pos - buff); + DBUG_RETURN((uint)(pos - buff)); } @@ -1990,7 +1990,7 @@ int write_bin_log(THD *thd, bool clear_error, tables List of tables to delete if_exists If 1, don't give error if one table doesn't exists drop_temporary 1 if DROP TEMPORARY - drop_seqeunce 1 if DROP SEQUENCE + drop_sequence 1 if DROP SEQUENCE NOTES Will delete all tables that can be deleted and give a compact error @@ -2038,6 +2038,25 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists, if (!thd->locked_tables_mode) { + if (drop_sequence) + { + /* We are trying to drop a sequence. + Change all temporary tables that are not sequences to + normal tables so that we can try to drop them instead. + If we don't do this, we will get an error 'not a sequence' + when trying to drop a sequence that is hidden by a temporary + table. + */ + for (table= tables; table; table= table->next_global) + { + if (table->open_type == OT_TEMPORARY_OR_BASE && + is_temporary_table(table) && !table->table->s->sequence) + { + thd->mark_tmp_table_as_free_for_reuse(table->table); + table->table= NULL; + } + } + } if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout, 0)) DBUG_RETURN(true); @@ -2134,7 +2153,7 @@ static uint32 comment_length(THD *thd, uint32 comment_pos, for (query+= 3; query < query_end; query++) { if (query[-1] == '*' && query[0] == '/') - return (char*) query - *comment_start + 1; + return (uint32)((char*) query - *comment_start + 1); } return 0; } @@ -2724,7 +2743,7 @@ bool quick_rm_table(THD *thd, handlerton *base, const char *db, bool error= 0; DBUG_ENTER("quick_rm_table"); - uint path_length= table_path ? + size_t path_length= table_path ? (strxnmov(path, sizeof(path) - 1, table_path, reg_ext, NullS) - path) : build_table_filename(path, sizeof(path)-1, db, table_name, reg_ext, flags); if (mysql_file_delete(key_file_frm, path, MYF(0))) @@ -3306,7 +3325,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, { if (!(file->ha_table_flags() & HA_CAN_TABLES_WITHOUT_ROLLBACK)) { - my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), file->engine_name()->str, + my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), file->table_type(), "SEQUENCE"); DBUG_RETURN(TRUE); } @@ -4022,7 +4041,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (!sql_field->default_value && !sql_field->has_default_function() && (sql_field->flags & NOT_NULL_FLAG) && - !sql_field->is_timestamp_type()) + (!sql_field->is_timestamp_type() || + opt_explicit_defaults_for_timestamp)) { sql_field->flags|= NO_DEFAULT_VALUE_FLAG; sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT; @@ -4031,6 +4051,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, if (thd->variables.sql_mode & MODE_NO_ZERO_DATE && !sql_field->default_value && !sql_field->vcol_info && sql_field->is_timestamp_type() && + !opt_explicit_defaults_for_timestamp && (sql_field->flags & NOT_NULL_FLAG) && (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD)) { @@ -6558,7 +6579,7 @@ static bool fill_alter_inplace_info(THD *thd, table_key; ha_alter_info->index_add_buffer [ha_alter_info->index_add_count++]= - new_key - ha_alter_info->key_info_buffer; + (uint)(new_key - ha_alter_info->key_info_buffer); /* Mark all old fields which are used in newly created index. */ DBUG_PRINT("info", ("index changed: '%s'", table_key->name.str)); } @@ -6583,7 +6604,7 @@ static bool fill_alter_inplace_info(THD *thd, /* Key not found. Add the offset of the key to the add buffer. */ ha_alter_info->index_add_buffer [ha_alter_info->index_add_count++]= - new_key - ha_alter_info->key_info_buffer; + (uint)(new_key - ha_alter_info->key_info_buffer); DBUG_PRINT("info", ("index added: '%s'", new_key->name.str)); } else @@ -6923,7 +6944,6 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled, case Alter_info::LEAVE_AS_IS: if (!indexes_were_disabled) break; - /* disabled indexes */ /* fall through */ case Alter_info::DISABLE: error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE); diff --git a/sql/sql_test.cc b/sql/sql_test.cc index ab12278ef8c..3d43c35177d 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -85,8 +85,9 @@ static my_bool print_cached_tables_callback(TDC_element *element, while ((entry= it++)) { THD *in_use= entry->in_use; - printf("%-14.14s %-32s%6ld%8ld%6d %s\n", - entry->s->db.str, entry->s->table_name.str, element->version, + printf("%-14.14s %-32s%6lu%8ld%6d %s\n", + entry->s->db.str, entry->s->table_name.str, + (ulong) element->version, in_use ? (long) in_use->thread_id : (long) 0, entry->db_stat ? 1 : 0, in_use ? lock_descriptions[(int)entry->reginfo.lock_type] : @@ -106,7 +107,8 @@ static void print_cached_tables(void) tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true); - printf("\nCurrent refresh version: %ld\n", tdc_refresh_version()); + printf("\nCurrent refresh version: %ld\n", + (long) tdc_refresh_version()); fflush(stdout); /* purecov: end */ return; @@ -172,7 +174,7 @@ TEST_join(JOIN *join) in order not to garble the tabular output below. */ String ref_key_parts[MAX_TABLES]; - int tables_in_range= jt_range->end - jt_range->start; + int tables_in_range= (int)(jt_range->end - jt_range->start); for (i= 0; i < tables_in_range; i++) { JOIN_TAB *tab= jt_range->start + i; diff --git a/sql/sql_time.cc b/sql/sql_time.cc index a8a0ffa3cf2..309ede45ecc 100644 --- a/sql/sql_time.cc +++ b/sql/sql_time.cc @@ -274,7 +274,7 @@ to_ascii(CHARSET_INFO *cs, *dst++= static_cast<char>(wc); } *dst= '\0'; - return dst - dst0; + return (uint)(dst - dst0); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index dcce8ae3724..d6c722246e7 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -453,6 +453,7 @@ 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) { @@ -616,6 +617,10 @@ end: my_ok(thd); DBUG_RETURN(result); +#ifdef WITH_WSREP + error: + DBUG_RETURN(true); +#endif /* WITH_WSREP */ } /** diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 3ea364f2fba..62dcff33f1d 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -1625,6 +1625,17 @@ bool Type_handler_null:: return false; } +bool Type_handler_row:: + Column_definition_prepare_stage1(THD *thd, + MEM_ROOT *mem_root, + Column_definition *def, + handler *file, + ulonglong table_flags) const +{ + def->create_length_to_internal_length_null(); + return false; +} + bool Type_handler_newdecimal:: Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, @@ -2687,9 +2698,27 @@ Type_handler_string_result::Item_get_cache(THD *thd, const Item *item) const } Item_cache * -Type_handler_temporal_result::Item_get_cache(THD *thd, const Item *item) const +Type_handler_timestamp_common::Item_get_cache(THD *thd, const Item *item) const +{ + return new (thd->mem_root) Item_cache_datetime(thd); +} + +Item_cache * +Type_handler_datetime_common::Item_get_cache(THD *thd, const Item *item) const +{ + return new (thd->mem_root) Item_cache_datetime(thd); +} + +Item_cache * +Type_handler_time_common::Item_get_cache(THD *thd, const Item *item) const +{ + return new (thd->mem_root) Item_cache_time(thd); +} + +Item_cache * +Type_handler_date_common::Item_get_cache(THD *thd, const Item *item) const { - return new (thd->mem_root) Item_cache_temporal(thd, item->type_handler()); + return new (thd->mem_root) Item_cache_date(thd); } /*************************************************************************/ @@ -3531,7 +3560,7 @@ bool Type_handler_numeric:: bool Type_handler_temporal_result:: Item_func_between_fix_length_and_dec(Item_func_between *func) const { - return func->fix_length_and_dec_numeric(current_thd); + return func->fix_length_and_dec_temporal(current_thd); } bool Type_handler_string_result:: @@ -5259,7 +5288,7 @@ Item *Type_handler_time_common:: longlong value= item->val_time_packed(); if (item->null_value) return new (thd->mem_root) Item_null(thd, item->name.str); - cache= new (thd->mem_root) Item_cache_temporal(thd, this); + cache= new (thd->mem_root) Item_cache_time(thd); if (cache) cache->store_packed(value, item); return cache; @@ -5273,7 +5302,7 @@ Item *Type_handler_temporal_with_date:: longlong value= item->val_datetime_packed(); if (item->null_value) return new (thd->mem_root) Item_null(thd, item->name.str); - cache= new (thd->mem_root) Item_cache_temporal(thd, this); + cache= new (thd->mem_root) Item_cache_datetime(thd); if (cache) cache->store_packed(value, item); return cache; diff --git a/sql/sql_type.h b/sql/sql_type.h index 0354adfde1e..d94c5a87811 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -1046,18 +1046,13 @@ public: } bool Column_definition_fix_attributes(Column_definition *c) const { - DBUG_ASSERT(0); - return true; + return false; } bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, Column_definition *c, handler *file, - ulonglong table_flags) const - { - DBUG_ASSERT(0); - return true; - } + ulonglong table_flags) const; bool Column_definition_redefine_stage1(Column_definition *def, const Column_definition *dup, const handler *file, @@ -1071,8 +1066,7 @@ public: handler *file, ulonglong table_flags) const { - DBUG_ASSERT(0); - return true; + return false; } Field *make_table_field(const LEX_CSTRING *name, const Record_addr &addr, @@ -1584,7 +1578,6 @@ public: Item *source_expr, Item *source_const) const; bool subquery_type_allows_materialization(const Item *inner, const Item *outer) const; - Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; @@ -2066,6 +2059,7 @@ public: } int Item_save_in_field(Item *item, Field *field, bool no_conversions) const; String *print_item_value(THD *thd, Item *item, String *str) const; + Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -2152,6 +2146,7 @@ public: bool Column_definition_fix_attributes(Column_definition *c) const; uint Item_decimal_precision(const Item *item) const; String *print_item_value(THD *thd, Item *item, String *str) const; + Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -2225,6 +2220,7 @@ public: return Item_send_datetime(item, protocol, buf); } String *print_item_value(THD *thd, Item *item, String *str) const; + Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, @@ -2304,6 +2300,7 @@ public: return Item_send_datetime(item, protocol, buf); } String *print_item_value(THD *thd, Item *item, String *str) const; + Item_cache *Item_get_cache(THD *thd, const Item *item) const; bool Item_hybrid_func_fix_attributes(THD *thd, const char *name, Type_handler_hybrid_field_type *, diff --git a/sql/sql_update.cc b/sql/sql_update.cc index d188be8bc97..96f48be5ff2 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -80,7 +80,7 @@ bool compare_record(const TABLE *table) { if (field->real_maybe_null()) { - uchar null_byte_index= field->null_ptr - table->record[0]; + uchar null_byte_index= (uchar)(field->null_ptr - table->record[0]); if (((table->record[0][null_byte_index]) & field->null_bit) != ((table->record[1][null_byte_index]) & field->null_bit)) @@ -362,7 +362,7 @@ int mysql_update(THD *thd, table_list->grant.want_privilege= table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif - if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, 0)) + if (setup_fields(thd, Ref_ptr_array(), values, MARK_COLUMNS_READ, 0, NULL, 0)) { free_underlaid_joins(thd, select_lex); DBUG_RETURN(1); /* purecov: inspected */ @@ -1683,7 +1683,7 @@ int multi_update::prepare(List<Item> ¬_used_values, */ int error= setup_fields(thd, Ref_ptr_array(), - *values, MARK_COLUMNS_READ, 0, 0); + *values, MARK_COLUMNS_READ, 0, NULL, 0); ti.rewind(); while ((table_ref= ti++)) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index fd6ecbbdec9..2d8129fd223 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -430,6 +430,8 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, lex->link_first_table_back(view, link_to_local); view->open_type= OT_BASE_ONLY; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) + if (check_dependencies_in_with_clauses(lex->with_clauses_list)) { res= TRUE; @@ -707,6 +709,10 @@ 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 277d67ca014..67b73dea506 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -392,11 +392,11 @@ LEX::create_item_for_sp_var(LEX_CSTRING *name, sp_variable *spvar, DBUG_ASSERT(spcont && spvar); /* Position and length of the SP variable name in the query. */ - pos_in_q= start_in_q - sphead->m_tmp_query; - len_in_q= end_in_q - start_in_q; + pos_in_q= (uint)(start_in_q - sphead->m_tmp_query); + len_in_q= (uint)(end_in_q - start_in_q); item= new (thd->mem_root) - Item_splocal(thd, name, spvar->offset, spvar->sql_type(), + Item_splocal(thd, name, spvar->offset, spvar->type_handler(), pos_in_q, len_in_q); #ifdef DBUG_ASSERT_EXISTS @@ -4762,17 +4762,11 @@ size_number: switch (end_ptr[0]) { case 'g': - case 'G': - text_shift_number+=10; - /* fall through */ + case 'G': text_shift_number+=30; break; case 'm': - case 'M': - text_shift_number+=10; - /* fall through */ + case 'M': text_shift_number+=20; break; case 'k': - case 'K': - text_shift_number+=10; - break; + case 'K': text_shift_number+=10; break; default: my_yyabort_error((ER_WRONG_SIZE_NUMBER, MYF(0))); } @@ -5906,7 +5900,7 @@ create_table_option: | SEQUENCE_SYM opt_equal choice { Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE; - Lex->create_info.sequence= $3; + Lex->create_info.sequence= ($3 == HA_CHOICE_YES); } ; @@ -9877,26 +9871,22 @@ function_call_nonkeyword: } | SUBSTRING '(' expr ',' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7))) MYSQL_YYABORT; } | SUBSTRING '(' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5))) MYSQL_YYABORT; } | SUBSTRING '(' expr FROM expr FOR_SYM expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7))) MYSQL_YYABORT; } | SUBSTRING '(' expr FROM expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5))) MYSQL_YYABORT; } | SYSDATE opt_time_precision @@ -13872,36 +13862,18 @@ text_literal: } | NCHAR_STRING { - DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info)); - $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length, - national_charset_info, - DERIVATION_COERCIBLE, - $1.repertoire()); - if ($$ == NULL) + if (!($$= thd->make_string_literal_nchar($1))) MYSQL_YYABORT; } | UNDERSCORE_CHARSET TEXT_STRING { - $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str, - $2.length, $1); - if ($$ == NULL) + if (!($$= thd->make_string_literal_charset($2, $1))) MYSQL_YYABORT; } | text_literal TEXT_STRING_literal { - Item_string* item= (Item_string*) $1; - item->append($2.str, $2.length); - if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED)) - { - /* - If the string has been pure ASCII so far, - check the new part. - */ - CHARSET_INFO *cs= thd->variables.collation_connection; - item->collation.repertoire|= my_string_repertoire(cs, - $2.str, - $2.length); - } + if (!($$= thd->make_string_literal_concat($1, $2))) + MYSQL_YYABORT; } ; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index ad8b6697ce7..db45414fd28 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -5777,7 +5777,7 @@ create_table_option: | SEQUENCE_SYM opt_equal choice { Lex->create_info.used_fields|= HA_CREATE_USED_SEQUENCE; - Lex->create_info.sequence= $3; + Lex->create_info.sequence= ($3 == HA_CHOICE_YES); } ; @@ -9896,26 +9896,22 @@ function_call_nonkeyword: } | SUBSTRING '(' expr ',' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7))) MYSQL_YYABORT; } | SUBSTRING '(' expr ',' expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5))) MYSQL_YYABORT; } | SUBSTRING '(' expr FROM expr FOR_SYM expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5, $7); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5, $7))) MYSQL_YYABORT; } | SUBSTRING '(' expr FROM expr ')' { - $$= new (thd->mem_root) Item_func_substr(thd, $3, $5); - if ($$ == NULL) + if (!($$= Lex->make_item_func_substr(thd, $3, $5))) MYSQL_YYABORT; } | SYSDATE opt_time_precision @@ -13924,36 +13920,18 @@ text_literal: } | NCHAR_STRING { - DBUG_ASSERT(my_charset_is_ascii_based(national_charset_info)); - $$= new (thd->mem_root) Item_string(thd, $1.str, $1.length, - national_charset_info, - DERIVATION_COERCIBLE, - $1.repertoire()); - if ($$ == NULL) + if (!($$= thd->make_string_literal_nchar($1))) MYSQL_YYABORT; } | UNDERSCORE_CHARSET TEXT_STRING { - $$= new (thd->mem_root) Item_string_with_introducer(thd, $2.str, - $2.length, $1); - if ($$ == NULL) + if (!($$= thd->make_string_literal_charset($2, $1))) MYSQL_YYABORT; } | text_literal TEXT_STRING_literal { - Item_string* item= (Item_string*) $1; - item->append($2.str, $2.length); - if (!(item->collation.repertoire & MY_REPERTOIRE_EXTENDED)) - { - /* - If the string has been pure ASCII so far, - check the new part. - */ - CHARSET_INFO *cs= thd->variables.collation_connection; - item->collation.repertoire|= my_string_repertoire(cs, - $2.str, - $2.length); - } + if (!($$= thd->make_string_literal_concat($1, $2))) + MYSQL_YYABORT; } ; diff --git a/sql/strfunc.cc b/sql/strfunc.cc index f4c8fcd517f..45a0f8f6558 100644 --- a/sql/strfunc.cc +++ b/sql/strfunc.cc @@ -339,7 +339,7 @@ int find_string_in_array(LEX_CSTRING * const haystack, LEX_CSTRING * const needl if (!cs->coll->strnncollsp(cs, (uchar *) pos->str, pos->length, (uchar *) needle->str, needle->length)) { - return (pos - haystack); + return (int)(pos - haystack); } return -1; } diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index fd704ca6dae..e5f9be5c769 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1523,7 +1523,7 @@ static Sys_var_ulonglong Sys_max_heap_table_size( "max_heap_table_size", "Don't allow creation of heap tables bigger than this", SESSION_VAR(max_heap_table_size), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(16384, (ulonglong)~(intptr)0), DEFAULT(16*1024*1024), + VALID_RANGE(16384, SIZE_T_MAX), DEFAULT(16*1024*1024), BLOCK_SIZE(1024)); static ulong mdl_locks_cache_size; @@ -3138,7 +3138,7 @@ static const char *sql_mode_names[]= "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE", "NO_ENGINE_SUBSTITUTION", - "PAD_CHAR_TO_FULL_LENGTH", + "PAD_CHAR_TO_FULL_LENGTH", "EMPTY_STRING_IS_NULL", 0 }; diff --git a/sql/table.cc b/sql/table.cc index 70adb869e0a..6d32440bb11 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2516,7 +2516,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, the correct null_bytes can now be set, since bitfields have been taken into account */ - share->null_bytes= (null_pos - (uchar*) null_flags + + share->null_bytes= (uint)(null_pos - (uchar*) null_flags + (null_bit_pos + 7) / 8); share->last_null_bit_pos= null_bit_pos; share->null_bytes_for_compare= null_bits_are_used ? share->null_bytes : 0; @@ -5721,7 +5721,8 @@ Item *Field_iterator_table::create_item(THD *thd) Item_field *item= new (thd->mem_root) Item_field(thd, &select->context, *ptr); DBUG_ASSERT(strlen(item->name.str) == item->name.length); if (item && thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && - !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS) + !thd->lex->in_sum_func && select->cur_pos_in_select_list != UNDEF_POS && + select->join) { select->join->non_agg_fields.push_back(item); item->marker= select->cur_pos_in_select_list; @@ -6002,8 +6003,8 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ /* The field belongs to a merge view or information schema table. */ Field_translator *translated_field= view_field_it.field_translator(); nj_col= new Natural_join_column(translated_field, table_ref); - field_count= table_ref->field_translation_end - - table_ref->field_translation; + field_count= (uint)(table_ref->field_translation_end - + table_ref->field_translation); } else { diff --git a/sql/table.h b/sql/table.h index 5a9f3c18ab9..94a161eefba 100644 --- a/sql/table.h +++ b/sql/table.h @@ -35,6 +35,7 @@ /* Structs that defines the TABLE */ class Item; /* Needed by ORDER */ +typedef Item (*Item_ptr); class Item_subselect; class Item_field; class GRANT_TABLE; @@ -2556,7 +2557,7 @@ typedef struct st_nested_join table_map sj_depends_on; /* Outer non-trivially correlated tables */ table_map sj_corr_tables; - List<Item> sj_outer_expr_list; + List<Item_ptr> sj_outer_expr_list; /** True if this join nest node is completely covered by the query execution plan. This means two things. diff --git a/sql/unireg.cc b/sql/unireg.cc index 49724a3f47e..1ca0233552e 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -981,13 +981,18 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, null_count+= field->length & 7; if (field->default_value && !field->default_value->flags && - !(field->flags & BLOB_FLAG)) + (!(field->flags & BLOB_FLAG) || + field->real_field_type() == MYSQL_TYPE_GEOMETRY)) { Item *expr= field->default_value->expr; + int res= !expr->fixed && // may be already fixed if ALTER TABLE expr->fix_fields(thd, &expr); if (!res) res= expr->save_in_field(regfield, 1); + if (!res && (field->flags & BLOB_FLAG)) + regfield->reset(); + /* If not ok or warning of level 'note' */ if (res != 0 && res != 3) { @@ -996,6 +1001,7 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options, delete regfield; //To avoid memory leak goto err; } + delete regfield; //To avoid memory leak } else if (regfield->real_type() == MYSQL_TYPE_ENUM && (field->flags & NOT_NULL_FLAG)) |