From e46972348a041d1783de56bf4903a2790410e972 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Mon, 5 Mar 2007 11:35:04 +0400 Subject: [PATCH 01/17] bug #25492 (Invalid deallocation in mysql_stmt_fetch()) Additional patch. mysql_flush_use_result() fixed. --- libmysqld/lib_sql.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index 8992bea943b..9ee8d48eec4 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -69,10 +69,14 @@ void embedded_get_error(MYSQL *mysql) static void emb_free_rows(THD *thd) { + if (!thd->data) + return; + if (thd->current_stmt) free_root(&thd->data->alloc,MYF(0)); else free_rows(thd->data); + thd->data= NULL; } @@ -86,11 +90,8 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, THD *thd=(THD *) mysql->thd; NET *net= &mysql->net; - if (thd->data) - { - emb_free_rows(thd); - thd->data= 0; - } + emb_free_rows(thd); + /* Check that we are calling the client functions in right order */ if (mysql->status != MYSQL_STATUS_READY) { @@ -143,13 +144,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command, static void emb_flush_use_result(MYSQL *mysql) { - MYSQL_DATA *data= ((THD*)(mysql->thd))->data; - - if (data) - { - free_rows(data); - ((THD*)(mysql->thd))->data= NULL; - } + emb_free_rows((THD*) (mysql->thd)); } static MYSQL_DATA * @@ -304,8 +299,7 @@ int emb_unbuffered_fetch(MYSQL *mysql, char **row) static void emb_free_embedded_thd(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; - if (thd->data) - emb_free_rows(thd); + emb_free_rows(thd); thread_count--; delete thd; mysql->thd=0; From 28962a76a3a1e9bd91a85ec238f6e6fdca1736a2 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@macbook.local" <> Date: Tue, 20 Mar 2007 19:46:02 +0200 Subject: [PATCH 02/17] Bug #24484: To correctly decide which predicates can be evaluated with a given table the optimizer must know the exact set of tables that a predicate depends on. If that mask is too wide (refer to non-existing tables) the optimizer can erroneously skip a predicate. One such case of wrong table usage mask were the aggregate functions. The have a all-1 mask (meaning depend on all tables, including non-existent ones). Fixed by making a real used_tables mask for the aggregates. The mask is constructed in the following way : 1. OR the table dependency masks of all the arguments of the aggregate. 2. If all the arguments of the function are from the local name resolution context and it is evaluated in the same name resolution context where it is referenced all the tables from that name resolution context are OR-ed to the dependency mask. This is to denote that an aggregate function depends on the number of rows it processes. 3. Handle correctly the case of an aggregate function optimization (such that the aggregate function can be pre-calculated and made a constant). Made sure that an aggregate function is never a constant (unless subject of a specific optimization and pre-calculation). One other flaw was revealed and fixed in the process : references were not calling the recalculation method for used_tables of their targets. --- mysql-test/r/subselect3.result | 53 ++++++++++++++++++++++++++++++ mysql-test/t/subselect3.test | 41 +++++++++++++++++++++++ sql/item.h | 5 +++ sql/item_sum.cc | 36 +++++++++++++++++---- sql/item_sum.h | 59 +++++++++++++++++++++------------- sql/opt_range.cc | 6 ++-- sql/sql_base.cc | 2 ++ sql/sql_class.h | 3 ++ sql/sql_insert.cc | 6 ++-- sql/sql_select.cc | 23 +++++++------ 10 files changed, 189 insertions(+), 45 deletions(-) diff --git a/mysql-test/r/subselect3.result b/mysql-test/r/subselect3.result index 29143b9e504..1320bc76222 100644 --- a/mysql-test/r/subselect3.result +++ b/mysql-test/r/subselect3.result @@ -645,3 +645,56 @@ a b Z 2 2 0 3 3 1 drop table t1,t2; +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t1 VALUES (1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), +(2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'),(3,3,'j'), (3,2,'k'), (3,1,'l'), +(1,9,'m'); +CREATE TABLE t2 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t2 SELECT * FROM t1; +SELECT a, MAX(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) +as test FROM t1 GROUP BY a; +a MAX(b) test +1 9 m +2 3 h +3 4 i +SELECT * FROM t1 GROUP by t1.a +HAVING (MAX(t1.b) > (SELECT MAX(t2.b) FROM t2 WHERE t2.c < t1.c +HAVING MAX(t2.b+t1.a) < 10)); +a b c +SELECT a, AVG(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=AVG(t1.b)) +AS test FROM t1 GROUP BY a; +a AVG(b) test +1 4.0000 NULL +2 2.0000 k +3 2.5000 NULL +SELECT a,b,c FROM t1 WHERE b in (9,3,4) ORDER BY b,c; +a b c +1 3 c +2 3 h +3 3 j +1 4 d +3 4 i +1 9 m +SELECT a, MAX(b), +(SELECT COUNT(DISTINCT t.c) FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) +LIMIT 1) +as cnt, +(SELECT t.b FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) +as t_b, +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) +as t_b, +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) ORDER BY t.c LIMIT 1) +as t_b +FROM t1 GROUP BY a; +a MAX(b) cnt t_b t_b t_b +1 9 1 9 m m +2 3 1 3 h h +3 4 1 4 i i +SELECT a, MAX(b), +(SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) as test +FROM t1 GROUP BY a; +a MAX(b) test +1 9 m +2 3 h +3 4 i +DROP TABLE t1, t2; diff --git a/mysql-test/t/subselect3.test b/mysql-test/t/subselect3.test index ed8480ba464..e3703c0da16 100644 --- a/mysql-test/t/subselect3.test +++ b/mysql-test/t/subselect3.test @@ -489,3 +489,44 @@ select a, b, (a,b) in (select a, min(b) from t2 group by a) Z from t1; drop table t1,t2; +# +# Bug #24484: Aggregate function used in column list subquery gives erroneous +# error +# +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t1 VALUES (1,1,'a'), (1,2,'b'), (1,3,'c'), (1,4,'d'), (1,5,'e'), + (2,1,'f'), (2,2,'g'), (2,3,'h'), (3,4,'i'),(3,3,'j'), (3,2,'k'), (3,1,'l'), + (1,9,'m'); +CREATE TABLE t2 (a int, b INT, c CHAR(10) NOT NULL, PRIMARY KEY (a, b)); +INSERT INTO t2 SELECT * FROM t1; + +# Gives error, but should work since it is (a, b) is the PK so only one +# given match possible +SELECT a, MAX(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b)) + as test FROM t1 GROUP BY a; +SELECT * FROM t1 GROUP by t1.a + HAVING (MAX(t1.b) > (SELECT MAX(t2.b) FROM t2 WHERE t2.c < t1.c + HAVING MAX(t2.b+t1.a) < 10)); +SELECT a, AVG(b), (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=AVG(t1.b)) + AS test FROM t1 GROUP BY a; + +SELECT a,b,c FROM t1 WHERE b in (9,3,4) ORDER BY b,c; + +SELECT a, MAX(b), + (SELECT COUNT(DISTINCT t.c) FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) + LIMIT 1) + as cnt, + (SELECT t.b FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) + as t_b, + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) + as t_b, + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) ORDER BY t.c LIMIT 1) + as t_b + FROM t1 GROUP BY a; + +SELECT a, MAX(b), + (SELECT t.c FROM t1 AS t WHERE t1.a=t.a AND t.b=MAX(t1.b) LIMIT 1) as test + FROM t1 GROUP BY a; + + +DROP TABLE t1, t2; diff --git a/sql/item.h b/sql/item.h index 6c41aa09f80..1e724e2aa93 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1881,6 +1881,11 @@ public: { return depended_from ? OUTER_REF_TABLE_BIT : (*ref)->used_tables(); } + void update_used_tables() + { + if (!depended_from) + (*ref)->update_used_tables(); + } table_map not_null_tables() const { return (*ref)->not_null_tables(); } void set_result_field(Field *field) { result_field= field; } bool is_result_field() { return 1; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 8bfac058936..0b0fb065bb3 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -61,6 +61,7 @@ bool Item_sum::init_sum_func_check(THD *thd) /* Save a pointer to object to be used in items for nested set functions */ thd->lex->in_sum_func= this; nest_level= thd->lex->current_select->nest_level; + nest_level_tables_count= thd->lex->current_select->join->tables; ref_by= 0; aggr_level= -1; max_arg_level= -1; @@ -176,6 +177,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) */ set_if_bigger(in_sum_func->max_sum_func_level, aggr_level); } + update_used_tables(); thd->lex->in_sum_func= in_sum_func; return FALSE; } @@ -271,8 +273,8 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref) } -Item_sum::Item_sum(List &list) - :arg_count(list.elements) +Item_sum::Item_sum(List &list) :arg_count(list.elements), + forced_const(FALSE) { if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) { @@ -296,7 +298,10 @@ Item_sum::Item_sum(List &list) Item_sum::Item_sum(THD *thd, Item_sum *item): Item_result_field(thd, item), arg_count(item->arg_count), - quick_group(item->quick_group) + nest_level(item->nest_level), aggr_level(item->aggr_level), + quick_group(item->quick_group), used_tables_cache(item->used_tables_cache), + forced_const(item->forced_const), + nest_level_tables_count(item->nest_level_tables_count) { if (arg_count <= 2) args=tmp_args; @@ -425,6 +430,26 @@ case DECIMAL_RESULT: } +void Item_sum::update_used_tables () +{ + if (!forced_const) + { + used_tables_cache= 0; + for (uint i=0 ; i < arg_count ; i++) + { + args[i]->update_used_tables(); + used_tables_cache|= args[i]->used_tables(); + } + + used_tables_cache&= PSEUDO_TABLE_BITS; + + /* the aggregate function is aggregated into its local context */ + if (aggr_level == nest_level) + used_tables_cache |= (1 << nest_level_tables_count) - 1; + } +} + + String * Item_sum_num::val_str(String *str) { @@ -484,7 +509,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref) Item_sum_hybrid::Item_sum_hybrid(THD *thd, Item_sum_hybrid *item) :Item_sum(thd, item), value(item->value), hybrid_type(item->hybrid_type), hybrid_field_type(item->hybrid_field_type), cmp_sign(item->cmp_sign), - used_table_cache(item->used_table_cache), was_values(item->was_values) + was_values(item->was_values) { /* copy results from old value */ switch (hybrid_type) { @@ -1072,7 +1097,6 @@ void Item_sum_count::cleanup() DBUG_ENTER("Item_sum_count::cleanup"); count= 0; Item_sum_int::cleanup(); - used_table_cache= ~(table_map) 0; DBUG_VOID_RETURN; } @@ -1553,7 +1577,7 @@ void Item_sum_hybrid::cleanup() { DBUG_ENTER("Item_sum_hybrid::cleanup"); Item_sum::cleanup(); - used_table_cache= ~(table_map) 0; + forced_const= FALSE; /* by default it is TRUE to avoid TRUE reporting by diff --git a/sql/item_sum.h b/sql/item_sum.h index f011f105453..9ddda94a8ee 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -215,7 +215,9 @@ TODO: to catch queries where the limit is exceeded to make the code clean here. -*/ +*/ + +class st_select_lex; class Item_sum :public Item_result_field { @@ -237,19 +239,26 @@ public: int8 max_sum_func_level;/* max level of aggregation for embedded functions */ bool quick_group; /* If incremental update of fields */ +protected: + table_map used_tables_cache; + bool forced_const; + byte nest_level_tables_count; + +public: + void mark_as_sum_func(); - Item_sum() :arg_count(0), quick_group(1) + Item_sum() :arg_count(0), quick_group(1), forced_const(FALSE) { mark_as_sum_func(); } - Item_sum(Item *a) - :args(tmp_args), arg_count(1), quick_group(1) + Item_sum(Item *a) :args(tmp_args), arg_count(1), quick_group(1), + forced_const(FALSE) { args[0]=a; mark_as_sum_func(); } - Item_sum( Item *a, Item *b ) - :args(tmp_args), arg_count(2), quick_group(1) + Item_sum( Item *a, Item *b ) :args(tmp_args), arg_count(2), quick_group(1), + forced_const(FALSE) { args[0]=a; args[1]=b; mark_as_sum_func(); @@ -319,10 +328,20 @@ public: virtual const char *func_name() const= 0; virtual Item *result_item(Field *field) { return new Item_field(field); } - table_map used_tables() const { return ~(table_map) 0; } /* Not used */ - bool const_item() const { return 0; } + table_map used_tables() const { return used_tables_cache; } + void update_used_tables (); + void cleanup() + { + Item::cleanup(); + forced_const= FALSE; + } bool is_null() { return null_value; } - void update_used_tables() { } + void make_const () + { + used_tables_cache= 0; + forced_const= TRUE; + } + virtual bool const_item() const { return forced_const; } void make_field(Send_field *field); void print(String *str); void fix_num_length_and_dec(); @@ -509,23 +528,23 @@ public: class Item_sum_count :public Item_sum_int { longlong count; - table_map used_table_cache; public: Item_sum_count(Item *item_par) - :Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0) + :Item_sum_int(item_par),count(0) {} Item_sum_count(THD *thd, Item_sum_count *item) - :Item_sum_int(thd, item), count(item->count), - used_table_cache(item->used_table_cache) + :Item_sum_int(thd, item), count(item->count) {} - table_map used_tables() const { return used_table_cache; } - bool const_item() const { return !used_table_cache; } enum Sumfunctype sum_func () const { return COUNT_FUNC; } void clear(); void no_rows_in_result() { count=0; } bool add(); - void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; } + void make_const(longlong count_arg) + { + count=count_arg; + Item_sum::make_const(); + } longlong val_int(); void reset_field(); void cleanup(); @@ -805,28 +824,22 @@ protected: Item_result hybrid_type; enum_field_types hybrid_field_type; int cmp_sign; - table_map used_table_cache; bool was_values; // Set if we have found at least one row (for max/min only) public: Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par), sum(0.0), sum_int(0), hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG), - cmp_sign(sign), used_table_cache(~(table_map) 0), - was_values(TRUE) + cmp_sign(sign), was_values(TRUE) { collation.set(&my_charset_bin); } Item_sum_hybrid(THD *thd, Item_sum_hybrid *item); bool fix_fields(THD *, Item **); - table_map used_tables() const { return used_table_cache; } - bool const_item() const { return !used_table_cache; } - void clear(); double val_real(); longlong val_int(); my_decimal *val_decimal(my_decimal *); void reset_field(); String *val_str(String *); - void make_const() { used_table_cache=0; } bool keep_field_type(void) const { return 1; } enum Item_result result_type () const { return hybrid_type; } enum enum_field_types field_type() const { return hybrid_field_type; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index f0af4b7db2a..8985561dd30 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7516,7 +7516,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) else DBUG_RETURN(NULL); - Item *expr= min_max_item->args[0]; /* The argument of MIN/MAX. */ + /* The argument of MIN/MAX. */ + Item *expr= min_max_item->args[0]->real_item(); if (expr->type() == Item::FIELD_ITEM) /* Is it an attribute? */ { if (! min_max_arg_item) @@ -7894,6 +7895,7 @@ check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item, DBUG_ENTER("check_group_min_max_predicates"); DBUG_ASSERT(cond && min_max_arg_item); + cond= cond->real_item(); Item::Type cond_type= cond->type(); if (cond_type == Item::COND_ITEM) /* 'AND' or 'OR' */ { @@ -7931,7 +7933,7 @@ check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item, DBUG_PRINT("info", ("Analyzing: %s", pred->func_name())); for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++) { - cur_arg= arguments[arg_idx]; + cur_arg= arguments[arg_idx]->real_item(); DBUG_PRINT("info", ("cur_arg: %s", cur_arg->full_name())); if (cur_arg->type() == Item::FIELD_ITEM) { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ad9cd5985d1..0f9ba371ce1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4656,6 +4656,7 @@ bool setup_tables_and_check_access(THD *thd, TABLE_LIST *leaves_tmp = NULL; bool first_table= true; + thd->leaf_count= 0; if (setup_tables (thd, context, from_clause, tables, conds, &leaves_tmp, select_insert)) return TRUE; @@ -4673,6 +4674,7 @@ bool setup_tables_and_check_access(THD *thd, return TRUE; } first_table= false; + thd->leaf_count++; } return FALSE; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 05034ebd573..3421f506ca5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1432,6 +1432,9 @@ public: query_id_t first_query_id; } binlog_evt_union; + /* pass up the count of "leaf" tables in a JOIN out of setup_tables() */ + byte leaf_count; + THD(); ~THD(); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index fb59aeea8e7..c369f03d978 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2301,12 +2301,14 @@ bool mysql_insert_select_prepare(THD *thd) DBUG_ASSERT(select_lex->leaf_tables != 0); lex->leaf_tables_insert= select_lex->leaf_tables; /* skip all leaf tables belonged to view where we are insert */ - for (first_select_leaf_table= select_lex->leaf_tables->next_leaf; + for (first_select_leaf_table= select_lex->leaf_tables->next_leaf, + thd->leaf_count --; first_select_leaf_table && first_select_leaf_table->belong_to_view && first_select_leaf_table->belong_to_view == lex->leaf_tables_insert->belong_to_view; - first_select_leaf_table= first_select_leaf_table->next_leaf) + first_select_leaf_table= first_select_leaf_table->next_leaf, + thd->leaf_count --) {} select_lex->leaf_tables= first_select_leaf_table; DBUG_RETURN(FALSE); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 05ee0d77c1f..12bab33cc13 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -342,12 +342,15 @@ JOIN::prepare(Item ***rref_pointer_array, /* Check that all tables, fields, conds and order are ok */ - if ((!(select_options & OPTION_SETUP_TABLES_DONE) && - setup_tables_and_check_access(thd, &select_lex->context, join_list, - tables_list, &conds, - &select_lex->leaf_tables, FALSE, - SELECT_ACL, SELECT_ACL)) || - setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || + if (!(select_options & OPTION_SETUP_TABLES_DONE) && + setup_tables_and_check_access(thd, &select_lex->context, join_list, + tables_list, &conds, + &select_lex->leaf_tables, FALSE, + SELECT_ACL, SELECT_ACL)) + DBUG_RETURN(-1); + tables= thd->leaf_count; + + if (setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) || select_lex->setup_ref_array(thd, og_num) || setup_fields(thd, (*rref_pointer_array), fields_list, 1, &all_fields, 1) || @@ -437,11 +440,6 @@ JOIN::prepare(Item ***rref_pointer_array, DBUG_RETURN(-1); } } - TABLE_LIST *table_ptr; - for (table_ptr= select_lex->leaf_tables; - table_ptr; - table_ptr= table_ptr->next_leaf) - tables++; } { /* Caclulate the number of groups */ @@ -6376,7 +6374,8 @@ static void update_depend_map(JOIN *join, ORDER *order) order->item[0]->update_used_tables(); order->depend_map=depend_map=order->item[0]->used_tables(); // Not item_sum(), RAND() and no reference to table outside of sub select - if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT))) + if (!(order->depend_map & (OUTER_REF_TABLE_BIT | RAND_TABLE_BIT)) + && !order->item[0]->with_sum_func) { for (JOIN_TAB **tab=join->map2table; depend_map ; From 19da4d3972bf32831df76f983f97ed8a4c7b4ce2 Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Tue, 20 Mar 2007 11:51:09 -0700 Subject: [PATCH 03/17] Fixed bug #27257: queries containing subqueries with COUNT(*) aggregated in outer context returned wrong results. This happened only if the subquery did not contain any references to outer fields. As there were no references to outer fields the subquery erroneously was taken for non-correlated one. Now any set function aggregated in outer context makes the subquery correlated. --- mysql-test/r/subselect.result | 25 +++++++++++++++++++++++++ mysql-test/t/subselect.test | 21 +++++++++++++++++++++ sql/item_sum.cc | 1 + 3 files changed, 47 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index f2d41bd44ae..72bde001e87 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3880,3 +3880,28 @@ this is a test. 3 this is a test. 1 this is a test. 2 DROP table t1; +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (m int, n int); +INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4); +INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44); +SELECT COUNT(*), a, +(SELECT m FROM t2 WHERE m = count(*) LIMIT 1) +FROM t1 GROUP BY a; +COUNT(*) a (SELECT m FROM t2 WHERE m = count(*) LIMIT 1) +2 2 2 +3 3 3 +1 4 1 +SELECT COUNT(*), a, +(SELECT MIN(m) FROM t2 WHERE m = count(*)) +FROM t1 GROUP BY a; +COUNT(*) a (SELECT MIN(m) FROM t2 WHERE m = count(*)) +2 2 2 +3 3 3 +1 4 1 +SELECT COUNT(*), a +FROM t1 GROUP BY a +HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1; +COUNT(*) a +2 2 +3 3 +DROP TABLE t1,t2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1655422c51e..a238c8f070b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2741,4 +2741,25 @@ SELECT * FROM (SELECT 'this is ' 'a test.' AS col1, a AS t2 FROM t1) t; DROP table t1; +# +# Bug #27257: COUNT(*) aggregated in outer query +# +CREATE TABLE t1 (a int, b int); +CREATE TABLE t2 (m int, n int); +INSERT INTO t1 VALUES (2,2), (2,2), (3,3), (3,3), (3,3), (4,4); +INSERT INTO t2 VALUES (1,11), (2,22), (3,32), (4,44), (4,44); + +SELECT COUNT(*), a, + (SELECT m FROM t2 WHERE m = count(*) LIMIT 1) + FROM t1 GROUP BY a; + +SELECT COUNT(*), a, + (SELECT MIN(m) FROM t2 WHERE m = count(*)) + FROM t1 GROUP BY a; + +SELECT COUNT(*), a + FROM t1 GROUP BY a + HAVING (SELECT MIN(m) FROM t2 WHERE m = count(*)) > 1; + +DROP TABLE t1,t2; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 41f0dd6496b..a8ffa200102 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -267,6 +267,7 @@ bool Item_sum::register_sum_func(THD *thd, Item **ref) sl= sl->master_unit()->outer_select() ) sl->master_unit()->item->with_sum_func= 1; } + thd->lex->current_select->mark_as_dependent(aggr_sl); return FALSE; } From 72bf9b4847349354a269f4341349b36beb38f7fe Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Wed, 21 Mar 2007 21:54:38 +0300 Subject: [PATCH 04/17] Bug#23345: Wrongly allowed INTO in a non-last select of a UNION. INTO clause can be specified only for the last select of a UNION and it receives the result of the whole query. But it was wrongly allowed in non-last selects of a UNION which leads to a confusing query result. Now INTO allowed only in the last select of a UNION. --- mysql-test/r/union.result | 8 ++++++++ mysql-test/t/union.test | 9 +++++++++ sql/sql_yacc.yy | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 9861b1bffeb..8219d68a681 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1381,4 +1381,12 @@ a SELECT a FROM (SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY c) AS test; ERROR 42S22: Unknown column 'c' in 'order clause' DROP TABLE t1; +(select 1 into @var) union (select 1); +ERROR HY000: Incorrect usage of UNION and INTO +(select 1) union (select 1 into @var); +select @var; +@var +1 +(select 2) union (select 1 into @var); +ERROR 42000: Result consisted of more than one row End of 5.0 tests diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 29a9ee36481..22f09466b1c 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -868,4 +868,13 @@ SELECT a FROM (SELECT a FROM t1 UNION SELECT a FROM t1 ORDER BY c) AS test; DROP TABLE t1; +# +# Bug#23345: Wrongly allowed INTO in a non-last select of a UNION. +# +--error 1221 +(select 1 into @var) union (select 1); +(select 1) union (select 1 into @var); +select @var; +--error 1172 +(select 2) union (select 1 into @var); --echo End of 5.0 tests diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 258283d113e..a2e7100a6f5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9307,7 +9307,7 @@ union_list: UNION_SYM union_option { LEX *lex=Lex; - if (lex->exchange) + if (lex->result) { /* Only the last SELECT can have INTO...... */ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO"); From 03ae298ec37634de782cc89ed1d010f33eb80bfd Mon Sep 17 00:00:00 2001 From: "igor@olga.mysql.com" <> Date: Thu, 22 Mar 2007 00:05:36 -0700 Subject: [PATCH 05/17] Fixed bug #27362: crash at evaluation of IN predicate when one of its argument happened to be a decimal expression returning the NULL value. The crash was due to the fact the function in_decimal::set did not take into account that val_decimal() could return 0 if the decimal expression had been evaluated to NULL. --- mysql-test/r/func_in.result | 5 +++++ mysql-test/t/func_in.test | 11 +++++++++++ sql/item_cmpfunc.cc | 3 ++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result index fad9a7157e1..87855091699 100644 --- a/mysql-test/r/func_in.result +++ b/mysql-test/r/func_in.result @@ -470,4 +470,9 @@ a Warnings: Warning 1292 Incorrect date value: '19772-07-29' for column 'a' at row 1 DROP TABLE t1,t2,t3,t4; +CREATE TABLE t1 (id int not null); +INSERT INTO t1 VALUES (1),(2); +SELECT id FROM t1 WHERE id IN(4564, (SELECT IF(1=0,1,1/0)) ); +id +DROP TABLE t1; End of 5.0 tests diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test index f9749662ec1..77592d015eb 100644 --- a/mysql-test/t/func_in.test +++ b/mysql-test/t/func_in.test @@ -360,4 +360,15 @@ SELECT * FROM t4 WHERE a IN ('1972-02-06','19772-07-29'); DROP TABLE t1,t2,t3,t4; +# +# BUG#27362: IN with a decimal expression that may return NULL +# + +CREATE TABLE t1 (id int not null); +INSERT INTO t1 VALUES (1),(2); + +SELECT id FROM t1 WHERE id IN(4564, (SELECT IF(1=0,1,1/0)) ); + +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index e032974fdea..44472bf0803 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -2423,7 +2423,8 @@ void in_decimal::set(uint pos, Item *item) dec->len= DECIMAL_BUFF_LENGTH; dec->fix_buffer_pointer(); my_decimal *res= item->val_decimal(dec); - if (res != dec) + /* if item->val_decimal() is evaluated to NULL then res == 0 */ + if (!item->null_value && res != dec) my_decimal2decimal(res, dec); } From 36e11d049e3d61af00d536fb3e5dfbb9c5a4606b Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Thu, 22 Mar 2007 12:19:41 +0400 Subject: [PATCH 06/17] merging --- sql/sql_base.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d4316f11491..a3c03fdaf12 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5771,11 +5771,13 @@ bool setup_tables_and_check_access(THD *thd, TABLE_LIST *leaves_tmp= NULL; bool first_table= true; + thd->leaf_count= 0; if (setup_tables(thd, context, from_clause, tables, &leaves_tmp, select_insert)) return TRUE; - *leaves= leaves_tmp; + if (leaves) + *leaves= leaves_tmp; for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf) { @@ -5787,6 +5789,7 @@ bool setup_tables_and_check_access(THD *thd, return TRUE; } first_table= 0; + thd->leaf_count++; } return FALSE; } From e0f0507f999a35362e19ff0d80b3fd2565c83d7c Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Thu, 22 Mar 2007 12:24:56 +0400 Subject: [PATCH 07/17] bug #16546 (DATETIME + 0 not always coerced in the same way) fix for cast( AS DATETIME) + 0 operation. I just implemented Item_datetime_typecast::val() method as it is usually done in other classes. Should be fixed more radically in 5.0 --- mysql-test/r/type_datetime.result | 3 +++ mysql-test/t/type_datetime.test | 6 ++++++ sql/item_timefunc.h | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index f313a6b934b..64337bd2c2f 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -166,3 +166,6 @@ dt 0000-00-00 00:00:00 0000-00-00 00:00:00 drop table t1; +select cast('2006-12-05 22:10:10' as datetime) + 0; +cast('2006-12-05 22:10:10' as datetime) + 0 +20061205221010.000000 diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 4b6741b4242..87b86b55fc9 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -113,4 +113,10 @@ insert into t1 values ("00-00-00"), ("00-00-00 00:00:00"); select * from t1; drop table t1; +# +# Bug #16546 DATETIME+0 not always coerced the same way +# +select cast('2006-12-05 22:10:10' as datetime) + 0; + + # End of 4.1 tests diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 45cad627c05..2383b4f86ac 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -751,12 +751,19 @@ public: String *val_str(String *str); const char *cast_type() const { return "datetime"; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } + void fix_length_and_dec() + { + Item_typecast_maybe_null::fix_length_and_dec(); + decimals= DATETIME_DEC; + } + Field *tmp_table_field(TABLE *t_arg) { return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); } bool result_as_longlong() { return TRUE; } longlong val_int(); + double val() { return (double) val_int(); } }; class Item_func_makedate :public Item_str_func From a016f71c45d01ee95308e1f862d990e149ccb9f6 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Thu, 22 Mar 2007 12:44:38 +0400 Subject: [PATCH 08/17] bug #16546 (DATETIME+0 not always coerced the same way) fix for cast( AS DATETIME)+0 in 5.0 and above versions. val_real now works using val_decimal for DATETIME Items Superfluous val_real() methods deleted --- sql/item_timefunc.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index acc5e6a80cc..14ceb8dcb28 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -330,7 +330,7 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_DATE; } String *val_str(String *str); longlong val_int(); - double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } + double val_real() { return val_real_from_decimal(); } const char *func_name() const { return "date"; } void fix_length_and_dec() { @@ -368,6 +368,7 @@ public: return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); } bool result_as_longlong() { return TRUE; } + double val_real() { return (double) val_int(); } my_decimal *val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -390,13 +391,14 @@ public: enum_field_types field_type() const { return MYSQL_TYPE_TIME; } void fix_length_and_dec() { - decimals=0; + decimals= DATETIME_DEC; max_length=MAX_TIME_WIDTH*MY_CHARSET_BIN_MB_MAXLEN; } Field *tmp_table_field(TABLE *t_arg) { return (new Field_time(maybe_null, name, t_arg, &my_charset_bin)); } + double val_real() { return val_real_from_decimal(); } my_decimal *val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -504,7 +506,6 @@ public: Item_func_now() :Item_date_func() {} Item_func_now(Item *a) :Item_date_func(a) {} enum Item_result result_type () const { return STRING_RESULT; } - double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; } longlong val_int() { DBUG_ASSERT(fixed == 1); return value; } int save_in_field(Field *to, bool no_conversions); String *val_str(String *str); @@ -592,11 +593,6 @@ class Item_func_from_unixtime :public Item_date_func THD *thd; public: Item_func_from_unixtime(Item *a) :Item_date_func(a) {} - double val_real() - { - DBUG_ASSERT(fixed == 1); - return (double) Item_func_from_unixtime::val_int(); - } longlong val_int(); String *val_str(String *str); const char *func_name() const { return "from_unixtime"; } @@ -635,7 +631,6 @@ class Item_func_convert_tz :public Item_date_func Item_func_convert_tz(Item *a, Item *b, Item *c): Item_date_func(a, b, c), from_tz_cached(0), to_tz_cached(0) {} longlong val_int(); - double val_real() { return (double) val_int(); } String *val_str(String *str); const char *func_name() const { return "convert_tz"; } bool fix_fields(THD *, Item **); @@ -661,7 +656,6 @@ public: Item_str_timefunc::fix_length_and_dec(); collation.set(&my_charset_bin); maybe_null=1; - decimals= DATETIME_DEC; } const char *func_name() const { return "sec_to_time"; } bool result_as_longlong() { return TRUE; } @@ -699,7 +693,6 @@ public: const char *func_name() const { return "date_add_interval"; } void fix_length_and_dec(); enum_field_types field_type() const { return cached_field_type; } - double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } longlong val_int(); bool get_date(TIME *res, uint fuzzy_date); bool eq(const Item *item, bool binary_cmp) const; @@ -800,6 +793,7 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); + double val_real() { return (double) val_int(); } my_decimal *val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -827,6 +821,7 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); + double val_real() { return val_real_from_decimal(); } my_decimal *val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); @@ -859,6 +854,7 @@ public: } bool result_as_longlong() { return TRUE; } longlong val_int(); + double val_real() { return val_real_from_decimal(); } double val() { return (double) val_int(); } my_decimal *val_decimal(my_decimal *decimal_value) { @@ -928,6 +924,7 @@ public: } void print(String *str); const char *func_name() const { return "add_time"; } + double val_real() { return val_real_from_decimal(); } my_decimal *val_decimal(my_decimal *decimal_value) { DBUG_ASSERT(fixed == 1); From 50077b6db992e71d189110d90c3267d85e911446 Mon Sep 17 00:00:00 2001 From: "mhansson/martin@linux-st28.site" <> Date: Thu, 22 Mar 2007 10:56:47 +0100 Subject: [PATCH 09/17] Bug #24791: Union with AVG-groups generates wrong results The problem in this bug is when we create temporary tables. When temporary tables are created for unions, there is some inferrence being carried out regarding the type of the column. Whenever this column type is inferred to be REAL (i.e. FLOAT or DOUBLE), MySQL will always try to maintain exact precision, and if that is not possible (there are hardware limits, since FLOAT and DOUBLE are stored as approximate values) will switch to using approximate values. The problem here is that at this point the information about number of significant digits is not available. Furthermore, the number of significant digits should be increased for the AVG function, however, this was not properly handled. There are 4 parts to the problem: #1: DOUBLE and FLOAT fields don't display their proper display lengths in max_display_length(). This is hard-coded as 53 for DOUBLE and 24 for FLOAT. Now changed to instead return the field_length. #2: Type holders for temporary tables do not preserve the max_length of the Item's from which they are created, and is instead reverted to the 53 and 24 from above. This causes *all* fields to get non-fixed significant digits. #3: AVG function does not update max_length (display length) when updating number of decimals. #4: The function that switches to non-fixed number of significant digits should use DBL_DIG + 2 or FLT_DIG + 2 as cut-off values (Since fixed precision does not use the 'e' notation) Of these points, #1 is the controversial one, but this change is preferred and has been cleared with Monty. The function causes quite a few unit tests to blow up and they had to b changed, but each one is annotated and motivated. We frequently see the magical 53 and 24 give way to more relevant numbers. --- mysql-test/r/create.result | 4 ++-- mysql-test/r/temp_table.result | 21 +++++++++++++++++++++ mysql-test/r/type_float.result | 8 ++++---- mysql-test/t/temp_table.test | 16 ++++++++++++++++ sql/field.h | 4 +--- sql/item.cc | 18 +++++++++++------- sql/item_sum.cc | 4 +++- 7 files changed, 58 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 11c1431de7b..0a8fef8d881 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -447,8 +447,8 @@ t2 CREATE TABLE `t2` ( `ifnull(c,c)` mediumint(8) default NULL, `ifnull(d,d)` int(11) default NULL, `ifnull(e,e)` bigint(20) default NULL, - `ifnull(f,f)` float(24,2) default NULL, - `ifnull(g,g)` double(53,3) default NULL, + `ifnull(f,f)` float(3,2) default NULL, + `ifnull(g,g)` double(4,3) default NULL, `ifnull(h,h)` decimal(5,4) default NULL, `ifnull(i,i)` year(4) default NULL, `ifnull(j,j)` date default NULL, diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result index 139a7da77de..d6adf51602b 100644 --- a/mysql-test/r/temp_table.result +++ b/mysql-test/r/temp_table.result @@ -152,3 +152,24 @@ SELECT * FROM t1; i DROP TABLE t1; End of 4.1 tests. +CREATE TABLE t1 ( c FLOAT( 20, 14 ) ); +INSERT INTO t1 VALUES( 12139 ); +CREATE TABLE t2 ( c FLOAT(30,18) ); +INSERT INTO t2 VALUES( 123456 ); +SELECT AVG( c ) FROM t1 UNION SELECT 1; +AVG( c ) +12139 +1 +SELECT 1 UNION SELECT AVG( c ) FROM t1; +1 +1 +12139 +SELECT 1 UNION SELECT * FROM t2 UNION SELECT 1; +1 +1 +123456 +SELECT c/1 FROM t1 UNION SELECT 1; +c/1 +12139 +1 +DROP TABLE t1, t2; diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index 0cb77f42caf..188963c5bdf 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -92,7 +92,7 @@ show create table t2; Table Create Table t2 CREATE TABLE `t2` ( `col1` double default NULL, - `col2` double(53,5) default NULL, + `col2` double(22,5) default NULL, `col3` double default NULL, `col4` double default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 @@ -232,12 +232,12 @@ insert into t2 values ("1.23456780"); create table t3 select * from t2 union select * from t1; select * from t3; d -1.234567800 -100000000.000000000 +1.2345678 +100000000 show create table t3; Table Create Table t3 CREATE TABLE `t3` ( - `d` double(22,9) default NULL + `d` double default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2, t3; create table t1 select 105213674794682365.00 + 0.0 x; diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test index 8cb9e34ca08..90f868f5932 100644 --- a/mysql-test/t/temp_table.test +++ b/mysql-test/t/temp_table.test @@ -163,3 +163,19 @@ DROP TABLE t1; --echo End of 4.1 tests. + +# +# Bug #24791: Union with AVG-groups generates wrong results +# +CREATE TABLE t1 ( c FLOAT( 20, 14 ) ); +INSERT INTO t1 VALUES( 12139 ); + +CREATE TABLE t2 ( c FLOAT(30,18) ); +INSERT INTO t2 VALUES( 123456 ); + +SELECT AVG( c ) FROM t1 UNION SELECT 1; +SELECT 1 UNION SELECT AVG( c ) FROM t1; +SELECT 1 UNION SELECT * FROM t2 UNION SELECT 1; +SELECT c/1 FROM t1 UNION SELECT 1; + +DROP TABLE t1, t2; diff --git a/sql/field.h b/sql/field.h index 524380800f3..a00419893e1 100644 --- a/sql/field.h +++ b/sql/field.h @@ -432,6 +432,7 @@ public: int store_decimal(const my_decimal *); my_decimal *val_decimal(my_decimal *); + uint32 max_display_length() { return field_length; } }; @@ -461,7 +462,6 @@ public: void overflow(bool negative); bool zero_pack() const { return 0; } void sql_type(String &str) const; - uint32 max_display_length() { return field_length; } }; @@ -719,7 +719,6 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(float); } void sql_type(String &str) const; - uint32 max_display_length() { return 24; } }; @@ -762,7 +761,6 @@ public: void sort_string(char *buff,uint length); uint32 pack_length() const { return sizeof(double); } void sql_type(String &str) const; - uint32 max_display_length() { return 53; } uint size_of() const { return sizeof(*this); } }; diff --git a/sql/item.cc b/sql/item.cc index 11a5039ca19..958de308cc4 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -6348,8 +6348,6 @@ Item_type_holder::Item_type_holder(THD *thd, Item *item) :Item(thd, item), enum_set_typelib(0), fld_type(get_real_type(item)) { DBUG_ASSERT(item->fixed); - - max_length= display_length(item); maybe_null= item->maybe_null; collation.set(item->collation); get_full_info(item); @@ -6521,11 +6519,17 @@ bool Item_type_holder::join_types(THD *thd, Item *item) { int delta1= max_length_orig - decimals_orig; int delta2= item->max_length - item->decimals; - if (fld_type == MYSQL_TYPE_DECIMAL) - max_length= max(delta1, delta2) + decimals; - else - max_length= min(max(delta1, delta2) + decimals, - (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7); + max_length= max(delta1, delta2) + decimals; + if (fld_type == MYSQL_TYPE_FLOAT && max_length > FLT_DIG + 2) + { + max_length= FLT_DIG + 6; + decimals= NOT_FIXED_DEC; + } + if (fld_type == MYSQL_TYPE_DOUBLE && max_length > DBL_DIG + 2) + { + max_length= DBL_DIG + 7; + decimals= NOT_FIXED_DEC; + } } else max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 41f0dd6496b..acc2d22c57c 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1096,8 +1096,10 @@ void Item_sum_avg::fix_length_and_dec() f_scale= args[0]->decimals; dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale); } - else + else { decimals= min(args[0]->decimals + prec_increment, NOT_FIXED_DEC); + max_length= args[0]->max_length + prec_increment; + } } From 99ac24679d1fe289493f28b513210175cc60d075 Mon Sep 17 00:00:00 2001 From: "mhansson/martin@linux-st28.site" <> Date: Thu, 22 Mar 2007 14:58:43 +0100 Subject: [PATCH 10/17] Bug#24791: Union with AVG-groups generates wrong results Patch appled after doing a pull from the team tree. Additional tests had to be fixed --- mysql-test/r/union.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 8219d68a681..efdd8195fb5 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -554,7 +554,7 @@ aa show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` varbinary(20) NOT NULL default '' + `a` varbinary(2) NOT NULL default '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT 12 as a UNION select 12.2 as a; @@ -655,7 +655,7 @@ f show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `f` varbinary(24) default NULL + `f` varbinary(12) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT y from t2 UNION select da from t2; From ef1bb48af9a0f8ce11cafc8d5a3e7d07c404c660 Mon Sep 17 00:00:00 2001 From: "gkodinov/kgeorge@magare.gmz" <> Date: Thu, 22 Mar 2007 18:44:16 +0200 Subject: [PATCH 11/17] Bug #26207: When making the key image to use in index search MySQL was not explicitly suppressing warnings. And if the context happens to enable warnings (e.g. INSERT .. SELECT) the warnings resulting from converting the data the key is compared to are reported to the client. Fixed by suppressing warnings when converting the data to the same type as the key parts. --- mysql-test/r/insert_select.result | 29 +++++++++++++++++ mysql-test/t/insert_select.test | 27 +++++++++++++++- sql/sql_select.h | 53 ++++++++++++++++++++++++------- 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result index 92b3ea0e42b..a96add7eb9a 100644 --- a/mysql-test/r/insert_select.result +++ b/mysql-test/r/insert_select.result @@ -744,3 +744,32 @@ f1 f2 2 2 10 10 DROP TABLE t1, t2; +SET SQL_MODE='STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; +CREATE TABLE t1 (c VARCHAR(30), INDEX ix_c (c(10))); +CREATE TABLE t2 (d VARCHAR(10)); +INSERT INTO t1 (c) VALUES ('7_chars'), ('13_characters'); +EXPLAIN +SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') FROM t1; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 +2 SUBQUERY t1 ref ix_c ix_c 13 const 1 Using where +SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') FROM t1; +(SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') +13 +13 +INSERT INTO t2 (d) +SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') FROM t1; +INSERT INTO t2 (d) +SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='7_chars') FROM t1; +INSERT INTO t2 (d) +SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c IN (SELECT t1.c FROM t1)) +FROM t1; +SELECT * FROM t2; +d +13 +13 +7 +7 +20 +20 +DROP TABLE t1,t2; diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test index 31508b3d6c4..bbc51be6dc9 100644 --- a/mysql-test/t/insert_select.test +++ b/mysql-test/t/insert_select.test @@ -306,4 +306,29 @@ INSERT INTO t2 (f1, f2) SELECT * FROM t2; DROP TABLE t1, t2; - +# +# Bug #26207: inserts don't work with shortened index +# +SET SQL_MODE='STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; + +CREATE TABLE t1 (c VARCHAR(30), INDEX ix_c (c(10))); +CREATE TABLE t2 (d VARCHAR(10)); +INSERT INTO t1 (c) VALUES ('7_chars'), ('13_characters'); + +EXPLAIN + SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') FROM t1; + +SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') FROM t1; + +INSERT INTO t2 (d) + SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='13_characters') FROM t1; + +INSERT INTO t2 (d) + SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c='7_chars') FROM t1; + +INSERT INTO t2 (d) + SELECT (SELECT SUM(LENGTH(c)) FROM t1 WHERE c IN (SELECT t1.c FROM t1)) + FROM t1; + +SELECT * FROM t2; +DROP TABLE t1,t2; diff --git a/sql/sql_select.h b/sql/sql_select.h index a17d7fcb362..e70e42da4ae 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -488,15 +488,11 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b); class store_key :public Sql_alloc { - protected: - Field *to_field; // Store data here - char *null_ptr; - char err; public: bool null_key; /* TRUE <=> the value of the key has a null part */ enum store_key_result { STORE_KEY_OK, STORE_KEY_FATAL, STORE_KEY_CONV }; store_key(THD *thd, Field *field_arg, char *ptr, char *null, uint length) - :null_ptr(null), err(0), null_key(0) + :null_key(0), null_ptr(null), err(0) { if (field_arg->type() == FIELD_TYPE_BLOB) { @@ -510,8 +506,35 @@ public: ptr, (uchar*) null, 1); } virtual ~store_key() {} /* Not actually needed */ - virtual enum store_key_result copy()=0; virtual const char *name() const=0; + + /** + @brief sets ignore truncation warnings mode and calls the real copy method + + @details this function makes sure truncation warnings when preparing the + key buffers don't end up as errors (because of an enclosing INSERT/UPDATE). + */ + enum store_key_result copy() + { + enum store_key_result result; + enum_check_fields saved_count_cuted_fields= + to_field->table->in_use->count_cuted_fields; + + to_field->table->in_use->count_cuted_fields= CHECK_FIELD_IGNORE; + + result= copy_inner(); + + to_field->table->in_use->count_cuted_fields= saved_count_cuted_fields; + + return result; + } + + protected: + Field *to_field; // Store data here + char *null_ptr; + char err; + + virtual enum store_key_result copy_inner()=0; }; @@ -531,13 +554,15 @@ class store_key_field: public store_key copy_field.set(to_field,from_field,0); } } - enum store_key_result copy() + const char *name() const { return field_name; } + + protected: + enum store_key_result copy_inner() { copy_field.do_copy(©_field); null_key= to_field->is_null(); return err != 0 ? STORE_KEY_FATAL : STORE_KEY_OK; } - const char *name() const { return field_name; } }; @@ -552,13 +577,15 @@ public: null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ? &err : NullS, length), item(item_arg) {} - enum store_key_result copy() + const char *name() const { return "func"; } + + protected: + enum store_key_result copy_inner() { int res= item->save_in_field(to_field, 1); null_key= to_field->is_null() || item->null_value; return (err != 0 || res > 2 ? STORE_KEY_FATAL : (store_key_result) res); } - const char *name() const { return "func"; } }; @@ -574,7 +601,10 @@ public: &err : NullS, length, item_arg), inited(0) { } - enum store_key_result copy() + const char *name() const { return "const"; } + +protected: + enum store_key_result copy_inner() { int res; if (!inited) @@ -589,7 +619,6 @@ public: null_key= to_field->is_null() || item->null_value; return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); } - const char *name() const { return "const"; } }; bool cp_buffer_from_ref(THD *thd, TABLE_REF *ref); From 1ac5987ae2e97a4d899741a04096f1bf7153c934 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Thu, 22 Mar 2007 22:05:19 +0300 Subject: [PATCH 12/17] Bug#26813: The SUPER privilege is wrongly required to alter a view created by another user. When the DEFINER clause isn't specified in the ALTER statement then it's loaded from the view definition. If the definer differs from the current user then the error is thrown because only a super-user can set other users as a definers. Now if the DEFINER clause is omitted in the ALTER VIEW statement then the definer from the original view is used without check. --- mysql-test/r/view_grant.result | 21 +++++++++++++++++++++ mysql-test/t/view_grant.test | 31 +++++++++++++++++++++++++++++++ sql/sql_view.cc | 14 ++++++++------ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index 45cf5076fe1..6fec52896c9 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -773,4 +773,25 @@ DROP DATABASE mysqltest_db1; DROP DATABASE mysqltest_db2; DROP USER mysqltest_u1@localhost; DROP USER mysqltest_u2@localhost; +CREATE DATABASE db26813; +USE db26813; +CREATE TABLE t1(f1 INT, f2 INT); +CREATE VIEW v1 AS SELECT f1 FROM t1; +CREATE VIEW v2 AS SELECT f1 FROM t1; +CREATE VIEW v3 AS SELECT f1 FROM t1; +CREATE USER u26813@localhost; +GRANT DROP ON db26813.v1 TO u26813@localhost; +GRANT CREATE VIEW ON db26813.v2 TO u26813@localhost; +GRANT DROP, CREATE VIEW ON db26813.v3 TO u26813@localhost; +GRANT SELECT ON db26813.t1 TO u26813@localhost; +ALTER VIEW v1 AS SELECT f2 FROM t1; +ERROR 42000: CREATE VIEW command denied to user 'u26813'@'localhost' for table 'v1' +ALTER VIEW v2 AS SELECT f2 FROM t1; +ERROR 42000: DROP command denied to user 'u26813'@'localhost' for table 'v2' +ALTER VIEW v3 AS SELECT f2 FROM t1; +SHOW CREATE VIEW v3; +View Create View +v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t1`.`f2` AS `f2` from `t1` +DROP USER u26813@localhost; +DROP DATABASE db26813; End of 5.0 tests. diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index 0785b74dd47..b45afe4f312 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1034,5 +1034,36 @@ DROP DATABASE mysqltest_db2; DROP USER mysqltest_u1@localhost; DROP USER mysqltest_u2@localhost; +# +# Bug#26813: The SUPER privilege is wrongly required to alter a view created +# by another user. +# +connection root; +CREATE DATABASE db26813; +USE db26813; +CREATE TABLE t1(f1 INT, f2 INT); +CREATE VIEW v1 AS SELECT f1 FROM t1; +CREATE VIEW v2 AS SELECT f1 FROM t1; +CREATE VIEW v3 AS SELECT f1 FROM t1; +CREATE USER u26813@localhost; +GRANT DROP ON db26813.v1 TO u26813@localhost; +GRANT CREATE VIEW ON db26813.v2 TO u26813@localhost; +GRANT DROP, CREATE VIEW ON db26813.v3 TO u26813@localhost; +GRANT SELECT ON db26813.t1 TO u26813@localhost; + +connect (u1,localhost,u26813,,db26813); +connection u1; +--error 1142 +ALTER VIEW v1 AS SELECT f2 FROM t1; +--error 1142 +ALTER VIEW v2 AS SELECT f2 FROM t1; +ALTER VIEW v3 AS SELECT f2 FROM t1; + +connection root; +SHOW CREATE VIEW v3; + +DROP USER u26813@localhost; +DROP DATABASE db26813; +disconnect u1; --echo End of 5.0 tests. diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 7143df8474a..714534707d1 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -224,6 +224,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { LEX *lex= thd->lex; bool link_to_local; + bool definer_check_is_needed= mode != VIEW_ALTER || lex->definer; /* first table in list is target VIEW name => cut off it */ TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; @@ -256,8 +257,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, /* DEFINER-clause is missing; we have to create default definer in persistent arena to be PS/SP friendly. + If this is an ALTER VIEW then the current user should be set as + the definer. */ - Query_arena original_arena; Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); @@ -277,11 +279,11 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, - same as current user - current user has SUPER_ACL */ - if (strcmp(lex->definer->user.str, - thd->security_ctx->priv_user) != 0 || - my_strcasecmp(system_charset_info, - lex->definer->host.str, - thd->security_ctx->priv_host) != 0) + if (definer_check_is_needed && + (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) != 0 || + my_strcasecmp(system_charset_info, + lex->definer->host.str, + thd->security_ctx->priv_host) != 0)) { if (!(thd->security_ctx->master_access & SUPER_ACL)) { From 38e023781a26d25eb24026ef57dff58e2f978639 Mon Sep 17 00:00:00 2001 From: "evgen@moonbone.local" <> Date: Thu, 22 Mar 2007 23:13:40 +0300 Subject: [PATCH 13/17] sql_view.cc: Post-fix for bug#26813. --- sql/sql_view.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 714534707d1..83beec3d1be 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -224,7 +224,9 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views, { LEX *lex= thd->lex; bool link_to_local; +#ifndef NO_EMBEDDED_ACCESS_CHECKS bool definer_check_is_needed= mode != VIEW_ALTER || lex->definer; +#endif /* first table in list is target VIEW name => cut off it */ TABLE_LIST *view= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; From e1044ab5d1f9c707cb60cef857e96a44ba45a39b Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Fri, 23 Mar 2007 01:04:31 +0400 Subject: [PATCH 14/17] merging --- mysql-test/r/create.result | 30 +++++++++++++++--------------- mysql-test/r/type_float.result | 10 +++++----- mysql-test/r/union.result | 4 ++-- mysql-test/r/view.result | 2 -- 4 files changed, 22 insertions(+), 24 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 77eb2bb025f..53892b219eb 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -455,21 +455,21 @@ create table t2 select ifnull(a,a), ifnull(b,b), ifnull(c,c), ifnull(d,d), ifnul show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `ifnull(a,a)` tinyint(4) default NULL, - `ifnull(b,b)` smallint(6) default NULL, - `ifnull(c,c)` mediumint(8) default NULL, - `ifnull(d,d)` int(11) default NULL, - `ifnull(e,e)` bigint(20) default NULL, - `ifnull(f,f)` float(3,2) default NULL, - `ifnull(g,g)` double(4,3) default NULL, - `ifnull(h,h)` decimal(5,4) default NULL, - `ifnull(i,i)` year(4) default NULL, - `ifnull(j,j)` date default NULL, - `ifnull(k,k)` timestamp NOT NULL default '0000-00-00 00:00:00', - `ifnull(l,l)` datetime default NULL, - `ifnull(m,m)` varchar(1) default NULL, - `ifnull(n,n)` varchar(3) default NULL, - `ifnull(o,o)` varchar(10) default NULL + `ifnull(a,a)` tinyint(4) DEFAULT NULL, + `ifnull(b,b)` smallint(6) DEFAULT NULL, + `ifnull(c,c)` mediumint(8) DEFAULT NULL, + `ifnull(d,d)` int(11) DEFAULT NULL, + `ifnull(e,e)` bigint(20) DEFAULT NULL, + `ifnull(f,f)` float(3,2) DEFAULT NULL, + `ifnull(g,g)` double(4,3) DEFAULT NULL, + `ifnull(h,h)` decimal(5,4) DEFAULT NULL, + `ifnull(i,i)` year(4) DEFAULT NULL, + `ifnull(j,j)` date DEFAULT NULL, + `ifnull(k,k)` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `ifnull(l,l)` datetime DEFAULT NULL, + `ifnull(m,m)` varchar(1) DEFAULT NULL, + `ifnull(n,n)` varchar(3) DEFAULT NULL, + `ifnull(o,o)` varchar(10) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1,t2; create table t1(str varchar(10) default 'def',strnull varchar(10),intg int default '10',rel double default '3.14'); diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index de782f9a5e4..ac1270d33a0 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -91,10 +91,10 @@ col1 col2 col3 col4 show create table t2; Table Create Table t2 CREATE TABLE `t2` ( - `col1` double default NULL, - `col2` double(22,5) default NULL, - `col3` double default NULL, - `col4` double default NULL + `col1` double DEFAULT NULL, + `col2` double(22,5) DEFAULT NULL, + `col3` double DEFAULT NULL, + `col4` double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1,t2; create table t1 (a float); @@ -237,7 +237,7 @@ d show create table t3; Table Create Table t3 CREATE TABLE `t3` ( - `d` double default NULL + `d` double DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1, t2, t3; create table t1 select 105213674794682365.00 + 0.0 x; diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 2c8fa5cb896..275f3357c65 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -554,7 +554,7 @@ aa show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `a` varbinary(2) NOT NULL default '' + `a` varbinary(2) NOT NULL DEFAULT '' ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT 12 as a UNION select 12.2 as a; @@ -655,7 +655,7 @@ f show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `f` varbinary(12) default NULL + `f` varbinary(12) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; create table t1 SELECT y from t2 UNION select da from t2; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 46b09b55565..9d20a8a16c7 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3338,8 +3338,6 @@ v1 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VI Warnings: Note 1449 There is no 'no_such'@'user_1' registered ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; -Warnings: -Note 1449 There is no 'no_such'@'user_1' registered SHOW CREATE VIEW v1; View Create View v1 CREATE ALGORITHM=MERGE DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` From 7eb78d8d04602aa71e10178fe34426cebe1e1c55 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Fri, 23 Mar 2007 01:46:02 +0400 Subject: [PATCH 15/17] merging --- mysql-test/t/gis.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 7ae6e3adda7..9cf42070f2f 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -1,5 +1,6 @@ -- source include/have_geometry.inc + # # Spatial objects # From e06a8826c98c970282de63cbfa97a8937b8d1097 Mon Sep 17 00:00:00 2001 From: "holyfoot/hf@mysql.com/hfmain.(none)" <> Date: Fri, 23 Mar 2007 10:16:30 +0400 Subject: [PATCH 16/17] fixes to make embedded-server test working --- mysql-test/r/view.result | 32 ---------------------- mysql-test/r/view_grant.result | 33 +++++++++++++++++++++++ mysql-test/t/query_cache_sql_prepare.test | 2 +- mysql-test/t/view.test | 25 ----------------- mysql-test/t/view_grant.test | 27 +++++++++++++++++++ 5 files changed, 61 insertions(+), 58 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 9d20a8a16c7..0fa7cda1187 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3321,36 +3321,4 @@ DROP TABLE `t-2`; DROP VIEW `v-2`; DROP DATABASE `d-1`; USE test; -DROP VIEW IF EXISTS v1; -DROP TABLE IF EXISTS t1; -CREATE TABLE t1 (i INT); -CREATE VIEW v1 AS SELECT * FROM t1; -ALTER VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` -ALTER DEFINER=no_such@user_1 VIEW v1 AS SELECT * FROM t1; -Warnings: -Note 1449 There is no 'no_such'@'user_1' registered -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` -Warnings: -Note 1449 There is no 'no_such'@'user_1' registered -ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=MERGE DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` -Warnings: -Note 1449 There is no 'no_such'@'user_1' registered -ALTER ALGORITHM=TEMPTABLE DEFINER=no_such@user_2 VIEW v1 AS SELECT * FROM t1; -Warnings: -Note 1449 There is no 'no_such'@'user_2' registered -SHOW CREATE VIEW v1; -View Create View -v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`no_such`@`user_2` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` -Warnings: -Note 1449 There is no 'no_such'@'user_2' registered -DROP VIEW v1; -DROP TABLE t1; End of 5.1 tests. diff --git a/mysql-test/r/view_grant.result b/mysql-test/r/view_grant.result index a8770bdac41..2a0bedc1443 100644 --- a/mysql-test/r/view_grant.result +++ b/mysql-test/r/view_grant.result @@ -797,3 +797,36 @@ v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VI DROP USER u26813@localhost; DROP DATABASE db26813; End of 5.0 tests. +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; +ALTER VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` +ALTER DEFINER=no_such@user_1 VIEW v1 AS SELECT * FROM t1; +Warnings: +Note 1449 There is no 'no_such'@'user_1' registered +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` +Warnings: +Note 1449 There is no 'no_such'@'user_1' registered +ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=MERGE DEFINER=`no_such`@`user_1` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` +Warnings: +Note 1449 There is no 'no_such'@'user_1' registered +ALTER ALGORITHM=TEMPTABLE DEFINER=no_such@user_2 VIEW v1 AS SELECT * FROM t1; +Warnings: +Note 1449 There is no 'no_such'@'user_2' registered +SHOW CREATE VIEW v1; +View Create View +v1 CREATE ALGORITHM=TEMPTABLE DEFINER=`no_such`@`user_2` SQL SECURITY DEFINER VIEW `v1` AS select `t1`.`i` AS `i` from `t1` +Warnings: +Note 1449 There is no 'no_such'@'user_2' registered +DROP VIEW v1; +DROP TABLE t1; +End of 5.1 tests. diff --git a/mysql-test/t/query_cache_sql_prepare.test b/mysql-test/t/query_cache_sql_prepare.test index 69b504e2fd1..98141153002 100644 --- a/mysql-test/t/query_cache_sql_prepare.test +++ b/mysql-test/t/query_cache_sql_prepare.test @@ -5,7 +5,7 @@ -- source include/have_query_cache.inc -connect (con1,127.0.0.1,root,,test,$MASTER_MYPORT,); +connect (con1,localhost,root,,test,$MASTER_MYPORT,); connection default; set global query_cache_size=100000; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 026a08bf365..4961d95d0ac 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -3216,29 +3216,4 @@ DROP VIEW `v-2`; DROP DATABASE `d-1`; USE test; - -# -# Test that ALTER VIEW accepts DEFINER and ALGORITHM, see bug#16425. -# ---disable_warnings -DROP VIEW IF EXISTS v1; -DROP TABLE IF EXISTS t1; ---enable_warnings - -CREATE TABLE t1 (i INT); -CREATE VIEW v1 AS SELECT * FROM t1; - -ALTER VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -ALTER DEFINER=no_such@user_1 VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; -ALTER ALGORITHM=TEMPTABLE DEFINER=no_such@user_2 VIEW v1 AS SELECT * FROM t1; -SHOW CREATE VIEW v1; - -DROP VIEW v1; -DROP TABLE t1; - - --echo End of 5.1 tests. diff --git a/mysql-test/t/view_grant.test b/mysql-test/t/view_grant.test index acdfec90601..64cafe89d10 100644 --- a/mysql-test/t/view_grant.test +++ b/mysql-test/t/view_grant.test @@ -1073,3 +1073,30 @@ DROP DATABASE db26813; disconnect u1; --echo End of 5.0 tests. + + +# +# Test that ALTER VIEW accepts DEFINER and ALGORITHM, see bug#16425. +# +connection default; +--disable_warnings +DROP VIEW IF EXISTS v1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT); +CREATE VIEW v1 AS SELECT * FROM t1; + +ALTER VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +ALTER DEFINER=no_such@user_1 VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +ALTER ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; +ALTER ALGORITHM=TEMPTABLE DEFINER=no_such@user_2 VIEW v1 AS SELECT * FROM t1; +SHOW CREATE VIEW v1; + +DROP VIEW v1; +DROP TABLE t1; + +--echo End of 5.1 tests. From b9a317de708a30f977e94e23e60c286e638d8785 Mon Sep 17 00:00:00 2001 From: "dfischer/mysqldev@mysql.com/production.mysql.com" <> Date: Fri, 23 Mar 2007 07:27:46 +0100 Subject: [PATCH 17/17] Raise version number after cloning 5.1.17-beta --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 99f05be35a5..4a70337b048 100644 --- a/configure.in +++ b/configure.in @@ -7,7 +7,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 5.1.17-beta) +AM_INIT_AUTOMAKE(mysql, 5.1.18-beta) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10