diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-05-04 22:00:24 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-05-04 22:00:24 +0200 |
commit | 49c853fb948aeaeb5c7e3f02da3f14da51ee4100 (patch) | |
tree | 8c3d487a02209cc0c6f126144f1340fc5897d527 /sql | |
parent | ae18a28500974351cf42fa3cac67c83e0647d510 (diff) | |
parent | 4c87f727734955f9e4a0ffde25aae4d43ec0b2a5 (diff) | |
download | mariadb-git-49c853fb948aeaeb5c7e3f02da3f14da51ee4100.tar.gz |
Merge branch '5.5' into 10.0
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.h | 10 | ||||
-rw-r--r-- | sql/item.cc | 30 | ||||
-rw-r--r-- | sql/item.h | 26 | ||||
-rw-r--r-- | sql/item_geofunc.h | 4 | ||||
-rw-r--r-- | sql/item_strfunc.h | 3 | ||||
-rw-r--r-- | sql/lex.h | 4 | ||||
-rw-r--r-- | sql/log.cc | 37 | ||||
-rw-r--r-- | sql/mysqld.cc | 11 | ||||
-rw-r--r-- | sql/opt_subselect.cc | 55 | ||||
-rw-r--r-- | sql/opt_subselect.h | 4 | ||||
-rw-r--r-- | sql/slave.cc | 22 | ||||
-rw-r--r-- | sql/sp.cc | 6 | ||||
-rw-r--r-- | sql/sql_admin.cc | 41 | ||||
-rw-r--r-- | sql/sql_base.cc | 8 | ||||
-rw-r--r-- | sql/sql_class.cc | 31 | ||||
-rw-r--r-- | sql/sql_class.h | 14 | ||||
-rw-r--r-- | sql/sql_delete.cc | 3 | ||||
-rw-r--r-- | sql/sql_derived.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 39 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 51 | ||||
-rw-r--r-- | sql/sql_select.h | 16 | ||||
-rw-r--r-- | sql/sql_table.cc | 5 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 10 | ||||
-rw-r--r-- | sql/sql_update.cc | 4 | ||||
-rw-r--r-- | sql/sql_view.cc | 155 | ||||
-rw-r--r-- | sql/sql_view.h | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 49 | ||||
-rw-r--r-- | sql/sys_vars.cc | 8 | ||||
-rw-r--r-- | sql/table.cc | 42 | ||||
-rw-r--r-- | sql/uniques.cc | 14 |
31 files changed, 526 insertions, 190 deletions
diff --git a/sql/field.h b/sql/field.h index 6f4bcc638c9..8d76f54e216 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1,7 +1,7 @@ #ifndef FIELD_INCLUDED #define FIELD_INCLUDED /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2014, SkySQL Ab. + Copyright (c) 2008, 2015, 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 @@ -2561,6 +2561,14 @@ public: int store(longlong nr, bool unsigned_val); int store_decimal(const my_decimal *); uint size_of() const { return sizeof(*this); } + /** + Key length is provided only to support hash joins. (compared byte for byte) + Ex: SELECT .. FROM t1,t2 WHERE t1.field_geom1=t2.field_geom2. + + The comparison is not very relevant, as identical geometry might be + represented differently, but we need to support it either way. + */ + uint32 key_length() const { return packlength; } /** Non-nullable GEOMETRY types cannot have defaults, diff --git a/sql/item.cc b/sql/item.cc index 132cfa2846a..a465c2d4e36 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2014, Monty Program Ab. + Copyright (c) 2010, 2015, 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 @@ -7931,6 +7931,7 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference) return TRUE; if (view->table && view->table->maybe_null) maybe_null= TRUE; + set_null_ref_table(); return FALSE; } @@ -9775,13 +9776,30 @@ void Item_ref::update_used_tables() (*ref)->update_used_tables(); } +void Item_direct_view_ref::update_used_tables() +{ + set_null_ref_table(); + Item_direct_ref::update_used_tables(); +} + + table_map Item_direct_view_ref::used_tables() const { - return get_depended_from() ? - OUTER_REF_TABLE_BIT : - ((view->is_merged_derived() || view->merged || !view->table) ? - (*ref)->used_tables() : - view->table->map); + DBUG_ASSERT(null_ref_table); + + if (get_depended_from()) + return OUTER_REF_TABLE_BIT; + + if (view->is_merged_derived() || view->merged || !view->table) + { + table_map used= (*ref)->used_tables(); + return (used ? + used : + ((null_ref_table != NO_NULL_TABLE) ? + null_ref_table->map : + (table_map)0 )); + } + return view->table->map; } table_map Item_direct_view_ref::not_null_tables() const diff --git a/sql/item.h b/sql/item.h index 7c61c5fc65f..ce757749217 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1,8 +1,8 @@ #ifndef SQL_ITEM_INCLUDED #define SQL_ITEM_INCLUDED -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013 Monty Program Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, 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 @@ -3735,13 +3735,16 @@ class Item_direct_view_ref :public Item_direct_ref #define NO_NULL_TABLE (reinterpret_cast<TABLE *>(0x1)) + void set_null_ref_table() + { + if (!view->is_inner_table_of_outer_join() || + !(null_ref_table= view->get_real_join_table())) + null_ref_table= NO_NULL_TABLE; + } + bool check_null_ref() { - if (null_ref_table == NULL) - { - if (!(null_ref_table= view->get_real_join_table())) - null_ref_table= NO_NULL_TABLE; - } + DBUG_ASSERT(null_ref_table); if (null_ref_table != NO_NULL_TABLE && null_ref_table->null_row) { null_value= 1; @@ -3749,6 +3752,7 @@ class Item_direct_view_ref :public Item_direct_ref } return FALSE; } + public: Item_direct_view_ref(Name_resolution_context *context_arg, Item **item, const char *table_name_arg, @@ -3756,7 +3760,11 @@ public: TABLE_LIST *view_arg) :Item_direct_ref(context_arg, item, table_name_arg, field_name_arg), item_equal(0), view(view_arg), - null_ref_table(NULL) {} + null_ref_table(NULL) + { + if (fixed) + set_null_ref_table(); + } bool fix_fields(THD *, Item **); bool eq(const Item *item, bool binary_cmp) const; @@ -3774,7 +3782,9 @@ public: Item *equal_fields_propagator(uchar *arg); Item *replace_equal_field(uchar *arg); table_map used_tables() const; + void update_used_tables(); table_map not_null_tables() const; + bool const_item() const { return used_tables() == 0; } bool walk(Item_processor processor, bool walk_subquery, uchar *arg) { return (*ref)->walk(processor, walk_subquery, arg) || diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 6d52661e5c9..94be38e26ee 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -2,7 +2,7 @@ #define ITEM_GEOFUNC_INCLUDED /* Copyright (c) 2000, 2010 Oracle and/or its affiliates. - Copyright (C) 2011 Monty Program Ab. + Copyright (C) 2011, 2015 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 @@ -116,7 +116,7 @@ class Item_func_point: public Item_geometry_func public: Item_func_point(Item *a, Item *b): Item_geometry_func(a, b) {} Item_func_point(Item *a, Item *b, Item *srid): Item_geometry_func(a, b, srid) {} - const char *func_name() const { return "st_point"; } + const char *func_name() const { return "point"; } String *val_str(String *); Field::geometry_type get_geometry_type() const; }; diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 8377a20e0a4..2886cb68f9b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -3,7 +3,7 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. + Copyright (c) 2009, 2015, 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 @@ -937,7 +937,6 @@ public: Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) :Item_str_func(a) { - DBUG_ASSERT(args[0]->fixed); conv_charset= cs; if (cache_if_const && args[0]->const_item() && !args[0]->is_expensive()) { diff --git a/sql/lex.h b/sql/lex.h index 10a52160cf0..a272504c0f2 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -1,7 +1,8 @@ #ifndef LEX_INCLUDED #define LEX_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, 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 @@ -389,6 +390,7 @@ static SYMBOL symbols[] = { { "MULTIPOINT", SYM(MULTIPOINT)}, { "MULTIPOLYGON", SYM(MULTIPOLYGON)}, { "MUTEX", SYM(MUTEX_SYM)}, + { "MYSQL", SYM(MYSQL_SYM)}, { "MYSQL_ERRNO", SYM(MYSQL_ERRNO_SYM)}, { "NAME", SYM(NAME_SYM)}, { "NAMES", SYM(NAMES_SYM)}, diff --git a/sql/log.cc b/sql/log.cc index 850b685be83..99d3fb69b18 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. + Copyright (c) 2009, 2015, 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 @@ -2493,6 +2493,8 @@ bool MYSQL_LOG::open( char buff[FN_REFLEN]; MY_STAT f_stat; File file= -1; + my_off_t seek_offset; + bool is_fifo = false; int open_flags= O_CREAT | O_BINARY; DBUG_ENTER("MYSQL_LOG::open"); DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg)); @@ -2509,15 +2511,17 @@ bool MYSQL_LOG::open( log_type_arg, io_cache_type_arg)) goto err; - /* File is regular writable file */ - if (my_stat(log_file_name, &f_stat, MYF(0)) && !MY_S_ISREG(f_stat.st_mode)) - goto err; + is_fifo = my_stat(log_file_name, &f_stat, MYF(0)) && + MY_S_ISFIFO(f_stat.st_mode); if (io_cache_type == SEQ_READ_APPEND) open_flags |= O_RDWR | O_APPEND; else open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND); + if (is_fifo) + open_flags |= O_NONBLOCK; + db[0]= 0; #ifdef HAVE_PSI_INTERFACE @@ -2525,11 +2529,16 @@ bool MYSQL_LOG::open( m_log_file_key= log_file_key; #endif - if ((file= mysql_file_open(log_file_key, - log_file_name, open_flags, - MYF(MY_WME | ME_WAITTANG))) < 0 || - init_io_cache(&log_file, file, IO_SIZE, io_cache_type, - mysql_file_tell(file, MYF(MY_WME)), 0, + if ((file= mysql_file_open(log_file_key, log_file_name, open_flags, + MYF(MY_WME | ME_WAITTANG))) < 0) + goto err; + + if (is_fifo) + seek_offset= 0; + else if ((seek_offset= mysql_file_tell(file, MYF(MY_WME)))) + goto err; + + if (init_io_cache(&log_file, file, IO_SIZE, io_cache_type, seek_offset, 0, MYF(MY_WME | MY_NABP | ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0)))) goto err; @@ -2618,17 +2627,17 @@ void MYSQL_LOG::close(uint exiting) { end_io_cache(&log_file); - if (mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) + if (log_type == LOG_BIN && mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno); } if (!(exiting & LOG_CLOSE_DELAYED_CLOSE) && mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error) { write_error= 1; - sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno); + sql_print_error(ER_THD_OR_DEFAULT(current_thd, ER_ERROR_ON_WRITE), name, errno); } } @@ -6665,6 +6674,10 @@ bool MYSQL_BIN_LOG::write_incident(THD *thd) if (check_purge) checkpoint_and_purge(prev_binlog_id); } + else + { + mysql_mutex_unlock(&LOCK_log); + } DBUG_RETURN(error); } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1df6622b9e7..2eaf8096795 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2008, 2014, SkySQL Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2008, 2015, 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 @@ -2251,7 +2251,8 @@ static struct passwd *check_user(const char *user) { if (!opt_bootstrap && !opt_help) { - sql_print_error("Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n"); + sql_print_error("Fatal error: Please consult the Knowledge Base " + "to find out how to run mysqld as root!\n"); unireg_abort(1); } return NULL; @@ -4068,6 +4069,10 @@ static int init_common_variables() return 1; set_server_version(); + if (!opt_help) + sql_print_information("%s (mysqld %s) starting as process %lu ...", + my_progname, server_version, (ulong) getpid()); + #ifndef EMBEDDED_LIBRARY if (opt_abort && !opt_verbose) unireg_abort(0); diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 2122349f324..0ad90e2ef3d 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -1,5 +1,5 @@ /* - Copyright (c) 2010, 2012, Monty Program Ab + Copyright (c) 2010, 2015, 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 @@ -1611,9 +1611,20 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) sj_nest->sj_on_expr= and_items(sj_nest->sj_on_expr, item_eq); } } - /* Fix the created equality and AND */ - if (!sj_nest->sj_on_expr->fixed) - sj_nest->sj_on_expr->fix_fields(parent_join->thd, &sj_nest->sj_on_expr); + /* + Fix the created equality and AND + + Note that fix_fields() can actually fail in a meaningful way here. One + example is when the IN-equality is not valid, because it compares columns + with incompatible collations. (One can argue it would be more appropriate + to check for this at name resolution stage, but as a legacy of IN->EXISTS + we have in here). + */ + if (!sj_nest->sj_on_expr->fixed && + sj_nest->sj_on_expr->fix_fields(parent_join->thd, &sj_nest->sj_on_expr)) + { + DBUG_RETURN(TRUE); + } /* Walk through sj nest's WHERE and ON expressions and call @@ -1632,12 +1643,15 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) /* Inject sj_on_expr into the parent's WHERE or ON */ if (emb_tbl_nest) { - emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr, + emb_tbl_nest->on_expr= and_items(emb_tbl_nest->on_expr, sj_nest->sj_on_expr); emb_tbl_nest->on_expr->top_level_item(); - if (!emb_tbl_nest->on_expr->fixed) - emb_tbl_nest->on_expr->fix_fields(parent_join->thd, - &emb_tbl_nest->on_expr); + if (!emb_tbl_nest->on_expr->fixed && + emb_tbl_nest->on_expr->fix_fields(parent_join->thd, + &emb_tbl_nest->on_expr)) + { + DBUG_RETURN(TRUE); + } } else { @@ -1650,8 +1664,12 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred) */ save_lex= thd->lex->current_select; thd->lex->current_select=parent_join->select_lex; - if (!parent_join->conds->fixed) - parent_join->conds->fix_fields(parent_join->thd, &parent_join->conds); + if (!parent_join->conds->fixed && + parent_join->conds->fix_fields(parent_join->thd, + &parent_join->conds)) + { + DBUG_RETURN(1); + } thd->lex->current_select=save_lex; parent_join->select_lex->where= parent_join->conds; } @@ -2508,10 +2526,16 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, LooseScan detector in best_access_path) */ remaining_tables &= ~new_join_tab->table->map; - pos->prefix_dups_producing_tables= join->cur_dups_producing_tables; + table_map dups_producing_tables; + + if (idx == join->const_tables) + dups_producing_tables= 0; + else + dups_producing_tables= pos[-1].dups_producing_tables; + TABLE_LIST *emb_sj_nest; if ((emb_sj_nest= new_join_tab->emb_sj_nest)) - join->cur_dups_producing_tables |= emb_sj_nest->sj_inner_tables; + dups_producing_tables |= emb_sj_nest->sj_inner_tables; Semi_join_strategy_picker **strategy; if (idx == join->const_tables) @@ -2564,7 +2588,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, fanout from semijoin X. 3. We have no clue what to do about fanount of semi-join Y. */ - if ((join->cur_dups_producing_tables & handled_fanout) || + if ((dups_producing_tables & handled_fanout) || (read_time < *current_read_time && !(handled_fanout & pos->inner_tables_handled_with_other_sjs))) { @@ -2577,7 +2601,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, join->sjm_lookup_tables &= ~handled_fanout; *current_read_time= read_time; *current_record_count= rec_count; - join->cur_dups_producing_tables &= ~handled_fanout; + dups_producing_tables &= ~handled_fanout; //TODO: update bitmap of semi-joins that were handled together with // others. if (is_multiple_semi_joins(join, join->positions, idx, handled_fanout)) @@ -2604,6 +2628,7 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, pos->prefix_cost.convert_from_cost(*current_read_time); pos->prefix_record_count= *current_record_count; + pos->dups_producing_tables= dups_producing_tables; } @@ -3115,8 +3140,6 @@ void restore_prev_sj_state(const table_map remaining_tables, tab->join->cur_sj_inner_tables &= ~emb_sj_nest->sj_inner_tables; } } - POSITION *pos= tab->join->positions + idx; - tab->join->cur_dups_producing_tables= pos->prefix_dups_producing_tables; } diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h index acfbebed6b3..3da94d05521 100644 --- a/sql/opt_subselect.h +++ b/sql/opt_subselect.h @@ -1,5 +1,5 @@ /* - Copyright (c) 2010, 2012, Monty Program Ab + Copyright (c) 2010, 2015, 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 @@ -299,7 +299,7 @@ public: }; -extern void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, +void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx, double *current_record_count, double *current_read_time, POSITION *loose_scan_pos); void restore_prev_sj_state(const table_map remaining_tables, diff --git a/sql/slave.cc b/sql/slave.cc index 896270acf36..30d55f8bc2a 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2014, SkySQL Ab. +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2008, 2015, 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 @@ -6061,7 +6061,23 @@ static int connect_to_master(THD* thd, MYSQL* mysql, Master_info* mi, } #endif - mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname); + /* + If server's default charset is not supported (like utf16, utf32) as client + charset, then set client charset to 'latin1' (default client charset). + */ + if (is_supported_parser_charset(default_charset_info)) + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset_info->csname); + else + { + sql_print_information("'%s' can not be used as client character set. " + "'%s' will be used as default client character set " + "while connecting to master.", + default_charset_info->csname, + default_client_charset_info->csname); + mysql_options(mysql, MYSQL_SET_CHARSET_NAME, + default_client_charset_info->csname); + } + /* This one is not strictly needed but we have it here for completeness */ mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir); diff --git a/sql/sp.cc b/sql/sp.cc index 35155cf031a..334b5e12ba3 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -1,5 +1,6 @@ /* - Copyright (c) 2002, 2011, Oracle and/or its affiliates. + Copyright (c) 2002, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, 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 @@ -1476,6 +1477,9 @@ bool lock_db_routines(THD *thd, char *db) { char *sp_name= get_field(thd->mem_root, table->field[MYSQL_PROC_FIELD_NAME]); + if (sp_name == NULL) // skip invalid sp names (hand-edited mysql.proc?) + continue; + longlong sp_type= table->field[MYSQL_PROC_MYSQL_TYPE]->val_int(); MDL_request *mdl_request= new (thd->mem_root) MDL_request; mdl_request->init(sp_type == TYPE_ENUM_FUNCTION ? diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index ce8302af0b3..afce7794dd7 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2010, 2014, Oracle and/or its affiliates. - Copyright (c) 2012, 2014, Monty Program Ab. + Copyright (c) 2012, 2015, 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 @@ -309,7 +309,8 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT *), int (handler::*operator_func)(THD *, HA_CHECK_OPT *), - int (view_operator_func)(THD *, TABLE_LIST*)) + int (view_operator_func)(THD *, TABLE_LIST*, + HA_CHECK_OPT *)) { TABLE_LIST *table; SELECT_LEX *select= &thd->lex->select_lex; @@ -393,7 +394,18 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, lex->query_tables_own_last= 0; if (view_operator_func == NULL) + { table->required_type=FRMTYPE_TABLE; + DBUG_ASSERT(!lex->only_view); + } + else if (lex->only_view) + { + table->required_type= FRMTYPE_VIEW; + } + else if (!lex->only_view && lex->sql_command == SQLCOM_REPAIR) + { + table->required_type= FRMTYPE_TABLE; + } if (lex->sql_command == SQLCOM_CHECK || lex->sql_command == SQLCOM_REPAIR || @@ -521,9 +533,9 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, } /* - CHECK TABLE command is only command where VIEW allowed here and this - command use only temporary teble method for VIEWs resolving => there - can't be VIEW tree substitition of join view => if opening table + CHECK/REPAIR TABLE command is only command where VIEW allowed here and + this command use only temporary table method for VIEWs resolving => + there can't be VIEW tree substitition of join view => if opening table succeed then table->table will have real TABLE pointer as value (in case of join view substitution table->table can be 0, but here it is impossible) @@ -536,7 +548,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE)); /* if it was a view will check md5 sum */ if (table->view && - view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM) + view_check(thd, table, check_opt) == HA_ADMIN_WRONG_CHECKSUM) push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM)); if (thd->get_stmt_da()->is_error() && @@ -551,7 +563,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (table->view) { DBUG_PRINT("admin", ("calling view_operator_func")); - result_code= (*view_operator_func)(thd, table); + result_code= (*view_operator_func)(thd, table, check_opt); goto send_result; } @@ -968,7 +980,16 @@ send_result_message: size_t length; protocol->store(STRING_WITH_LEN("error"), system_charset_info); - if (table->table->file->ha_table_flags() & HA_CAN_REPAIR) +#if MYSQL_VERSION_ID > 100104 +#error fix the error message to take TABLE or VIEW as an argument +#else + if (table->view) + length= my_snprintf(buf, sizeof(buf), + "Upgrade required. Please do \"REPAIR VIEW %`s\" or dump/reload to fix it!", + table->table_name); + else +#endif + if (table->table->file->ha_table_flags() & HA_CAN_REPAIR || table->view) length= my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE), table->table_name); else @@ -1189,7 +1210,7 @@ bool Sql_cmd_check_table::execute(THD *thd) res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "check", lock_type, 0, 0, HA_OPEN_FOR_REPAIR, 0, - &handler::ha_check, &view_checksum); + &handler::ha_check, &view_check); m_lex->select_lex.table_list.first= first_table; m_lex->query_tables= first_table; @@ -1246,7 +1267,7 @@ bool Sql_cmd_repair_table::execute(THD *thd) TL_WRITE, 1, MY_TEST(m_lex->check_opt.sql_flags & TT_USEFRM), HA_OPEN_FOR_REPAIR, &prepare_for_repair, - &handler::ha_repair, 0); + &handler::ha_repair, &view_repair); /* ! we write after unlocking the table */ if (!res && !m_lex->no_write_to_binlog) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f337b3b6283..3731c646b20 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2010, 2013 Monty Program Ab +/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2010, 2015, 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 @@ -3456,7 +3456,7 @@ request_backoff_action(enum_open_table_action action_arg, if (action_arg != OT_REOPEN_TABLES && m_has_locks) { my_error(ER_LOCK_DEADLOCK, MYF(0)); - mark_transaction_to_rollback(m_thd, true); + m_thd->mark_transaction_to_rollback(true); return TRUE; } /* @@ -6985,7 +6985,7 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter, Item_field for tables. */ Item_ident *item_ref= (Item_ident *) item; - if (item_ref->name && item_ref->table_name && + if (field_name && item_ref->name && item_ref->table_name && !my_strcasecmp(system_charset_info, item_ref->name, field_name) && !my_strcasecmp(table_alias_charset, item_ref->table_name, table_name) && diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 8c52d5dd92d..1ef0827b943 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2014, SkySQL Ab. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2008, 2015, 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 @@ -881,7 +881,7 @@ THD::THD() failed_com_change_user(0), is_fatal_error(0), transaction_rollback_request(0), - is_fatal_sub_stmt_error(0), + is_fatal_sub_stmt_error(false), rand_used(0), time_zone_used(0), in_lock_tables(0), @@ -1520,6 +1520,7 @@ void THD::cleanup(void) mysql_ha_cleanup(this); locked_tables_list.unlock_locked_tables(this); + delete_dynamic(&user_var_events); close_temporary_tables(this); transaction.xid_state.xa_state= XA_NOTR; @@ -1551,7 +1552,6 @@ void THD::cleanup(void) debug_sync_end_thread(this); #endif /* defined(ENABLED_DEBUG_SYNC) */ - delete_dynamic(&user_var_events); my_hash_free(&user_vars); sp_cache_clear(&sp_proc_cache); sp_cache_clear(&sp_func_cache); @@ -4450,7 +4450,8 @@ extern "C" int thd_binlog_format(const MYSQL_THD thd) extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all) { - mark_transaction_to_rollback(thd, all); + DBUG_ASSERT(thd); + thd->mark_transaction_to_rollback(all); } extern "C" bool thd_binlog_filter_ok(const MYSQL_THD thd) @@ -4691,9 +4692,12 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) If we've left sub-statement mode, reset the fatal error flag. Otherwise keep the current value, to propagate it up the sub-statement stack. + + NOTE: is_fatal_sub_stmt_error can be set only if we've been in the + sub-statement mode. */ if (!in_sub_stmt) - is_fatal_sub_stmt_error= FALSE; + is_fatal_sub_stmt_error= false; if ((variables.option_bits & OPTION_BIN_LOG) && is_update_query(lex->sql_command) && !is_current_stmt_binlog_format_row()) @@ -4935,17 +4939,18 @@ void THD::get_definer(LEX_USER *definer, bool role) /** Mark transaction to rollback and mark error as fatal to a sub-statement. - @param thd Thread handle @param all TRUE <=> rollback main transaction. */ -void mark_transaction_to_rollback(THD *thd, bool all) +void THD::mark_transaction_to_rollback(bool all) { - if (thd) - { - thd->is_fatal_sub_stmt_error= TRUE; - thd->transaction_rollback_request= all; - } + /* + There is no point in setting is_fatal_sub_stmt_error unless + we are actually in_sub_stmt. + */ + if (in_sub_stmt) + is_fatal_sub_stmt_error= true; + transaction_rollback_request= all; } /*************************************************************************** Handling of XA id cacheing diff --git a/sql/sql_class.h b/sql/sql_class.h index 38e3a383208..0746ac79b97 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. +/* + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2009, 2015, 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 @@ -772,9 +773,6 @@ void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var); void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, STATUS_VAR *dec_var); -void mark_transaction_to_rollback(THD *thd, bool all); - - /** Get collation by name, send error to client on failure. @param name Collation name @@ -802,7 +800,6 @@ mysqld_collation_get_by_name(const char *name, return cs; } - #ifdef MYSQL_SERVER void free_tmp_table(THD *thd, TABLE *entry); @@ -3113,6 +3110,8 @@ public: if (get_stmt_da()->is_error()) get_stmt_da()->reset_diagnostics_area(); is_slave_error= 0; + if (killed == KILL_BAD_DATA) + killed= NOT_KILLED; // KILL_BAD_DATA can be reset w/o a mutex DBUG_VOID_RETURN; } #ifndef EMBEDDED_LIBRARY @@ -3704,6 +3703,7 @@ public: wait_for_commit_ptr= suspended; } + void mark_transaction_to_rollback(bool all); private: /** The current internal error handler for this thread, or NULL. */ @@ -4885,8 +4885,6 @@ public: */ #define CF_SKIP_QUESTIONS (1U << 1) -void mark_transaction_to_rollback(THD *thd, bool all); - /* Inline functions */ inline bool add_item_to_list(THD *thd, Item *item) diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 99b44e6008c..5292b964576 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2010, 2015, 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 @@ -850,7 +851,7 @@ int mysql_multi_delete_prepare(THD *thd) */ lex->select_lex.exclude_from_table_unique_test= FALSE; - if (lex->select_lex.save_prep_leaf_tables(thd)) + if (lex->save_prep_leaf_tables()) DBUG_RETURN(TRUE); DBUG_RETURN(FALSE); diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index c68e7f490cc..fdc615d0fae 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2002, 2011, Oracle and/or its affiliates. + Copyright (c) 2010, 2015, 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 @@ -169,7 +170,9 @@ mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases) uint8 allowed_phases= (derived->is_merged_derived() ? DT_PHASES_MERGE : DT_PHASES_MATERIALIZE); DBUG_ENTER("mysql_handle_single_derived"); - DBUG_PRINT("enter", ("phases: 0x%x allowed: 0x%x", phases, allowed_phases)); + DBUG_PRINT("enter", ("phases: 0x%x allowed: 0x%x alias: '%s'", + phases, allowed_phases, + (derived->alias ? derived->alias : "<NULL>"))); if (!lex->derived_tables) DBUG_RETURN(FALSE); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 697988a6bf8..ba7d101a4cd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, Monty Program Ab. + Copyright (c) 2009, 2015, 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 @@ -4113,27 +4113,48 @@ bool st_select_lex::save_leaf_tables(THD *thd) } -bool st_select_lex::save_prep_leaf_tables(THD *thd) +bool LEX::save_prep_leaf_tables() { if (!thd->save_prep_leaf_list) - return 0; + return FALSE; Query_arena *arena= thd->stmt_arena, backup; arena= thd->activate_stmt_arena_if_needed(&backup); + //It is used for DETETE/UPDATE so top level has only one SELECT + DBUG_ASSERT(select_lex.next_select() == NULL); + bool res= select_lex.save_prep_leaf_tables(thd); + + if (arena) + thd->restore_active_arena(arena, &backup); + + if (res) + return TRUE; + thd->save_prep_leaf_list= FALSE; + return FALSE; +} + + +bool st_select_lex::save_prep_leaf_tables(THD *thd) +{ List_iterator_fast<TABLE_LIST> li(leaf_tables); TABLE_LIST *table; while ((table= li++)) { if (leaf_tables_prep.push_back(table)) - return 1; + return TRUE; + } + is_prep_leaf_list_saved= TRUE; + for (SELECT_LEX_UNIT *u= first_inner_unit(); u; u= u->next_unit()) + { + for (SELECT_LEX *sl= u->first_select(); sl; sl= sl->next_select()) + { + if (sl->save_prep_leaf_tables(thd)) + return TRUE; + } } - thd->lex->select_lex.is_prep_leaf_list_saved= TRUE; - thd->save_prep_leaf_list= FALSE; - if (arena) - thd->restore_active_arena(arena, &backup); - return 0; + return FALSE; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 88491743d39..38f1417b40c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2014, Monty Program Ab. + Copyright (c) 2010, 2015, 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 @@ -2743,6 +2743,8 @@ struct LEX: public Query_tables_list return FALSE; } + bool save_prep_leaf_tables(); + int print_explain(select_result_sink *output, uint8 explain_flags, bool *printed_anything); }; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index eb222b2f95a..2aeddf2415d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2000, 2014 Oracle and/or its affiliates. +/* Copyright (c) 2000, 2015 Oracle and/or its affiliates. Copyright (c) 2009, 2015 MariaDB This program is free software; you can redistribute it and/or modify @@ -709,9 +709,7 @@ JOIN::prepare(Item ***rref_pointer_array, if (!(select_options & OPTION_SETUP_TABLES_DONE) && setup_tables_and_check_access(thd, &select_lex->context, join_list, tables_list, select_lex->leaf_tables, - FALSE, SELECT_ACL, SELECT_ACL, - (thd->lex->sql_command == - SQLCOM_UPDATE_MULTI))) + FALSE, SELECT_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(-1); /* @@ -6466,7 +6464,6 @@ choose_plan(JOIN *join, table_map join_tables) DBUG_ENTER("choose_plan"); join->cur_embedding_map= 0; - join->cur_dups_producing_tables= 0; reset_nj_counters(join, join->join_list); qsort2_cmp jtab_sort_func; @@ -21149,18 +21146,33 @@ SORT_FIELD *make_unireg_sortorder(ORDER *order, uint *length, for (;order;order=order->next,pos++) { - Item *item= order->item[0]->real_item(); + Item *const item= order->item[0], *const real_item= item->real_item(); pos->field= 0; pos->item= 0; - if (item->type() == Item::FIELD_ITEM) - pos->field= ((Item_field*) item)->field; - else if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item()) - pos->field= ((Item_sum*) item)->get_tmp_table_field(); - else if (item->type() == Item::COPY_STR_ITEM) - { // Blob patch - pos->item= ((Item_copy*) item)->get_item(); + if (real_item->type() == Item::FIELD_ITEM) + { + // Could be a field, or Item_direct_view_ref wrapping a field + DBUG_ASSERT(item->type() == Item::FIELD_ITEM || + (item->type() == Item::REF_ITEM && + static_cast<Item_ref*>(item)->ref_type() == + Item_ref::VIEW_REF)); + pos->field= static_cast<Item_field*>(real_item)->field; + } + else if (real_item->type() == Item::SUM_FUNC_ITEM && + !real_item->const_item()) + { + // Aggregate, or Item_aggregate_ref + DBUG_ASSERT(item->type() == Item::SUM_FUNC_ITEM || + (item->type() == Item::REF_ITEM && + static_cast<Item_ref*>(item)->ref_type() == + Item_ref::AGGREGATE_REF)); + pos->field= item->get_tmp_table_field(); + } + else if (real_item->type() == Item::COPY_STR_ITEM) + { // Blob patch + pos->item= static_cast<Item_copy*>(real_item)->get_item(); } else - pos->item= *order->item; + pos->item= item; pos->reverse=! order->asc; DBUG_ASSERT(pos->field != NULL || pos->item != NULL); } @@ -21404,6 +21416,17 @@ find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, uint el= all_fields.elements; all_fields.push_front(order_item); /* Add new field to field list. */ ref_pointer_array[el]= order_item; + /* + If the order_item is a SUM_FUNC_ITEM, when fix_fields is called + ref_by is set to order->item which is the address of order_item. + But this needs to be address of order_item in the all_fields list. + As a result, when it gets replaced with Item_aggregate_ref + object in Item::split_sum_func2, we will be able to retrieve the + newly created object. + */ + if (order_item->type() == Item::SUM_FUNC_ITEM) + ((Item_sum *)order_item)->ref_by= all_fields.head_ref(); + order->item= ref_pointer_array + el; return FALSE; } diff --git a/sql/sql_select.h b/sql/sql_select.h index 45041def28f..5aa29715dc3 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -2,7 +2,7 @@ #define SQL_SELECT_INCLUDED /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2008, 2013, Monty Program Ab. + Copyright (c) 2008, 2015, 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 @@ -825,7 +825,12 @@ typedef struct st_position :public Sql_alloc */ uint n_sj_tables; - table_map prefix_dups_producing_tables; + /* + Bitmap of semi-join inner tables that are in the join prefix and for + which there's no provision for how to eliminate semi-join duplicates + they produce. + */ + table_map dups_producing_tables; table_map inner_tables_handled_with_other_sjs; @@ -1046,13 +1051,6 @@ public: */ table_map cur_sj_inner_tables; - /* - Bitmap of semi-join inner tables that are in the join prefix and for - which there's no provision for how to eliminate semi-join duplicates - they produce. - */ - table_map cur_dups_producing_tables; - /* We also maintain a stack of join optimization states in * join->positions[] */ /******* Join optimization state members end *******/ diff --git a/sql/sql_table.cc b/sql/sql_table.cc index df71140bc1d..817ab6e8967 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2014, SkySQL Ab. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2010, 2015, 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 @@ -28,7 +28,6 @@ #include "sql_base.h" // open_table_uncached, lock_table_names #include "lock.h" // mysql_unlock_tables #include "strfunc.h" // find_type2, find_set -#include "sql_view.h" // view_checksum #include "sql_truncate.h" // regenerate_locked_table #include "sql_partition.h" // mem_alloc_error, // generate_partition_syntax, diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index fe2ea02a8e2..05869b70c8f 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2010, 2014, Oracle and/or its affiliates. - Copyright (c) 2013, 2014, SkySQL Ab. +/* Copyright (c) 2010, 2015, Oracle and/or its affiliates. + Copyright (c) 2013, 2015, 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 @@ -283,6 +283,12 @@ static bool recreate_temporary_table(THD *thd, TABLE *table) table->file->info(HA_STATUS_AUTO | HA_STATUS_NO_LOCK); + /* + If LOCK TABLES list is not empty and contains this table + then unlock the table and remove it from this list. + */ + mysql_lock_remove(thd, thd->lock, table); + /* Don't free share. */ close_temporary_table(thd, table, FALSE, FALSE); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 6c4d864e75a..f616549097b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2011, 2013, Monty Program Ab. + Copyright (c) 2011, 2015, 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 @@ -1520,7 +1520,7 @@ int mysql_multi_update_prepare(THD *thd) */ lex->select_lex.exclude_from_table_unique_test= FALSE; - if (lex->select_lex.save_prep_leaf_tables(thd)) + if (lex->save_prep_leaf_tables()) DBUG_RETURN(TRUE); DBUG_RETURN (FALSE); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index be31a7df3f6..41647a7262f 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2004, 2013, Oracle and/or its affiliates. - Copyright (c) 2011, 2014, SkySQL Ab. + Copyright (c) 2011, 2015, 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 @@ -685,6 +685,26 @@ err: } +static void make_view_filename(LEX_STRING *dir, char *dir_buff, + size_t dir_buff_len, + LEX_STRING *path, char *path_buff, + size_t path_buff_len, + LEX_STRING *file, + TABLE_LIST *view) +{ + /* print file name */ + dir->length= build_table_filename(dir_buff, dir_buff_len - 1, + view->db, "", "", 0); + dir->str= dir_buff; + + path->length= build_table_filename(path_buff, path_buff_len - 1, + view->db, view->table_name, reg_ext, 0); + path->str= path_buff; + + file->str= path->str + dir->length; + file->length= path->length - dir->length; +} + /* number of required parameters for making view */ static const int required_view_parameters= 15; @@ -747,6 +767,67 @@ static File_option view_parameters[]= static LEX_STRING view_file_type[]= {{(char*) STRING_WITH_LEN("VIEW") }}; +int mariadb_fix_view(THD *thd, TABLE_LIST *view, bool wrong_checksum, + bool swap_alg) +{ + char dir_buff[FN_REFLEN + 1], path_buff[FN_REFLEN + 1]; + LEX_STRING dir, file, path; + DBUG_ENTER("mariadb_fix_view"); + + if (!wrong_checksum && view->mariadb_version) + DBUG_RETURN(HA_ADMIN_OK); + + make_view_filename(&dir, dir_buff, sizeof(dir_buff), + &path, path_buff, sizeof(path_buff), + &file, view); + /* init timestamp */ + if (!view->timestamp.str) + view->timestamp.str= view->timestamp_buffer; + + if (swap_alg && view->algorithm != VIEW_ALGORITHM_UNDEFINED) + { + DBUG_ASSERT(view->algorithm == VIEW_ALGORITHM_MERGE || + view->algorithm == VIEW_ALGORITHM_TMPTABLE); + if (view->algorithm == VIEW_ALGORITHM_MERGE) + view->algorithm= VIEW_ALGORITHM_TMPTABLE; + else + view->algorithm= VIEW_ALGORITHM_MERGE; + } + else + swap_alg= 0; + if (wrong_checksum) + { + if (view->md5.length != 32) + { + if ((view->md5.str= (char *)thd->alloc(32 + 1)) == NULL) + DBUG_RETURN(HA_ADMIN_FAILED); + } + view->calc_md5(view->md5.str); + view->md5.length= 32; + } + view->mariadb_version= MYSQL_VERSION_ID; + + if (sql_create_definition_file(&dir, &file, view_file_type, + (uchar*)view, view_parameters)) + { + sql_print_error("View '%-.192s'.'%-.192s': algorithm swap error.", + view->db, view->table_name); + DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); + } + sql_print_information("View %`s.%`s: the version is set to %llu%s%s", + view->db, view->table_name, view->mariadb_version, + (wrong_checksum ? ", checksum corrected" : ""), + (swap_alg ? + ((view->algorithm == VIEW_ALGORITHM_MERGE) ? + ", algorithm restored to be MERGE" + : ", algorithm restored to be TEMPTABLE") + : "")); + + + DBUG_RETURN(HA_ADMIN_OK); +} + + /* Register VIEW (write .frm & process .frm's history backups) @@ -887,17 +968,9 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, } loop_out: /* print file name */ - dir.length= build_table_filename(dir_buff, sizeof(dir_buff) - 1, - view->db, "", "", 0); - dir.str= dir_buff; - - path.length= build_table_filename(path_buff, sizeof(path_buff) - 1, - view->db, view->table_name, reg_ext, 0); - path.str= path_buff; - - file.str= path.str + dir.length; - file.length= path.length - dir.length; - + make_view_filename(&dir, dir_buff, sizeof(dir_buff), + &path, path_buff, sizeof(path_buff), + &file, view); /* init timestamp */ if (!view->timestamp.str) view->timestamp.str= view->timestamp_buffer; @@ -1023,7 +1096,7 @@ err: SYNOPSIS mysql_make_view() - thd Thread handler + thd Thread handle parser parser object table TABLE_LIST structure for filling flags flags @@ -1609,7 +1682,7 @@ err: SYNOPSIS mysql_drop_view() - thd - thread handler + thd - thread handle views - views to delete drop_mode - cascade/check @@ -1726,7 +1799,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) SYNOPSIS check_key_in_view() - thd thread handler + thd thread handle view view for check with opened table DESCRIPTION @@ -1912,6 +1985,58 @@ int view_checksum(THD *thd, TABLE_LIST *view) HA_ADMIN_OK); } +/** + Check view + + @param thd thread handle + @param view view for check + @param check_opt check options + + @retval HA_ADMIN_OK OK + @retval HA_ADMIN_NOT_IMPLEMENTED it is not VIEW + @retval HA_ADMIN_WRONG_CHECKSUM check sum is wrong +*/ +int view_check(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt) +{ + DBUG_ENTER("view_check"); + + int res= view_checksum(thd, view); + if (res != HA_ADMIN_OK) + DBUG_RETURN(res); + + if (((check_opt->sql_flags & TT_FOR_UPGRADE) && !view->mariadb_version)) + DBUG_RETURN(HA_ADMIN_NEEDS_UPGRADE); + + DBUG_RETURN(HA_ADMIN_OK); +} + + +/** + Repair view + + @param thd thread handle + @param view view for check + @param check_opt check options + + @retval HA_ADMIN_OK OK + @retval HA_ADMIN_NOT_IMPLEMENTED it is not VIEW + @retval HA_ADMIN_WRONG_CHECKSUM check sum is wrong +*/ + +int view_repair(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt) +{ + DBUG_ENTER("view_repair"); + bool swap_alg= (check_opt->sql_flags & TT_FROM_MYSQL); + bool wrong_checksum= view_checksum(thd, view) != HA_ADMIN_OK; + int ret; + if (wrong_checksum || swap_alg || (!view->mariadb_version)) + { + ret= mariadb_fix_view(thd, view, wrong_checksum, swap_alg); + DBUG_RETURN(ret); + } + DBUG_RETURN(HA_ADMIN_OK); +} + /* rename view diff --git a/sql/sql_view.h b/sql/sql_view.h index abe95c63e6e..8d733a1867c 100644 --- a/sql/sql_view.h +++ b/sql/sql_view.h @@ -2,7 +2,8 @@ #define SQL_VIEW_INCLUDED /* -*- C++ -*- */ -/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. + Copyright (c) 2015, 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 @@ -45,6 +46,8 @@ bool check_key_in_view(THD *thd, TABLE_LIST * view); bool insert_view_fields(THD *thd, List<Item> *list, TABLE_LIST *view); int view_checksum(THD *thd, TABLE_LIST *view); +int view_check(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt); +int view_repair(THD *thd, TABLE_LIST *view, HA_CHECK_OPT *check_opt); extern TYPELIB updatable_views_with_limit_typelib; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a23a88b7559..03022c7ed19 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2010, 2014, Monty Program Ab. + Copyright (c) 2000, 2015, Oracle and/or its affiliates. + Copyright (c) 2010, 2015, 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 @@ -1331,6 +1331,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token MULTIPOINT %token MULTIPOLYGON %token MUTEX_SYM +%token MYSQL_SYM %token MYSQL_ERRNO_SYM %token NAMES_SYM /* SQL-2003-N */ %token NAME_SYM /* SQL-2003-N */ @@ -7018,6 +7019,7 @@ alter: { Lex->name.str= 0; Lex->name.length= 0; + Lex->only_view= FALSE; Lex->sql_command= SQLCOM_ALTER_TABLE; Lex->duplicates= DUP_ERROR; Lex->col_list.empty(); @@ -7910,7 +7912,7 @@ opt_checksum_type: ; repair: - REPAIR opt_no_write_to_binlog table_or_tables + REPAIR opt_no_write_to_binlog table_or_view { LEX *lex=Lex; lex->sql_command = SQLCOM_REPAIR; @@ -7923,6 +7925,15 @@ repair: table_list opt_mi_repair_type { LEX* lex= thd->lex; + if ((lex->only_view && + ((lex->check_opt.flags & (T_QUICK | T_EXTEND)) || + (lex->check_opt.sql_flags & TT_USEFRM))) || + (!lex->only_view && + (lex->check_opt.sql_flags & TT_FROM_MYSQL))) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } DBUG_ASSERT(!lex->m_sql_cmd); lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_repair_table(); if (lex->m_sql_cmd == NULL) @@ -7944,6 +7955,7 @@ mi_repair_type: QUICK { Lex->check_opt.flags|= T_QUICK; } | EXTENDED_SYM { Lex->check_opt.flags|= T_EXTEND; } | USE_FRM { Lex->check_opt.sql_flags|= TT_USEFRM; } + | FROM MYSQL_SYM { Lex->check_opt.sql_flags|= TT_FROM_MYSQL; } ; analyze: @@ -8063,7 +8075,7 @@ binlog_base64_event: ; check: - CHECK_SYM table_or_tables + CHECK_SYM table_or_view { LEX *lex=Lex; @@ -8081,6 +8093,13 @@ check: table_list opt_mi_check_type { LEX* lex= thd->lex; + if (lex->only_view && + (lex->check_opt.flags & (T_QUICK | T_FAST | T_EXTEND | + T_CHECK_ONLY_CHANGED))) + { + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; + } DBUG_ASSERT(!lex->m_sql_cmd); lex->m_sql_cmd= new (thd->mem_root) Sql_cmd_check_table(); if (lex->m_sql_cmd == NULL) @@ -8188,6 +8207,7 @@ keycache: LEX *lex=Lex; lex->sql_command= SQLCOM_ASSIGN_TO_KEYCACHE; lex->ident= $6; + lex->only_view= FALSE; } ; @@ -8232,6 +8252,7 @@ preload: LEX *lex=Lex; lex->sql_command=SQLCOM_PRELOAD_KEYS; lex->alter_info.reset(); + lex->only_view= FALSE; } preload_list_or_parts {} @@ -10093,7 +10114,8 @@ udf_expr: parse it out. If we hijack the input stream with remember_name we may get quoted or escaped names. */ - else if ($2->type() != Item::FIELD_ITEM) + else if ($2->type() != Item::FIELD_ITEM && + $2->type() != Item::REF_ITEM /* For HAVING */ ) $2->set_name($1, (uint) ($3 - $1), thd->charset()); $$= $2; } @@ -14199,6 +14221,7 @@ keyword_sp: | MULTIPOINT {} | MULTIPOLYGON {} | MUTEX_SYM {} + | MYSQL_SYM {} | MYSQL_ERRNO_SYM {} | NAME_SYM {} | NAMES_SYM {} @@ -14827,8 +14850,13 @@ lock: ; table_or_tables: - TABLE_SYM {} - | TABLES {} + TABLE_SYM { Lex->only_view= FALSE; } + | TABLES { Lex->only_view= FALSE; } + ; + +table_or_view: + table_or_tables + | VIEW_SYM { Lex->only_view= TRUE; } ; table_lock_list: @@ -15732,6 +15760,13 @@ subselect_end: */ lex->current_select->select_n_where_fields+= child->select_n_where_fields; + + /* + Aggregate functions in having clause may add fields to an outer + select. Count them also. + */ + lex->current_select->select_n_having_items+= + child->select_n_having_items; } ; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 31bd712ee67..21ea70def63 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -1,5 +1,5 @@ -/* Copyright (c) 2002, 2014, Oracle and/or its affiliates. - Copyright (c) 2012, 2014, SkySQL Ab. +/* Copyright (c) 2002, 2015, Oracle and/or its affiliates. + Copyright (c) 2012, 2015, 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 @@ -2524,7 +2524,7 @@ static Sys_var_ulong Sys_trans_alloc_block_size( "transaction_alloc_block_size", "Allocation block size for transactions to be stored in binary log", SESSION_VAR(trans_alloc_block_size), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1024, UINT_MAX), DEFAULT(QUERY_ALLOC_BLOCK_SIZE), + VALID_RANGE(1024, 128 * 1024 * 1024), DEFAULT(QUERY_ALLOC_BLOCK_SIZE), BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_trans_mem_root)); @@ -2532,7 +2532,7 @@ static Sys_var_ulong Sys_trans_prealloc_size( "transaction_prealloc_size", "Persistent buffer for transactions to be stored in binary log", SESSION_VAR(trans_prealloc_size), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1024, UINT_MAX), DEFAULT(TRANS_ALLOC_PREALLOC_SIZE), + VALID_RANGE(1024, 128 * 1024 * 1024), DEFAULT(TRANS_ALLOC_PREALLOC_SIZE), BLOCK_SIZE(1024), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(fix_trans_mem_root)); diff --git a/sql/table.cc b/sql/table.cc index a9b525bd25f..053269ab435 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -5111,7 +5111,8 @@ TABLE *TABLE_LIST::get_real_join_table() TABLE_LIST *tbl= this; while (tbl->table == NULL || tbl->table->reginfo.join_tab == NULL) { - if (tbl->view == NULL && tbl->derived == NULL) + if ((tbl->view == NULL && tbl->derived == NULL) || + tbl->is_materialized_derived()) break; /* we do not support merging of union yet */ DBUG_ASSERT(tbl->view == NULL || @@ -5120,28 +5121,25 @@ TABLE *TABLE_LIST::get_real_join_table() tbl->derived->first_select()->next_select() == NULL); { - List_iterator_fast<TABLE_LIST> ti; + List_iterator_fast<TABLE_LIST> + ti(tbl->view != NULL ? + tbl->view->select_lex.top_join_list : + tbl->derived->first_select()->top_join_list); + for (;;) { - List_iterator_fast<TABLE_LIST> - ti(tbl->view != NULL ? - tbl->view->select_lex.top_join_list : - tbl->derived->first_select()->top_join_list); - for (;;) - { - tbl= NULL; - /* - Find left table in outer join on this level - (the list is reverted). - */ - for (TABLE_LIST *t= ti++; t; t= ti++) - tbl= t; - if (!tbl) - return NULL; // view/derived with no tables - if (!tbl->nested_join) - break; - /* go deeper if we've found nested join */ - ti= tbl->nested_join->join_list; - } + tbl= NULL; + /* + Find left table in outer join on this level + (the list is reverted). + */ + for (TABLE_LIST *t= ti++; t; t= ti++) + tbl= t; + if (!tbl) + return NULL; // view/derived with no tables + if (!tbl->nested_join) + break; + /* go deeper if we've found nested join */ + ti= tbl->nested_join->join_list; } } } diff --git a/sql/uniques.cc b/sql/uniques.cc index 912a38f8927..c755293035b 100644 --- a/sql/uniques.cc +++ b/sql/uniques.cc @@ -1,4 +1,5 @@ -/* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2001, 2010, Oracle and/or its affiliates. + Copyright (c) 2010, 2015, 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 @@ -100,7 +101,7 @@ Unique::Unique(qsort_cmp2 comp_func, void * comp_func_fixed_arg, max_elements= (ulong) (max_in_memory_size / ALIGN_SIZE(sizeof(TREE_ELEMENT)+size)); (void) open_cached_file(&file, mysql_tmpdir,TEMP_PREFIX, DISK_BUFFER_SIZE, - MYF(MY_WME)); + MYF(MY_WME)); } @@ -641,8 +642,8 @@ bool Unique::walk(TABLE *table, tree_walk_action action, void *walk_action_arg) return 1; if (flush_io_cache(&file) || reinit_io_cache(&file, READ_CACHE, 0L, 0, 0)) return 1; - ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size; - if (!(merge_buffer= (uchar *) my_malloc(buff_sz, MYF(MY_THREAD_SPECIFIC)))) + size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; + if (!(merge_buffer = (uchar *)my_malloc(buff_sz, MYF(MY_THREAD_SPECIFIC|MY_WME)))) return 1; if (buff_sz < full_size * (file_ptrs.elements + 1UL)) res= merge(table, merge_buffer, buff_sz >= full_size * MERGEBUFF2) ; @@ -773,9 +774,8 @@ bool Unique::get(TABLE *table) /* Not enough memory; Save the result to file && free memory used by tree */ if (flush()) return 1; - - ulong buff_sz= (max_in_memory_size / full_size + 1) * full_size; - if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(MY_THREAD_SPECIFIC)))) + size_t buff_sz= (max_in_memory_size / full_size + 1) * full_size; + if (!(sort_buffer= (uchar*) my_malloc(buff_sz, MYF(MY_THREAD_SPECIFIC|MY_WME)))) return 1; if (merge(table, sort_buffer, FALSE)) |