From 33b6bab87177851b134da6b0c0596fdba2a906e8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Dec 2006 15:08:41 +0400 Subject: [PATCH 01/55] Fix for bug #23616: Week() changed behaviour between 5.0.22 and 5.0.24 Consider double values as legal date{time} function's arguments (i.e. allow dates in internal format YYYYMMDDHHMMSS.XXXXXX). mysql-test/r/func_sapdb.result: Fix for bug #23616: Week() changed behaviour between 5.0.22 and 5.0.24 - result adjusted. mysql-test/r/func_time.result: Fix for bug #23616: Week() changed behaviour between 5.0.22 and 5.0.24 - test result. mysql-test/t/func_time.test: Fix for bug #23616: Week() changed behaviour between 5.0.22 and 5.0.24 - test case. sql-common/my_time.c: Fix for bug #23616: Week() changed behaviour between 5.0.22 and 5.0.24 - consider '.' as an acceptable separator for dates like YYYYYMMDDHHMMSS.XXXXXX --- mysql-test/r/func_sapdb.result | 4 +--- mysql-test/r/func_time.result | 4 ++++ mysql-test/t/func_time.test | 7 +++++++ sql-common/my_time.c | 2 +- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/func_sapdb.result b/mysql-test/r/func_sapdb.result index 447cadb9898..7c46b966dab 100644 --- a/mysql-test/r/func_sapdb.result +++ b/mysql-test/r/func_sapdb.result @@ -229,9 +229,7 @@ a 10000 select microsecond(19971231235959.01) as a; a -0 -Warnings: -Warning 1292 Truncated incorrect time value: '19971231235959.01' +10000 select date_add("1997-12-31",INTERVAL "10.09" SECOND_MICROSECOND) as a; a 1997-12-31 00:00:10.090000 diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index fdfb42c878d..fc218067d29 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -854,4 +854,8 @@ H select last_day('0000-00-00'); last_day('0000-00-00') NULL +select isnull(week(now() + 0)), isnull(week(now() + 0.2)), +week(20061108), week(20061108.01), week(20061108085411.000002); +isnull(week(now() + 0)) isnull(week(now() + 0.2)) week(20061108) week(20061108.01) week(20061108085411.000002) +0 0 45 45 45 End of 4.1 tests diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index fa12c45db04..2fb5ea04a19 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -492,4 +492,11 @@ union select last_day('0000-00-00'); +# +# Bug 23616: datetime functions with double argumets +# + +select isnull(week(now() + 0)), isnull(week(now() + 0.2)), + week(20061108), week(20061108.01), week(20061108085411.000002); + --echo End of 4.1 tests diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 2d3d71e646c..77226da3dc8 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -145,7 +145,7 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time, digits= (uint) (pos-str); start_loop= 0; /* Start of scan loop */ date_len[format_position[0]]= 0; /* Length of year field */ - if (pos == end) + if (pos == end || *pos == '.') { /* Found date in internal format (only numbers like YYYYMMDD) */ year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2; From cccad802ef31bcf96badaa67f4224fbe3b8d5985 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jan 2007 19:58:04 +0300 Subject: [PATCH 02/55] Added a test case for bug #20293 "group by cuts off value from time_format" --- mysql-test/r/func_time.result | 4 ++++ mysql-test/t/func_time.test | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 45c05f0b5b5..08ae7416db3 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1207,3 +1207,7 @@ SET NAMES DEFAULT; select str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE NULL +SELECT TIME_FORMAT(SEC_TO_TIME(a),"%H:%i:%s") FROM (SELECT 3020399 AS a UNION SELECT 3020398 ) x GROUP BY 1; +TIME_FORMAT(SEC_TO_TIME(a),"%H:%i:%s") +838:59:58 +838:59:59 diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index a69cbb67c5b..920c79c27c9 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -713,3 +713,11 @@ SET NAMES DEFAULT; # select str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; + + +# +# Bug #20293: group by cuts off value from time_format +# +# Check if using GROUP BY with TIME_FORMAT() produces correct results + +SELECT TIME_FORMAT(SEC_TO_TIME(a),"%H:%i:%s") FROM (SELECT 3020399 AS a UNION SELECT 3020398 ) x GROUP BY 1; From ef0132685d985bb283e3f4acaf4bfc12ce69b06f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 25 Jan 2007 20:00:12 +0300 Subject: [PATCH 03/55] BUG#23527: set global query_cache_size can crash the server under high load MySQL server could crash if two or more threads would initiate query cache resize at the moments very close in time. The problem was introduced with the fix of bug 21051 in 5.0 and 5.1: simultaneous query cache resizes would wait for the first one in progress, but then each thread would try to finish the operation, accessing the data that was already reset (attempt to dereference 'bins' pointer, which may be NULL already). The solution is to check after synchronization if another thread has done the reset already (test 'query_cache_size > 0' again). No test case is provided because the bug is a subject to a race. sql/sql_cache.cc: We release 'structure_guard_mutex' in flush_cache(), so after the call we check if another thread had reset the cache before us. --- sql/sql_cache.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 635c65eb726..47632f6f105 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1766,8 +1766,18 @@ void Query_cache::free_cache() { DBUG_ENTER("Query_cache::free_cache"); if (query_cache_size > 0) - { flush_cache(); + /* + There may be two free_cache() calls in progress, because we + release 'structure_guard_mutex' in flush_cache(). When the second + flush_cache() wakes up from the wait on 'COND_flush_finished', the + first call to free_cache() has done its job. So we have to test + 'query_cache_size > 0' the second time to see if the cache wasn't + reset by other thread, or if it was reset and was re-enabled then. + If the cache was reset, then we have nothing to do here. + */ + if (query_cache_size > 0) + { #ifndef DBUG_OFF if (bins[0].free_blocks == 0) { @@ -1809,6 +1819,12 @@ void Query_cache::free_cache() flush_in_progress flag and releases the lock, so other threads may proceed skipping the cache as if it is disabled. Concurrent flushes are performed in turn. + + After flush_cache() call, the cache is flushed, all the freed + memory is accumulated in bin[0], and the 'structure_guard_mutex' + is locked. However, since we could release the mutex during + execution, the rest of the cache state could have been changed, + and should not be relied on. */ void Query_cache::flush_cache() From a1e20e04d8f91f607a6c498989743f205dafa297 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Jan 2007 17:32:52 -0700 Subject: [PATCH 04/55] Bug#21904 (parser problem when using IN with a double "(())") Before this fix, a IN predicate of the form: "IN (( subselect ))", with two parenthesis, would be evaluated as a single row subselect: if the subselect returns more that 1 row, the statement would fail. The SQL:2003 standard defines a special exception in the specification, and mandates that this particular form of IN predicate shall be equivalent to "IN ( subselect )", which involves a table subquery and works with more than 1 row. This fix implements "IN (( subselect ))", "IN ((( subselect )))" etc as per the SQL:2003 requirement. All the details related to the implementation of this change have been commented in the code, and the relevant sections of the SQL:2003 spec are given for reference, so they are not repeated here. Having access to the spec is a requirement to review in depth this patch. mysql-test/r/subselect.result: Implement IN predicate special exceptions with subselects. mysql-test/t/subselect.test: Implement IN predicate special exceptions with subselects. sql/item_subselect.cc: Implement IN predicate special exceptions with subselects. sql/item_subselect.h: Implement IN predicate special exceptions with subselects. sql/sql_yacc.yy: Implement IN predicate special exceptions with subselects, cleanup. --- mysql-test/r/subselect.result | 113 +++++++++++++++++++++++++++++++++ mysql-test/t/subselect.test | 100 +++++++++++++++++++++++++++++ sql/item_subselect.cc | 30 +++++++++ sql/item_subselect.h | 16 +++++ sql/sql_yacc.yy | 115 +++++++++++++++++++++++++++++----- 5 files changed, 357 insertions(+), 17 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 43247b56096..b22912e0a93 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -3592,3 +3592,116 @@ FROM t1) t; COUNT(*) 3000 DROP TABLE t1,t2; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t1xt2; +CREATE TABLE t1 ( +id_1 int(5) NOT NULL, +t varchar(4) DEFAULT NULL +); +CREATE TABLE t2 ( +id_2 int(5) NOT NULL, +t varchar(4) DEFAULT NULL +); +CREATE TABLE t1xt2 ( +id_1 int(5) NOT NULL, +id_2 int(5) NOT NULL +); +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'); +INSERT INTO t2 VALUES (2, 'bb'), (3, 'cc'), (4, 'dd'), (12, 'aa'); +INSERT INTO t1xt2 VALUES (2, 2), (3, 3), (4, 4); +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); +id_1 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); +id_1 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); +id_1 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); +id_1 +1 +2 +3 +4 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1))); +id_1 +1 +2 +3 +4 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1)))); +id_1 +1 +2 +3 +4 +insert INTO t1xt2 VALUES (1, 12); +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); +id_1 +1 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); +id_1 +1 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); +id_1 +1 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); +id_1 +2 +3 +4 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); +id_1 +2 +3 +4 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); +id_1 +2 +3 +4 +insert INTO t1xt2 VALUES (2, 12); +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); +id_1 +1 +2 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); +id_1 +1 +2 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); +id_1 +1 +2 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); +id_1 +3 +4 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); +id_1 +3 +4 +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); +id_1 +3 +4 +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t1xt2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0bbbc5a793e..eac2331dc0b 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2496,3 +2496,103 @@ SELECT SQL_NO_CACHE COUNT(*) FROM t1) t; DROP TABLE t1,t2; + +# +# Bug#21904 (parser problem when using IN with a double "(())") +# + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP TABLE IF EXISTS t1xt2; +--enable_warnings + +CREATE TABLE t1 ( + id_1 int(5) NOT NULL, + t varchar(4) DEFAULT NULL +); + +CREATE TABLE t2 ( + id_2 int(5) NOT NULL, + t varchar(4) DEFAULT NULL +); + +CREATE TABLE t1xt2 ( + id_1 int(5) NOT NULL, + id_2 int(5) NOT NULL +); + +INSERT INTO t1 VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'); + +INSERT INTO t2 VALUES (2, 'bb'), (3, 'cc'), (4, 'dd'), (12, 'aa'); + +INSERT INTO t1xt2 VALUES (2, 2), (3, 3), (4, 4); + +# subselect returns 0 rows + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 where t1.id_1 = t1xt2.id_1)))); + +insert INTO t1xt2 VALUES (1, 12); + +# subselect returns 1 row + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); + +insert INTO t1xt2 VALUES (2, 12); + +# subselect returns more than 1 row + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN ((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1))); + +SELECT DISTINCT t1.id_1 FROM t1 WHERE +(12 NOT IN (((SELECT t1xt2.id_2 FROM t1xt2 WHERE t1.id_1 = t1xt2.id_1)))); + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t1xt2; + diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index bffecb3c84c..21624f23267 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -52,6 +52,10 @@ Item_subselect::Item_subselect(): void Item_subselect::init(st_select_lex *select_lex, select_subselect *result) { + /* + Please see Item_singlerow_subselect::invalidate_and_restore_select_lex(), + which depends on alterations to the parse tree implemented here. + */ DBUG_ENTER("Item_subselect::init"); DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex)); @@ -92,6 +96,12 @@ void Item_subselect::init(st_select_lex *select_lex, DBUG_VOID_RETURN; } +st_select_lex * +Item_subselect::get_select_lex() +{ + return unit->first_select(); +} + void Item_subselect::cleanup() { DBUG_ENTER("Item_subselect::cleanup"); @@ -265,6 +275,26 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) DBUG_VOID_RETURN; } +st_select_lex * +Item_singlerow_subselect::invalidate_and_restore_select_lex() +{ + DBUG_ENTER("Item_singlerow_subselect::invalidate_and_restore_select_lex"); + st_select_lex *result= get_select_lex(); + + DBUG_ASSERT(result); + + /* + This code restore the parse tree in it's state before the execution of + Item_singlerow_subselect::Item_singlerow_subselect(), + and in particular decouples this object from the SELECT_LEX, + so that the SELECT_LEX can be used with a different flavor + or Item_subselect instead, as part of query rewriting. + */ + unit->item= NULL; + + DBUG_RETURN(result); +} + Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param, Item_subselect *parent, st_select_lex *select_lex, diff --git a/sql/item_subselect.h b/sql/item_subselect.h index f1be99353cc..c866cafd8c0 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -126,6 +126,12 @@ public: virtual void reset_value_registration() {} enum_parsing_place place() { return parsing_place; } + /** + Get the SELECT_LEX structure associated with this Item. + @return the SELECT_LEX structure associated with this Item + */ + st_select_lex* get_select_lex(); + friend class select_subselect; friend class Item_in_optimizer; friend bool Item_field::fix_fields(THD *, Item **); @@ -169,6 +175,16 @@ public: bool null_inside(); void bring_value(); + /** + This method is used to implement a special case of semantic tree + rewriting, mandated by a SQL:2003 exception in the specification. + The only caller of this method is handle_sql2003_note184_exception(), + see the code there for more details. + Do not call this method for other purposes. + @return the SELECT_LEX structure that was given in the constructor. + */ + st_select_lex* invalidate_and_restore_select_lex(); + friend class select_singlerow_subselect; }; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 4f647fb1dbd..0e7b6236ed5 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -277,6 +277,81 @@ void case_stmt_action_end_case(LEX *lex, bool simple) lex->sphead->do_cont_backpatch(); } +/** + Helper to resolve the SQL:2003 Syntax exception 1) in . + See SQL:2003, Part 2, section 8.4 , Note 184, page 383. + This function returns the proper item for the SQL expression + left [NOT] IN ( expr ) + @param thd the current thread + @param left the in predicand + @param equal true for IN predicates, false for NOT IN predicates + @param expr first and only expression of the in value list + @return an expression representing the IN predicate. +*/ +Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal, + Item *expr) +{ + /* + Relevant references for this issue: + - SQL:2003, Part 2, section 8.4 , page 383, + - SQL:2003, Part 2, section 7.2 , page 296, + - SQL:2003, Part 2, section 6.3 , page 174, + - SQL:2003, Part 2, section 7.15 , page 370, + - SQL:2003 Feature F561, "Full value expressions". + + The exception in SQL:2003 Note 184 means: + Item_singlerow_subselect, which corresponds to a , + should be re-interpreted as an Item_in_subselect, which corresponds + to a when used inside an . + + Our reading of Note 184 is reccursive, so that all: + - IN (( )) + - IN ((( ))) + - IN '('^N ')'^N + - etc + should be interpreted as a
, no matter how deep in the + expression the is. + */ + + Item *result; + + DBUG_ENTER("handle_sql2003_note184_exception"); + + if (expr->type() == Item::SUBSELECT_ITEM) + { + Item_subselect *expr2 = (Item_subselect*) expr; + + if (expr2->substype() == Item_subselect::SINGLEROW_SUBS) + { + Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2; + st_select_lex *subselect; + + /* + Implement the mandated change, by altering the semantic tree: + left IN Item_singlerow_subselect(subselect) + is modified to + left IN (subselect) + which is represented as + Item_in_subselect(left, subselect) + */ + subselect= expr3->invalidate_and_restore_select_lex(); + result= new (thd->mem_root) Item_in_subselect(left, subselect); + + if (! equal) + result = negate_expression(thd, result); + + DBUG_RETURN(result); + } + } + + if (equal) + result= new (thd->mem_root) Item_func_eq(left, expr); + else + result= new (thd->mem_root) Item_func_ne(left, expr); + + DBUG_RETURN(result); +} + %} %union { int num; @@ -4401,31 +4476,37 @@ bool_pri: | predicate ; predicate: - bit_expr IN_SYM '(' subselect ')' - { $$= new Item_in_subselect($1, $4); } - | bit_expr not IN_SYM '(' subselect ')' - { $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); } + bit_expr IN_SYM '(' subselect ')' + { + $$= new (YYTHD->mem_root) Item_in_subselect($1, $4); + } + | bit_expr not IN_SYM '(' subselect ')' + { + THD *thd= YYTHD; + Item *item= new (thd->mem_root) Item_in_subselect($1, $5); + $$= negate_expression(thd, item); + } | bit_expr IN_SYM '(' expr ')' { - $$= new Item_func_eq($1, $4); + $$= handle_sql2003_note184_exception(YYTHD, $1, true, $4); } - | bit_expr IN_SYM '(' expr ',' expr_list ')' - { - $6->push_front($4); - $6->push_front($1); - $$= new Item_func_in(*$6); + | bit_expr IN_SYM '(' expr ',' expr_list ')' + { + $6->push_front($4); + $6->push_front($1); + $$= new (YYTHD->mem_root) Item_func_in(*$6); } | bit_expr not IN_SYM '(' expr ')' { - $$= new Item_func_ne($1, $5); + $$= handle_sql2003_note184_exception(YYTHD, $1, false, $5); } - | bit_expr not IN_SYM '(' expr ',' expr_list ')' + | bit_expr not IN_SYM '(' expr ',' expr_list ')' { - $7->push_front($5); - $7->push_front($1); - Item_func_in *item = new Item_func_in(*$7); - item->negate(); - $$= item; + $7->push_front($5); + $7->push_front($1); + Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7); + item->negate(); + $$= item; } | bit_expr BETWEEN_SYM bit_expr AND_SYM predicate { $$= new Item_func_between($1,$3,$5); } From f65038bd67576e1b53fe99db092431f7fbdc2c41 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Feb 2007 09:36:17 -0700 Subject: [PATCH 05/55] Improved comments --- sql/item_subselect.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql/item_subselect.h b/sql/item_subselect.h index a125a119ad8..97ded8bdd55 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -179,7 +179,11 @@ public: rewriting, mandated by a SQL:2003 exception in the specification. The only caller of this method is handle_sql2003_note184_exception(), see the code there for more details. - Do not call this method for other purposes. + Note that this method breaks the object internal integrity, by + removing it's association with the corresponding SELECT_LEX, + making this object orphan from the parse tree. + No other method, beside the destructor, should be called on this + object, as it is now invalid. @return the SELECT_LEX structure that was given in the constructor. */ st_select_lex* invalidate_and_restore_select_lex(); From 86b715a79f06d0a276e1e6f72fca3cb384890bfe Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 4 Feb 2007 16:49:24 +0300 Subject: [PATCH 06/55] BUG#25897: Some queries are no longer possible after a CREATE VIEW fails The bug was introduced with the push of the fix for bug#20953: after the error on view creation we never reset the error state, so some valid statements would give the same error after that. The solution is to properly reset the error state. mysql-test/r/view.result: Add result for bug#25897: Some queries are no longer possible after a CREATE VIEW fails. mysql-test/t/view.test: Add test case for bug#25897: Some queries are no longer possible after a CREATE VIEW fails. sql/sql_lex.cc: Add st_parsing_options::reset() method, call it from lex_start(). sql/sql_lex.h: Add st_parsing_options::reset() method, call it from constructor. --- mysql-test/r/view.result | 10 ++++++++++ mysql-test/t/view.test | 18 ++++++++++++++++++ sql/sql_lex.cc | 11 +++++++++++ sql/sql_lex.h | 6 ++---- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f8584275a5a..649b2827b1b 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3023,4 +3023,14 @@ SHOW CREATE VIEW v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _latin1'The\ZEnd' AS `TheEnd` DROP VIEW v1; +DROP VIEW IF EXISTS v1; +SELECT * FROM (SELECT 1) AS t; +1 +1 +CREATE VIEW v1 AS SELECT * FROM (SELECT 1) AS t; +ERROR HY000: View's SELECT contains a subquery in the FROM clause +# Previously the following would fail. +SELECT * FROM (SELECT 1) AS t; +1 +1 End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a34a1ba117d..a5454b302f1 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2975,4 +2975,22 @@ SHOW CREATE VIEW v1; DROP VIEW v1; + +# +# BUG#25897: Some queries are no longer possible after a CREATE VIEW +# fails +# +--disable_warnings +DROP VIEW IF EXISTS v1; +--enable_warnings + +let $query = SELECT * FROM (SELECT 1) AS t; + +eval $query; +--error ER_VIEW_SELECT_DERIVED +eval CREATE VIEW v1 AS $query; +--echo # Previously the following would fail. +eval $query; + + --echo End of 5.0 tests. diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index f14856e23fa..d60bfc9ab4c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -99,6 +99,16 @@ void lex_free(void) } +void +st_parsing_options::reset() +{ + allows_variable= TRUE; + allows_select_into= TRUE; + allows_select_procedure= TRUE; + allows_derived= TRUE; +} + + /* This is called before every query that is to be parsed. Because of this, it's critical to not do too much things here. @@ -149,6 +159,7 @@ void lex_start(THD *thd, uchar *buf,uint length) lex->safe_to_cache_query= 1; lex->time_zone_tables_used= 0; lex->leaf_tables_insert= 0; + lex->parsing_options.reset(); lex->empty_field_list_on_rset= 0; lex->select_lex.select_number= 1; lex->next_state=MY_LEX_START; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5731e009cb4..eaa907b6ed3 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -866,10 +866,8 @@ struct st_parsing_options bool allows_select_procedure; bool allows_derived; - st_parsing_options() - : allows_variable(TRUE), allows_select_into(TRUE), - allows_select_procedure(TRUE), allows_derived(TRUE) - {} + st_parsing_options() { reset(); } + void reset(); }; From 372fc7e443eaa6fcffd1cb33e9f8a28e2e76542a Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Feb 2007 16:01:22 -0700 Subject: [PATCH 07/55] Bug#12976 (stored procedures local variables of type bit) Before this change, a local variables in stored procedures / stored functions or triggers, when declared with a type of bit(N), would not evaluate their value properly. The problem was that the data was incorrectly typed as a string, causing for example bit b'1', implemented as a byte 0x01, to be interpreted as a string starting with the character 0x01. This later would cause implicit conversions to integers or booleans to fail. The root cause of this problem was an incorrect translation between field types, like bit(N), and internal types used when representing values in Item objects. Also, before this change, the function HEX() would sometime print extra "0" characters when invoked with bit(N) values. With this fix, the type translation (sp_map_result_type, sp_map_item_type) has been changed so that bit(N) fields are represented with integer values. A consequence is that, for the function HEX(), when called with a stored procedure local variable of type bit(N) as argument, HEX() is provided with an integer instead of a string, and therefore does not print "0" padding. A test case for Bug 12976 was present in the test suite, and has been updated. mysql-test/r/sp-vars.result: Local stored procedure variables of type bit(N) are integer values. mysql-test/t/sp-vars.test: Local stored procedure variables of type bit(N) are integer values. sql/sp_head.cc: Local stored procedure variables of type bit(N) are integer values. --- mysql-test/r/sp-vars.result | 62 +++++++++++++++++++++++++++++++---- mysql-test/t/sp-vars.test | 65 +++++++++++++++++++++++++++++++++---- sql/sp_head.cc | 2 ++ 3 files changed, 115 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result index f362187cd14..6090dfdf737 100644 --- a/mysql-test/r/sp-vars.result +++ b/mysql-test/r/sp-vars.result @@ -431,17 +431,17 @@ SELECT HEX(v10); END| CALL p1(); HEX(v1) -01 +1 HEX(v2) -00 +0 HEX(v3) -05 +5 HEX(v4) 5555555555555555 HEX(v5) -07 +7 HEX(v6) -0000000000000005 +5 HEX(v7) 80 HEX(v8) @@ -748,12 +748,60 @@ HEX(b) b = 0 b = FALSE b IS FALSE b = 1 b = TRUE b IS TRUE 1 0 0 0 1 1 1 call p2(); HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE -00 1 1 1 0 0 0 +0 1 1 1 0 0 0 HEX(vb) vb = 0 vb = FALSE vb IS FALSE vb = 1 vb = TRUE vb IS TRUE -01 0 0 1 1 1 0 +1 0 0 0 1 1 1 DROP TABLE t1; DROP PROCEDURE p1; DROP PROCEDURE p2; +DROP TABLE IF EXISTS table_12976_a; +DROP TABLE IF EXISTS table_12976_b; +DROP PROCEDURE IF EXISTS proc_12976_a; +DROP PROCEDURE IF EXISTS proc_12976_b; +CREATE TABLE table_12976_a (val bit(1)); +CREATE TABLE table_12976_b( +appname varchar(15), +emailperm bit not null default 1, +phoneperm bit not null default 0); +insert into table_12976_b values ('A', b'1', b'1'), ('B', b'0', b'0'); +CREATE PROCEDURE proc_12976_a() +BEGIN +declare localvar bit(1); +SELECT val INTO localvar FROM table_12976_a; +SELECT coalesce(localvar, 1)+1, coalesce(val, 1)+1 FROM table_12976_a; +END|| +CREATE PROCEDURE proc_12976_b( +name varchar(15), +out ep bit, +out msg varchar(10)) +BEGIN +SELECT emailperm into ep FROM table_12976_b where (appname = name); +IF ep is true THEN +SET msg = 'True'; +ELSE +SET msg = 'False'; +END IF; +END|| +INSERT table_12976_a VALUES (0); +call proc_12976_a(); +coalesce(localvar, 1)+1 coalesce(val, 1)+1 +1 1 +UPDATE table_12976_a set val=1; +call proc_12976_a(); +coalesce(localvar, 1)+1 coalesce(val, 1)+1 +2 2 +call proc_12976_b('A', @ep, @msg); +select @ep, @msg; +@ep @msg +1 True +call proc_12976_b('B', @ep, @msg); +select @ep, @msg; +@ep @msg +0 False +DROP TABLE table_12976_a; +DROP TABLE table_12976_b; +DROP PROCEDURE proc_12976_a; +DROP PROCEDURE proc_12976_b; --------------------------------------------------------------- BUG#9572 diff --git a/mysql-test/t/sp-vars.test b/mysql-test/t/sp-vars.test index 7cf92dc5d0d..0014dc1f6af 100644 --- a/mysql-test/t/sp-vars.test +++ b/mysql-test/t/sp-vars.test @@ -500,8 +500,6 @@ DROP PROCEDURE p1; # # Test case for BUG#12976: Boolean values reversed in stored procedures? # -# TODO: test case failed. -# ########################################################################### --echo @@ -566,13 +564,8 @@ BEGIN END| delimiter ;| -# The expected and correct result. - call p1(); -# The wrong result. Note that only hex(vb) works, but is printed with two -# digits for some reason in this case. - call p2(); # @@ -583,6 +576,64 @@ DROP TABLE t1; DROP PROCEDURE p1; DROP PROCEDURE p2; +# Additional tests for Bug#12976 + +--disable_warnings +DROP TABLE IF EXISTS table_12976_a; +DROP TABLE IF EXISTS table_12976_b; +DROP PROCEDURE IF EXISTS proc_12976_a; +DROP PROCEDURE IF EXISTS proc_12976_b; +--enable_warnings + +CREATE TABLE table_12976_a (val bit(1)); + +CREATE TABLE table_12976_b( + appname varchar(15), + emailperm bit not null default 1, + phoneperm bit not null default 0); + +insert into table_12976_b values ('A', b'1', b'1'), ('B', b'0', b'0'); + +delimiter ||; +CREATE PROCEDURE proc_12976_a() +BEGIN + declare localvar bit(1); + SELECT val INTO localvar FROM table_12976_a; + SELECT coalesce(localvar, 1)+1, coalesce(val, 1)+1 FROM table_12976_a; +END|| + +CREATE PROCEDURE proc_12976_b( + name varchar(15), + out ep bit, + out msg varchar(10)) +BEGIN + SELECT emailperm into ep FROM table_12976_b where (appname = name); + IF ep is true THEN + SET msg = 'True'; + ELSE + SET msg = 'False'; + END IF; +END|| + +delimiter ;|| + +INSERT table_12976_a VALUES (0); +call proc_12976_a(); +UPDATE table_12976_a set val=1; +call proc_12976_a(); + +call proc_12976_b('A', @ep, @msg); +select @ep, @msg; + +call proc_12976_b('B', @ep, @msg); +select @ep, @msg; + +DROP TABLE table_12976_a; +DROP TABLE table_12976_b; +DROP PROCEDURE proc_12976_a; +DROP PROCEDURE proc_12976_b; + + ########################################################################### # # Test case for BUG#9572: Stored procedures: variable type declarations diff --git a/sql/sp_head.cc b/sql/sp_head.cc index de0edabda3e..2e8ecd20000 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -36,6 +36,7 @@ Item_result sp_map_result_type(enum enum_field_types type) { switch (type) { + case MYSQL_TYPE_BIT: case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_LONG: @@ -58,6 +59,7 @@ Item::Type sp_map_item_type(enum enum_field_types type) { switch (type) { + case MYSQL_TYPE_BIT: case MYSQL_TYPE_TINY: case MYSQL_TYPE_SHORT: case MYSQL_TYPE_LONG: From 774cddae33de2f9333f07ab56a41cb53e29772da Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 9 Feb 2007 17:08:37 +0100 Subject: [PATCH 08/55] Raise version number after cloning 4.0.30 --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index 10f8ca37a4b..f0307c7de2d 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.30) +AM_INIT_AUTOMAKE(mysql, 4.0.31) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 From a475ed7c6b6607272afb87517ae6ab1f3a397f41 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 12 Feb 2007 13:59:29 -0700 Subject: [PATCH 09/55] Bug#24532 (The return data type of IS TRUE is different from similar operations) Before this change, the boolean predicates: - X IS TRUE, - X IS NOT TRUE, - X IS FALSE, - X IS NOT FALSE were implemented by expanding the Item tree in the parser, by using a construct like: Item_func_if(Item_func_ifnull(X, ), , ) Each was a constant integer, either 0 or 1. A bug in the implementation of the function IF(a, b, c), in Item_func_if::fix_length_and_dec(), would cause the following : When the arguments b and c are both unsigned, the result type of the function was signed, instead of unsigned. When the result of the if function is signed, space for the sign could be counted twice (in the max() expression for a signed argument, and in the total), causing the member max_length to be too high. An effect of this is that the final type of IF(x, int(1), int(1)) would be int(2) instead of int(1). With this fix, the problems found in Item_func_if::fix_length_and_dec() have been fixed. While it's semantically correct to represent 'X IS TRUE' with Item_func_if(Item_func_ifnull(X, ), , ), there are however more problems with this construct. a) Building the parse tree involves : - creating 5 Item instances (3 ints, 1 ifnull, 1 if), - creating each Item calls my_pthread_getspecific_ptr() once in the operator new(size), and a second time in the Item::Item() constructor, resulting in a total of 10 calls to get the current thread. Evaluating the expression involves evaluating up to 4 nodes at runtime. This representation could be greatly simplified and improved. b) Transforming the parse tree internally with if(ifnull(...)) is fine as long as this transformation is internal to the server implementation. With views however, the result of the parse tree is later exposed by the ::print() functions, and stored as part of the view definition. Doing this has long term consequences: 1) The original semantic 'X IS TRUE' is lost, and replaced by the if(ifnull(...)) expression. As a result, SHOW CREATE VIEW does not restore the original code. 2) Should a future version of MySQL implement the SQL BOOLEAN data type for example, views created today using 'X IS NULL' can be exported using mysqldump, and imported again. Such views would be converted correctly and automatically to use a BOOLEAN column in the future version. With 'X IS TRUE' and the current implementations, views using these "boolean" predicates would not be converted during the export/import, and would use integer columns instead. The difference traces back to how SHOW CREATE VIEW preserves 'X IS NULL' but does not preserve the 'X IS TRUE' semantic. With this fix, internal representation of 'X IS TRUE' booleans predicates has changed, so that: - dedicated Item classes are created for each predicate, - only 1 Item is created to represent 1 predicate - my_pthread_getspecific_ptr() is invoked 1 time instead of 10 - SHOW CREATE VIEW preserves the original semantic, and prints 'X IS TRUE'. Note that, because of the fix in Item_func_if, views created before this fix will: - correctly use a int(1) type instead of int(2) for boolean predicates, - incorrectly print the if(ifnull(...), ...) expression in SHOW CREATE VIEW, since the original semantic (X IS TRUE) has been lost. - except for the syntax used in SHOW CREATE VIEW, these views will operate properly, no action is needed. Views created after this fix will operate correctly, and will preserve the original code semantic in SHOW CREATE VIEW. mysql-test/r/func_if.result: IF(x, unsigned, unsigned) should be unsigned. mysql-test/r/view.result: Preserve the semantic of 'X IS [NOT] (TRUE|FALSE)' boolean predicates. mysql-test/t/func_if.test: IF(x, unsigned, unsigned) should be unsigned. mysql-test/t/view.test: Preserve the semantic of 'X IS [NOT] (TRUE|FALSE)' boolean predicates. sql/item_cmpfunc.cc: Preserve the semantic of 'X IS [NOT] (TRUE|FALSE)' boolean predicates. IF(x, unsigned, unsigned) should be unsigned. sql/item_cmpfunc.h: Preserve the semantic of 'X IS [NOT] (TRUE|FALSE)' boolean predicates. sql/sql_yacc.yy: Preserve the semantic of 'X IS [NOT] (TRUE|FALSE)' boolean predicates. --- mysql-test/r/func_if.result | 3 + mysql-test/r/view.result | 125 ++++++++++++++++++++++++++++++++++++ mysql-test/t/func_if.test | 11 ++++ mysql-test/t/view.test | 86 +++++++++++++++++++++++++ sql/item_cmpfunc.cc | 74 +++++++++++++++++++-- sql/item_cmpfunc.h | 86 +++++++++++++++++++++++++ sql/sql_yacc.yy | 28 ++++---- 7 files changed, 391 insertions(+), 22 deletions(-) diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index eef380c8f52..c75e37fa0a4 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -128,3 +128,6 @@ f1 f2 if(f1, 40.0, 5.00) 0 0 5.00 1 1 40.00 drop table t1; +select if(0, 18446744073709551610, 18446744073709551610); +if(0, 18446744073709551610, 18446744073709551610) +18446744073709551610 diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 649b2827b1b..1aef628f9df 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -3033,4 +3033,129 @@ ERROR HY000: View's SELECT contains a subquery in the FROM clause SELECT * FROM (SELECT 1) AS t; 1 1 +drop view if exists view_24532_a; +drop view if exists view_24532_b; +drop table if exists table_24532; +create table table_24532 ( +a int, +b bigint, +c int(4), +d bigint(48) +); +create view view_24532_a as +select +a IS TRUE, +a IS NOT TRUE, +a IS FALSE, +a IS NOT FALSE, +a IS UNKNOWN, +a IS NOT UNKNOWN, +a is NULL, +a IS NOT NULL, +ISNULL(a), +b IS TRUE, +b IS NOT TRUE, +b IS FALSE, +b IS NOT FALSE, +b IS UNKNOWN, +b IS NOT UNKNOWN, +b is NULL, +b IS NOT NULL, +ISNULL(b), +c IS TRUE, +c IS NOT TRUE, +c IS FALSE, +c IS NOT FALSE, +c IS UNKNOWN, +c IS NOT UNKNOWN, +c is NULL, +c IS NOT NULL, +ISNULL(c), +d IS TRUE, +d IS NOT TRUE, +d IS FALSE, +d IS NOT FALSE, +d IS UNKNOWN, +d IS NOT UNKNOWN, +d is NULL, +d IS NOT NULL, +ISNULL(d) +from table_24532; +describe view_24532_a; +Field Type Null Key Default Extra +a IS TRUE int(1) NO 0 +a IS NOT TRUE int(1) NO 0 +a IS FALSE int(1) NO 0 +a IS NOT FALSE int(1) NO 0 +a IS UNKNOWN int(1) NO 0 +a IS NOT UNKNOWN int(1) NO 0 +a is NULL int(1) NO 0 +a IS NOT NULL int(1) NO 0 +ISNULL(a) int(1) NO 0 +b IS TRUE int(1) NO 0 +b IS NOT TRUE int(1) NO 0 +b IS FALSE int(1) NO 0 +b IS NOT FALSE int(1) NO 0 +b IS UNKNOWN int(1) NO 0 +b IS NOT UNKNOWN int(1) NO 0 +b is NULL int(1) NO 0 +b IS NOT NULL int(1) NO 0 +ISNULL(b) int(1) NO 0 +c IS TRUE int(1) NO 0 +c IS NOT TRUE int(1) NO 0 +c IS FALSE int(1) NO 0 +c IS NOT FALSE int(1) NO 0 +c IS UNKNOWN int(1) NO 0 +c IS NOT UNKNOWN int(1) NO 0 +c is NULL int(1) NO 0 +c IS NOT NULL int(1) NO 0 +ISNULL(c) int(1) NO 0 +d IS TRUE int(1) NO 0 +d IS NOT TRUE int(1) NO 0 +d IS FALSE int(1) NO 0 +d IS NOT FALSE int(1) NO 0 +d IS UNKNOWN int(1) NO 0 +d IS NOT UNKNOWN int(1) NO 0 +d is NULL int(1) NO 0 +d IS NOT NULL int(1) NO 0 +ISNULL(d) int(1) NO 0 +create view view_24532_b as +select +a IS TRUE, +if(ifnull(a, 0), 1, 0) as old_istrue, +a IS NOT TRUE, +if(ifnull(a, 0), 0, 1) as old_isnottrue, +a IS FALSE, +if(ifnull(a, 1), 0, 1) as old_isfalse, +a IS NOT FALSE, +if(ifnull(a, 1), 1, 0) as old_isnotfalse +from table_24532; +describe view_24532_b; +Field Type Null Key Default Extra +a IS TRUE int(1) NO 0 +old_istrue int(1) NO 0 +a IS NOT TRUE int(1) NO 0 +old_isnottrue int(1) NO 0 +a IS FALSE int(1) NO 0 +old_isfalse int(1) NO 0 +a IS NOT FALSE int(1) NO 0 +old_isnotfalse int(1) NO 0 +show create view view_24532_b; +View Create View +view_24532_b CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `view_24532_b` AS select (`table_24532`.`a` is true) AS `a IS TRUE`,if(ifnull(`table_24532`.`a`,0),1,0) AS `old_istrue`,(`table_24532`.`a` is not true) AS `a IS NOT TRUE`,if(ifnull(`table_24532`.`a`,0),0,1) AS `old_isnottrue`,(`table_24532`.`a` is false) AS `a IS FALSE`,if(ifnull(`table_24532`.`a`,1),0,1) AS `old_isfalse`,(`table_24532`.`a` is not false) AS `a IS NOT FALSE`,if(ifnull(`table_24532`.`a`,1),1,0) AS `old_isnotfalse` from `table_24532` +insert into table_24532 values (0, 0, 0, 0); +select * from view_24532_b; +a IS TRUE old_istrue a IS NOT TRUE old_isnottrue a IS FALSE old_isfalse a IS NOT FALSE old_isnotfalse +0 0 1 1 1 1 0 0 +update table_24532 set a=1; +select * from view_24532_b; +a IS TRUE old_istrue a IS NOT TRUE old_isnottrue a IS FALSE old_isfalse a IS NOT FALSE old_isnotfalse +1 1 0 0 0 0 1 1 +update table_24532 set a=NULL; +select * from view_24532_b; +a IS TRUE old_istrue a IS NOT TRUE old_isnottrue a IS FALSE old_isfalse a IS NOT FALSE old_isnotfalse +0 0 1 1 0 0 1 1 +drop view view_24532_a; +drop view view_24532_b; +drop table table_24532; End of 5.0 tests. diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index beaa371f847..5373ca3fec6 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -97,3 +97,14 @@ create table t1 (f1 int, f2 int); insert into t1 values(1,1),(0,0); select f1, f2, if(f1, 40.0, 5.00) from t1 group by f1 order by f2; drop table t1; + +# +# Bug#24532 (The return data type of IS TRUE is different from similar +# operations) +# +# IF(x, unsigned, unsigned) should be unsigned. +# + +select if(0, 18446744073709551610, 18446744073709551610); + + diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a5454b302f1..a418e25a576 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2992,5 +2992,91 @@ eval CREATE VIEW v1 AS $query; --echo # Previously the following would fail. eval $query; +# +# Bug#24532: The return data type of IS TRUE is different from similar +# operations +# + +--disable_warnings +drop view if exists view_24532_a; +drop view if exists view_24532_b; +drop table if exists table_24532; +--enable_warnings + +create table table_24532 ( + a int, + b bigint, + c int(4), + d bigint(48) +); + +create view view_24532_a as +select + a IS TRUE, + a IS NOT TRUE, + a IS FALSE, + a IS NOT FALSE, + a IS UNKNOWN, + a IS NOT UNKNOWN, + a is NULL, + a IS NOT NULL, + ISNULL(a), + b IS TRUE, + b IS NOT TRUE, + b IS FALSE, + b IS NOT FALSE, + b IS UNKNOWN, + b IS NOT UNKNOWN, + b is NULL, + b IS NOT NULL, + ISNULL(b), + c IS TRUE, + c IS NOT TRUE, + c IS FALSE, + c IS NOT FALSE, + c IS UNKNOWN, + c IS NOT UNKNOWN, + c is NULL, + c IS NOT NULL, + ISNULL(c), + d IS TRUE, + d IS NOT TRUE, + d IS FALSE, + d IS NOT FALSE, + d IS UNKNOWN, + d IS NOT UNKNOWN, + d is NULL, + d IS NOT NULL, + ISNULL(d) +from table_24532; + +describe view_24532_a; + +create view view_24532_b as +select + a IS TRUE, + if(ifnull(a, 0), 1, 0) as old_istrue, + a IS NOT TRUE, + if(ifnull(a, 0), 0, 1) as old_isnottrue, + a IS FALSE, + if(ifnull(a, 1), 0, 1) as old_isfalse, + a IS NOT FALSE, + if(ifnull(a, 1), 1, 0) as old_isnotfalse +from table_24532; + +describe view_24532_b; + +show create view view_24532_b; + +insert into table_24532 values (0, 0, 0, 0); +select * from view_24532_b; +update table_24532 set a=1; +select * from view_24532_b; +update table_24532 set a=NULL; +select * from view_24532_b; + +drop view view_24532_a; +drop view view_24532_b; +drop table table_24532; --echo End of 5.0 tests. diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 936ae04e93d..ee06a7727e4 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -721,6 +721,59 @@ int Arg_comparator::compare_e_row() } +void Item_func_truth::fix_length_and_dec() +{ + maybe_null= 0; + null_value= 0; + decimals= 0; + max_length= 1; +} + + +void Item_func_truth::print(String *str) +{ + str->append('('); + args[0]->print(str); + str->append(STRING_WITH_LEN(" is ")); + if (! affirmative) + str->append(STRING_WITH_LEN("not ")); + if (value) + str->append(STRING_WITH_LEN("true")); + else + str->append(STRING_WITH_LEN("false")); + str->append(')'); +} + + +bool Item_func_truth::val_bool() +{ + bool val= args[0]->val_bool(); + if (args[0]->null_value) + { + /* + NULL val IS {TRUE, FALSE} --> FALSE + NULL val IS NOT {TRUE, FALSE} --> TRUE + */ + return (! affirmative); + } + + if (affirmative) + { + /* {TRUE, FALSE} val IS {TRUE, FALSE} value */ + return (val == value); + } + + /* {TRUE, FALSE} val IS NOT {TRUE, FALSE} value */ + return (val != value); +} + + +longlong Item_func_truth::val_int() +{ + return (val_bool() ? 1 : 0); +} + + bool Item_in_optimizer::fix_left(THD *thd, Item **ref) { if (!args[0]->fixed && args[0]->fix_fields(thd, args) || @@ -1432,6 +1485,7 @@ Item_func_if::fix_length_and_dec() { maybe_null=args[1]->maybe_null || args[2]->maybe_null; decimals= max(args[1]->decimals, args[2]->decimals); + unsigned_flag=args[1]->unsigned_flag && args[2]->unsigned_flag; enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg2_type=args[2]->result_type(); @@ -1461,12 +1515,20 @@ Item_func_if::fix_length_and_dec() collation.set(&my_charset_bin); // Number } } - max_length= - (cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT) ? - (max(args[1]->max_length - args[1]->decimals, - args[2]->max_length - args[2]->decimals) + decimals + - (unsigned_flag ? 0 : 1) ) : - max(args[1]->max_length, args[2]->max_length); + + if ((cached_result_type == DECIMAL_RESULT ) + || (cached_result_type == INT_RESULT)) + { + int len1= args[1]->max_length - args[1]->decimals + - (args[1]->unsigned_flag ? 0 : 1); + + int len2= args[2]->max_length - args[2]->decimals + - (args[2]->unsigned_flag ? 0 : 1); + + max_length=max(len1, len2) + decimals + (unsigned_flag ? 0 : 1); + } + else + max_length= max(args[1]->max_length, args[2]->max_length); } diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 7bdc90adcee..8d814714d34 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -98,6 +98,92 @@ public: uint decimal_precision() const { return 1; } }; + +/** + Abstract Item class, to represent X IS [NOT] (TRUE | FALSE) + boolean predicates. +*/ + +class Item_func_truth : public Item_bool_func +{ +public: + virtual bool val_bool(); + virtual longlong val_int(); + virtual void fix_length_and_dec(); + virtual void print(String *str); + +protected: + Item_func_truth(Item *a, bool a_value, bool a_affirmative) + : Item_bool_func(a), value(a_value), affirmative(a_affirmative) + {} + + ~Item_func_truth() + {} +private: + /** + True for X IS [NOT] TRUE, + false for X IS [NOT] FALSE predicates. + */ + const bool value; + /** + True for X IS Y, false for X IS NOT Y predicates. + */ + const bool affirmative; +}; + + +/** + This Item represents a X IS TRUE boolean predicate. +*/ + +class Item_func_istrue : public Item_func_truth +{ +public: + Item_func_istrue(Item *a) : Item_func_truth(a, true, true) {} + ~Item_func_istrue() {} + virtual const char* func_name() const { return "istrue"; } +}; + + +/** + This Item represents a X IS NOT TRUE boolean predicate. +*/ + +class Item_func_isnottrue : public Item_func_truth +{ +public: + Item_func_isnottrue(Item *a) : Item_func_truth(a, true, false) {} + ~Item_func_isnottrue() {} + virtual const char* func_name() const { return "isnottrue"; } +}; + + +/** + This Item represents a X IS FALSE boolean predicate. +*/ + +class Item_func_isfalse : public Item_func_truth +{ +public: + Item_func_isfalse(Item *a) : Item_func_truth(a, false, true) {} + ~Item_func_isfalse() {} + virtual const char* func_name() const { return "isfalse"; } +}; + + +/** + This Item represents a X IS NOT FALSE boolean predicate. +*/ + +class Item_func_isnotfalse : public Item_func_truth +{ +public: + Item_func_isnotfalse(Item *a) : Item_func_truth(a, false, false) {} + ~Item_func_isnotfalse() {} + virtual const char* func_name() const { return "isnotfalse"; } +}; + + class Item_cache; #define UNKNOWN ((my_bool)-1) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6739ba39bcd..71ebc627638 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -58,15 +58,6 @@ const LEX_STRING null_lex_str={0,0}; YYABORT; \ } -/* Helper for parsing "IS [NOT] truth_value" */ -inline Item *is_truth_value(Item *A, bool v1, bool v2) -{ - return new Item_func_if(create_func_ifnull(A, - new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)), - new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1), - new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1)); -} - #ifndef DBUG_OFF #define YYDEBUG 1 #else @@ -4457,13 +4448,18 @@ bool_factor: | bool_test ; bool_test: - bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); } - | bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); } - | bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); } - | bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); } - | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); } - | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); } - | bool_pri ; + bool_pri IS TRUE_SYM + { $$= new (YYTHD->mem_root) Item_func_istrue($1); } + | bool_pri IS not TRUE_SYM + { $$= new (YYTHD->mem_root) Item_func_isnottrue($1); } + | bool_pri IS FALSE_SYM + { $$= new (YYTHD->mem_root) Item_func_isfalse($1); } + | bool_pri IS not FALSE_SYM + { $$= new (YYTHD->mem_root) Item_func_isnotfalse($1); } + | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); } + | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); } + | bool_pri + ; bool_pri: bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); } From 4386278e611c70d09cafbaf24e53be58c7ad6654 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 16 Feb 2007 13:42:52 -0700 Subject: [PATCH 10/55] Manual merge --- mysql-test/r/subselect.result | 143 +++++++++++++++++++++++++++++----- mysql-test/r/view.result | 130 ++++++++++++++++++++++++++++--- mysql-test/t/subselect.test | 93 ++++++++++++++++++++++ mysql-test/t/view.test | 96 +++++++++++++++++++++-- 4 files changed, 428 insertions(+), 34 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index c3f4a7c7f6b..8ba52e81f35 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -744,7 +744,7 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DEPENDENT UNION NULL NULL NULL NULL NULL NULL NULL No tables used NULL UNION RESULT ALL NULL NULL NULL NULL NULL Warnings: -Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where (`test`.`t2`.`id`,(select 1 AS `1` having trigcond(((`test`.`t2`.`id`) = (1))) union select 3 AS `3` having trigcond(((`test`.`t2`.`id`) = (3))))) +Note 1003 select `test`.`t2`.`id` AS `id` from `test`.`t2` where (`test`.`t2`.`id`,(select 1 AS `1` having ((`test`.`t2`.`id`) = (1)) union select 3 AS `3` having ((`test`.`t2`.`id`) = (3)))) SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 3); id SELECT * FROM t2 WHERE id IN (SELECT 5 UNION SELECT 2); @@ -892,7 +892,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL PRIMARY 4 NULL 4 Using index 2 DEPENDENT SUBQUERY t2 index_subquery a a 5 func 2 Using index Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a`,(((`test`.`t1`.`a`) in t2 on a checking NULL))) AS `t1.a in (select t2.a from t2)` from `test`.`t1` +Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a`,(((`test`.`t1`.`a`) in t2 on a checking NULL having (`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2)` from `test`.`t1` CREATE TABLE t3 (a int(11) default '0'); INSERT INTO t3 VALUES (1),(2),(3); SELECT t1.a, t1.a in (select t2.a from t2,t3 where t3.a=t2.a) FROM t1; @@ -907,7 +907,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t2 ref_or_null a a 5 func 2 Using where; Using index 2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where Warnings: -Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a`,(select 1 AS `Not_used` from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and trigcond((((`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`)))) having trigcond((`test`.`t2`.`a`)))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` +Note 1003 select `test`.`t1`.`a` AS `a`,(`test`.`t1`.`a`,(select 1 AS `Not_used` from `test`.`t2` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t2`.`a`) and (((`test`.`t1`.`a`) = `test`.`t2`.`a`) or isnull(`test`.`t2`.`a`))) having (`test`.`t2`.`a`))) AS `t1.a in (select t2.a from t2,t3 where t3.a=t2.a)` from `test`.`t1` drop table t1,t2,t3; create table t1 (a float); select 10.5 IN (SELECT * from t1 LIMIT 1); @@ -1305,7 +1305,7 @@ a explain extended select * from t2 where t2.a in (select a from t1 where t1.b <> 30); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 index NULL PRIMARY 4 NULL 4 Using where; Using index -2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where +2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using where Warnings: Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where (`test`.`t2`.`a`,(((`test`.`t2`.`a`) in t1 on PRIMARY where (`test`.`t1`.`b` <> 30)))) select * from t2 where t2.a in (select t1.a from t1,t3 where t1.b=t3.a); @@ -1462,27 +1462,27 @@ a3 1 explain extended select s1, s1 NOT IN (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index -2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index; Full scan on NULL key Warnings: -Note 1003 select `test`.`t1`.`s1` AS `s1`,not((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 select `test`.`t1`.`s1` AS `s1`,(not((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond((`test`.`t2`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 = ANY (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index -2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index; Full scan on NULL key Warnings: -Note 1003 select `test`.`t1`.`s1` AS `s1`,(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 select `test`.`t1`.`s1` AS `s1`,(`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond((`test`.`t2`.`s1`))))) AS `s1 = ANY (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 <> ALL (SELECT s1 FROM t2) from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index -2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index; Full scan on NULL key Warnings: -Note 1003 select `test`.`t1`.`s1` AS `s1`,not((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL)))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` +Note 1003 select `test`.`t1`.`s1` AS `s1`,(not((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL having trigcond((`test`.`t2`.`s1`))))))) AS `s1 <> ALL (SELECT s1 FROM t2)` from `test`.`t1` explain extended select s1, s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2') from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 index NULL s1 6 NULL 3 Using index -2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index; Using where +2 DEPENDENT SUBQUERY t2 index_subquery s1 s1 6 func 2 Using index; Using where; Full scan on NULL key Warnings: -Note 1003 select `test`.`t1`.`s1` AS `s1`,not((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < _latin1'a2'))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` +Note 1003 select `test`.`t1`.`s1` AS `s1`,(not((`test`.`t1`.`s1`,(((`test`.`t1`.`s1`) in t2 on s1 checking NULL where (`test`.`t2`.`s1` < _latin1'a2') having trigcond((`test`.`t2`.`s1`))))))) AS `s1 NOT IN (SELECT s1 FROM t2 WHERE s1 < 'a2')` from `test`.`t1` drop table t1,t2; create table t2 (a int, b int); create table t3 (a int); @@ -1737,14 +1737,14 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 12 Using where 2 DEPENDENT SUBQUERY t1 unique_subquery PRIMARY PRIMARY 4 func 1 Using index; Using where Warnings: -Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where not((`test`.`t1`.`id`,(((`test`.`t1`.`id`) in t1 on PRIMARY where (`test`.`t1`.`id` < 8))))) +Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `test`.`t1` where (not((`test`.`t1`.`id`,(((`test`.`t1`.`id`) in t1 on PRIMARY where (`test`.`t1`.`id` < 8)))))) explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where 2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 Using where; Using index Warnings: Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1 -Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and (`test`.`t1`.`id` = `test`.`tt`.`id`)) having (`test`.`t1`.`id` is not null))) +Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where (not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and (`test`.`t1`.`id` = `test`.`tt`.`id`)) having (`test`.`t1`.`id` is not null)))) insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001'); create table t2 (id int not null, text varchar(20) not null default '', primary key (id)); insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10'); @@ -2816,19 +2816,19 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where Warnings: -Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,((`test`.`t1`.`one`,`test`.`t1`.`two`),(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'0') and trigcond(((((`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and (((`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`))))) having trigcond(((`test`.`t2`.`one`) and (`test`.`t2`.`two`))))) AS `test` from `test`.`t1` +Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,((`test`.`t1`.`one`,`test`.`t1`.`two`),(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'0') and trigcond((((`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond((((`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)))) having (trigcond((`test`.`t2`.`one`)) and trigcond((`test`.`t2`.`two`))))) AS `test` from `test`.`t1` explain extended SELECT one,two from t1 where ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = 'N'); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 Using where 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where Warnings: -Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where ((`test`.`t1`.`one`,`test`.`t1`.`two`),(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'N') and trigcond((((`test`.`t1`.`one`) = `test`.`t2`.`one`) and ((`test`.`t1`.`two`) = `test`.`t2`.`two`)))))) +Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two` from `test`.`t1` where ((`test`.`t1`.`one`,`test`.`t1`.`two`),(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where ((`test`.`t2`.`flag` = _latin1'N') and ((`test`.`t1`.`one`) = `test`.`t2`.`one`) and ((`test`.`t1`.`two`) = `test`.`t2`.`two`)))) explain extended SELECT one,two,ROW(one,two) IN (SELECT one,two FROM t2 WHERE flag = '0' group by one,two) as 'test' from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 8 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 9 Using where; Using temporary; Using filesort Warnings: -Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,((`test`.`t1`.`one`,`test`.`t1`.`two`),(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = _latin1'0') group by `test`.`t2`.`one`,`test`.`t2`.`two` having trigcond(((((`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`)) and (((`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`)) and (`test`.`t2`.`one`) and (`test`.`t2`.`two`))))) AS `test` from `test`.`t1` +Note 1003 select `test`.`t1`.`one` AS `one`,`test`.`t1`.`two` AS `two`,((`test`.`t1`.`one`,`test`.`t1`.`two`),(select `test`.`t2`.`one` AS `one`,`test`.`t2`.`two` AS `two` from `test`.`t2` where (`test`.`t2`.`flag` = _latin1'0') group by `test`.`t2`.`one`,`test`.`t2`.`two` having (trigcond((((`test`.`t1`.`one`) = `test`.`t2`.`one`) or isnull(`test`.`t2`.`one`))) and trigcond((((`test`.`t1`.`two`) = `test`.`t2`.`two`) or isnull(`test`.`t2`.`two`))) and trigcond((`test`.`t2`.`one`)) and trigcond((`test`.`t2`.`two`))))) AS `test` from `test`.`t1` DROP TABLE t1,t2; CREATE TABLE t1 (a char(5), b char(5)); INSERT INTO t1 VALUES (NULL,'aaa'), ('aaa','aaa'); @@ -3009,7 +3009,7 @@ INSERT INTO t2 VALUES (1),(2),(3); EXPLAIN SELECT a, a IN (SELECT a FROM t1) FROM t2; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t2 ALL NULL NULL NULL NULL 3 -2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index +2 DEPENDENT SUBQUERY t1 index_subquery a a 5 func 2 Using index; Full scan on NULL key SELECT a, a IN (SELECT a FROM t1) FROM t2; a a IN (SELECT a FROM t1) 1 1 @@ -3046,6 +3046,80 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 2 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE DROP TABLE t1; +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (2), (4), (1), (3); +CREATE TABLE t2 (b int, c int); +INSERT INTO t2 VALUES +(2,1), (1,3), (2,1), (4,4), (2,2), (1,4); +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 2 ); +a +2 +4 +1 +3 +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 1); +ERROR 21000: Subquery returns more than 1 row +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 2), a; +a +1 +2 +3 +4 +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 1), a; +ERROR 21000: Subquery returns more than 1 row +SELECT b, MAX(c) FROM t2 GROUP BY b, (SELECT c FROM t2 WHERE b > 2); +b MAX(c) +1 4 +2 2 +4 4 +SELECT b, MAX(c) FROM t2 GROUP BY b, (SELECT c FROM t2 WHERE b > 1); +ERROR 21000: Subquery returns more than 1 row +SELECT a FROM t1 GROUP BY a +HAVING IFNULL((SELECT b FROM t2 WHERE b > 2), +(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3; +a +1 +2 +3 +4 +SELECT a FROM t1 GROUP BY a +HAVING IFNULL((SELECT b FROM t2 WHERE b > 1), +(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3; +ERROR 21000: Subquery returns more than 1 row +SELECT a FROM t1 GROUP BY a +HAVING IFNULL((SELECT b FROM t2 WHERE b > 4), +(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3; +a +4 +SELECT a FROM t1 GROUP BY a +HAVING IFNULL((SELECT b FROM t2 WHERE b > 4), +(SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)) > 3; +ERROR 21000: Subquery returns more than 1 row +SELECT a FROM t1 +ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 2), +(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)); +a +2 +4 +1 +3 +SELECT a FROM t1 +ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 1), +(SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)); +ERROR 21000: Subquery returns more than 1 row +SELECT a FROM t1 +ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 4), +(SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)); +a +2 +1 +3 +4 +SELECT a FROM t1 +ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 4), +(SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)); +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1,t2; create table t1 (df decimal(5,1)); insert into t1 values(1.1); insert into t1 values(2.2); @@ -3605,6 +3679,39 @@ FROM t1) t; COUNT(*) 3000 DROP TABLE t1,t2; +CREATE TABLE t1 (id char(4) PRIMARY KEY, c int); +CREATE TABLE t2 (c int); +INSERT INTO t1 VALUES ('aa', 1); +INSERT INTO t2 VALUES (1); +SELECT * FROM t1 +WHERE EXISTS (SELECT c FROM t2 WHERE c=1 +UNION +SELECT c from t2 WHERE c=t1.c); +id c +aa 1 +INSERT INTO t1 VALUES ('bb', 2), ('cc', 3), ('dd',1); +SELECT * FROM t1 +WHERE EXISTS (SELECT c FROM t2 WHERE c=1 +UNION +SELECT c from t2 WHERE c=t1.c); +id c +aa 1 +bb 2 +cc 3 +dd 1 +INSERT INTO t2 VALUES (2); +CREATE TABLE t3 (c int); +INSERT INTO t3 VALUES (1); +SELECT * FROM t1 +WHERE EXISTS (SELECT t2.c FROM t2 JOIN t3 ON t2.c=t3.c WHERE t2.c=1 +UNION +SELECT c from t2 WHERE c=t1.c); +id c +aa 1 +bb 2 +cc 3 +dd 1 +DROP TABLE t1,t2,t3; DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t1xt2; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 1aef628f9df..6dad86712e4 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -834,14 +834,14 @@ show create view v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 99999999999999999999999999999999999999999999999999999 AS `col1` drop view v1; -create table tü (cü char); -create view vü as select cü from tü; -insert into vü values ('ü'); -select * from vü; -cü -ü -drop view vü; -drop table tü; +create table t (c char); +create view v as select c from t; +insert into v values (''); +select * from v; +c + +drop view v; +drop table t; create table t1 (a int, b int); insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10); create view v1(c) as select a+1 from t1 where b >= 4; @@ -2543,7 +2543,7 @@ create table t1(f1 int, f2 int); create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb .f1 and ta.f2=tb.f2; insert into t1 values(1,1),(2,2); -create view v2 as select * from v1 where a > 1 with check option; +create view v2 as select * from v1 where a > 1 with local check option; select * from v2; a b 2 2 @@ -3014,6 +3014,17 @@ i j 6 3 DROP VIEW v1, v2; DROP TABLE t1; +CREATE VIEW v AS SELECT !0 * 5 AS x FROM DUAL; +SHOW CREATE VIEW v; +View Create View +v CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select ((not(0)) * 5) AS `x` +SELECT !0 * 5 AS x FROM DUAL; +x +5 +SELECT * FROM v; +x +5 +DROP VIEW v; DROP VIEW IF EXISTS v1; CREATE VIEW v1 AS SELECT 'The\ZEnd'; SELECT * FROM v1; @@ -3023,6 +3034,107 @@ SHOW CREATE VIEW v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select _latin1'The\ZEnd' AS `TheEnd` DROP VIEW v1; +CREATE TABLE t1 (mydate DATETIME); +INSERT INTO t1 VALUES +('2007-01-01'), ('2007-01-02'), ('2007-01-30'), ('2007-01-31'); +CREATE VIEW v1 AS SELECT mydate from t1; +SELECT * FROM t1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31'; +mydate +2007-01-01 00:00:00 +2007-01-02 00:00:00 +2007-01-30 00:00:00 +2007-01-31 00:00:00 +SELECT * FROM v1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31'; +mydate +2007-01-01 00:00:00 +2007-01-02 00:00:00 +2007-01-30 00:00:00 +2007-01-31 00:00:00 +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); +CREATE VIEW v1 AS +SELECT t2.b FROM t1,t2 WHERE t1.a = t2.b WITH CHECK OPTION; +SELECT * FROM v1; +b +1 +2 +UPDATE v1 SET b=3; +ERROR HY000: CHECK OPTION failed 'test.v1' +SELECT * FROM v1; +b +1 +2 +SELECT * FROM t1; +a +1 +2 +SELECT * FROM t2; +b +1 +2 +DROP VIEW v1; +DROP TABLE t1,t2; +create table t1(f1 int, f2 int); +insert into t1 values(1,2),(1,3),(1,1),(2,3),(2,1),(2,2); +select * from t1; +f1 f2 +1 2 +1 3 +1 1 +2 3 +2 1 +2 2 +create view v1 as select * from t1 order by f2; +select * from v1; +f1 f2 +1 1 +2 1 +1 2 +2 2 +1 3 +2 3 +explain extended select * from v1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort +Warnings: +Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2` from `test`.`t1` order by `test`.`t1`.`f2` +select * from v1 order by f1; +f1 f2 +1 1 +1 2 +1 3 +2 1 +2 2 +2 3 +explain extended select * from v1 order by f1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 6 Using filesort +Warnings: +Note 1003 select `test`.`t1`.`f1` AS `f1`,`test`.`t1`.`f2` AS `f2` from `test`.`t1` order by `test`.`t1`.`f1`,`test`.`t1`.`f2` +drop view v1; +drop table t1; +CREATE TABLE t1 ( +id int(11) NOT NULL PRIMARY KEY, +country varchar(32), +code int(11) default NULL +); +INSERT INTO t1 VALUES +(1,'ITALY',100),(2,'ITALY',200),(3,'FRANCE',100), (4,'ITALY',100); +CREATE VIEW v1 AS SELECT * FROM t1; +SELECT code, COUNT(DISTINCT country) FROM t1 GROUP BY code ORDER BY MAX(id); +code COUNT(DISTINCT country) +200 1 +100 2 +SELECT code, COUNT(DISTINCT country) FROM v1 GROUP BY code ORDER BY MAX(id); +code COUNT(DISTINCT country) +200 1 +100 2 +DROP VIEW v1; +DROP TABLE t1; DROP VIEW IF EXISTS v1; SELECT * FROM (SELECT 1) AS t; 1 diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 712b0693c32..927adfec231 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2000,6 +2000,65 @@ SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; EXPLAIN SELECT a FROM t1 WHERE (SELECT 1 FROM DUAL WHERE 1=0) IS NULL; DROP TABLE t1; + +# +# Bug 24653: sorting by expressions containing subselects +# that return more than one row +# + +CREATE TABLE t1 (a int); +INSERT INTO t1 VALUES (2), (4), (1), (3); + +CREATE TABLE t2 (b int, c int); +INSERT INTO t2 VALUES + (2,1), (1,3), (2,1), (4,4), (2,2), (1,4); + +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 2 ); +--error 1242 +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 1); +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 2), a; +--error 1242 +SELECT a FROM t1 ORDER BY (SELECT c FROM t2 WHERE b > 1), a; + +SELECT b, MAX(c) FROM t2 GROUP BY b, (SELECT c FROM t2 WHERE b > 2); +--error 1242 +SELECT b, MAX(c) FROM t2 GROUP BY b, (SELECT c FROM t2 WHERE b > 1); + + +SELECT a FROM t1 GROUP BY a + HAVING IFNULL((SELECT b FROM t2 WHERE b > 2), + (SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3; +--error 1242 +SELECT a FROM t1 GROUP BY a + HAVING IFNULL((SELECT b FROM t2 WHERE b > 1), + (SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3; + +SELECT a FROM t1 GROUP BY a + HAVING IFNULL((SELECT b FROM t2 WHERE b > 4), + (SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)) > 3; +--error 1242 +SELECT a FROM t1 GROUP BY a + HAVING IFNULL((SELECT b FROM t2 WHERE b > 4), + (SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)) > 3; + +SELECT a FROM t1 + ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 2), + (SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)); +--error 1242 +SELECT a FROM t1 + ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 1), + (SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)); + +SELECT a FROM t1 + ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 4), + (SELECT c FROM t2 WHERE c=a AND b > 2 ORDER BY b)); +--error 1242 +SELECT a FROM t1 + ORDER BY IFNULL((SELECT b FROM t2 WHERE b > 4), + (SELECT c FROM t2 WHERE c=a AND b > 1 ORDER BY b)); + +DROP TABLE t1,t2; + # End of 4.1 tests # @@ -2509,6 +2568,40 @@ SELECT SQL_NO_CACHE COUNT(*) DROP TABLE t1,t2; +# +# Bug #25219: EXIST subquery with UNION over a mix of +# correlated and uncorrelated selects +# + +CREATE TABLE t1 (id char(4) PRIMARY KEY, c int); +CREATE TABLE t2 (c int); + +INSERT INTO t1 VALUES ('aa', 1); +INSERT INTO t2 VALUES (1); + +SELECT * FROM t1 + WHERE EXISTS (SELECT c FROM t2 WHERE c=1 + UNION + SELECT c from t2 WHERE c=t1.c); + +INSERT INTO t1 VALUES ('bb', 2), ('cc', 3), ('dd',1); + +SELECT * FROM t1 + WHERE EXISTS (SELECT c FROM t2 WHERE c=1 + UNION + SELECT c from t2 WHERE c=t1.c); + +INSERT INTO t2 VALUES (2); +CREATE TABLE t3 (c int); +INSERT INTO t3 VALUES (1); + +SELECT * FROM t1 + WHERE EXISTS (SELECT t2.c FROM t2 JOIN t3 ON t2.c=t3.c WHERE t2.c=1 + UNION + SELECT c from t2 WHERE c=t1.c); + +DROP TABLE t1,t2,t3; + # # Bug#21904 (parser problem when using IN with a double "(())") # diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index a418e25a576..d100630cf24 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -748,12 +748,12 @@ drop view v1; # # VIEWs with national characters # -create table tü (cü char); -create view vü as select cü from tü; -insert into vü values ('ü'); -select * from vü; -drop view vü; -drop table tü; +create table t (c char); +create view v as select c from t; +insert into v values (''); +select * from v; +drop view v; +drop table t; # # problem with used_tables() of outer reference resolved in VIEW @@ -2385,7 +2385,7 @@ create table t1(f1 int, f2 int); create view v1 as select ta.f1 as a, tb.f1 as b from t1 ta, t1 tb where ta.f1=tb .f1 and ta.f2=tb.f2; insert into t1 values(1,1),(2,2); -create view v2 as select * from v1 where a > 1 with check option; +create view v2 as select * from v1 where a > 1 with local check option; select * from v2; update v2 set b=3 where a=2; select * from v2; @@ -2959,6 +2959,17 @@ SELECT * FROM t1; DROP VIEW v1, v2; DROP TABLE t1; +# +# Bug #25580: !0 as an operand in a select expression of a view +# + +CREATE VIEW v AS SELECT !0 * 5 AS x FROM DUAL; +SHOW CREATE VIEW v; + +SELECT !0 * 5 AS x FROM DUAL; +SELECT * FROM v; + +DROP VIEW v; # # BUG#24293: '\Z' token is not handled correctly in views @@ -2975,6 +2986,77 @@ SHOW CREATE VIEW v1; DROP VIEW v1; +# +# Bug #26124: BETWEEN over a view column of the DATETIME type +# + +CREATE TABLE t1 (mydate DATETIME); +INSERT INTO t1 VALUES + ('2007-01-01'), ('2007-01-02'), ('2007-01-30'), ('2007-01-31'); + +CREATE VIEW v1 AS SELECT mydate from t1; + +SELECT * FROM t1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31'; +SELECT * FROM v1 WHERE mydate BETWEEN '2007-01-01' AND '2007-01-31'; + +DROP VIEW v1; +DROP TABLE t1; + +# +# Bug #25931: update of a multi-table view with check option +# + +CREATE TABLE t1 (a int); +CREATE TABLE t2 (b int); +INSERT INTO t1 VALUES (1), (2); +INSERT INTO t2 VALUES (1), (2); + +CREATE VIEW v1 AS + SELECT t2.b FROM t1,t2 WHERE t1.a = t2.b WITH CHECK OPTION; + +SELECT * FROM v1; +--error 1369 +UPDATE v1 SET b=3; +SELECT * FROM v1; +SELECT * FROM t1; +SELECT * FROM t2; + +DROP VIEW v1; +DROP TABLE t1,t2; + +# +# Bug#12122: Views with ORDER BY can't be resolved using MERGE algorithm. +# +create table t1(f1 int, f2 int); +insert into t1 values(1,2),(1,3),(1,1),(2,3),(2,1),(2,2); +select * from t1; +create view v1 as select * from t1 order by f2; +select * from v1; +explain extended select * from v1; +select * from v1 order by f1; +explain extended select * from v1 order by f1; +drop view v1; +drop table t1; + +# +# Bug#26209: queries with GROUP BY and ORDER BY using views +# + +CREATE TABLE t1 ( + id int(11) NOT NULL PRIMARY KEY, + country varchar(32), + code int(11) default NULL +); +INSERT INTO t1 VALUES + (1,'ITALY',100),(2,'ITALY',200),(3,'FRANCE',100), (4,'ITALY',100); + +CREATE VIEW v1 AS SELECT * FROM t1; + +SELECT code, COUNT(DISTINCT country) FROM t1 GROUP BY code ORDER BY MAX(id); +SELECT code, COUNT(DISTINCT country) FROM v1 GROUP BY code ORDER BY MAX(id); + +DROP VIEW v1; +DROP TABLE t1; # # BUG#25897: Some queries are no longer possible after a CREATE VIEW From 114e5b8ddb26aff34f9ea8418dfe73043b912f0f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Feb 2007 09:37:34 +0100 Subject: [PATCH 11/55] Bug#23240 --init-file statements with NOW() reports '1970-01-01 11:00:00'as the date time - Starting time of a query sent by file bootstrapping wasn't initialized and starting time defaulted to 0. This later used value by the Now- item and is translated to 1970-01-01 11:00:00. - marking the time with thd->set_time() before the call to mysql_parse resolves this issue. mysql-test/r/init_file.result: Appended test case mysql-test/std_data/init_file.dat: Appended test case mysql-test/t/init_file.test: Appended test case --- mysql-test/r/init_file.result | 7 +++++++ mysql-test/std_data/init_file.dat | 8 ++++++++ mysql-test/t/init_file.test | 9 +++++++++ sql/sql_parse.cc | 1 + 4 files changed, 25 insertions(+) diff --git a/mysql-test/r/init_file.result b/mysql-test/r/init_file.result index 5404a7b2064..509d382aadd 100644 --- a/mysql-test/r/init_file.result +++ b/mysql-test/r/init_file.result @@ -1,2 +1,9 @@ +INSERT INTO init_file.startup VALUES ( NOW() ); +SELECT * INTO @X FROM init_file.startup limit 0,1; +SELECT * INTO @Y FROM init_file.startup limit 1,1; +SELECT YEAR(@X)-YEAR(@Y); +YEAR(@X)-YEAR(@Y) +0 +DROP DATABASE init_file; ok End of 4.1 tests diff --git a/mysql-test/std_data/init_file.dat b/mysql-test/std_data/init_file.dat index 6105ca2ac1b..91e456e725d 100644 --- a/mysql-test/std_data/init_file.dat +++ b/mysql-test/std_data/init_file.dat @@ -1 +1,9 @@ select * from mysql.user as t1, mysql.user as t2, mysql.user as t3; + +# +# Bug#23240 --init-file statements with NOW() reports '1970-01-01 11:00:00'as the date time +# +CREATE DATABASE IF NOT EXISTS init_file; +CREATE TABLE IF NOT EXISTS init_file.startup ( startdate DATETIME ); +INSERT INTO init_file.startup VALUES ( NOW() ); + diff --git a/mysql-test/t/init_file.test b/mysql-test/t/init_file.test index bbe0c4ff884..34d738415c8 100644 --- a/mysql-test/t/init_file.test +++ b/mysql-test/t/init_file.test @@ -6,5 +6,14 @@ # mysql-test/t/init_file-master.opt for the actual test # +# +# Bug#23240 --init-file statements with NOW() reports '1970-01-01 11:00:00'as the date time +# +INSERT INTO init_file.startup VALUES ( NOW() ); +SELECT * INTO @X FROM init_file.startup limit 0,1; +SELECT * INTO @Y FROM init_file.startup limit 1,1; +SELECT YEAR(@X)-YEAR(@Y); +DROP DATABASE init_file; + --echo ok --echo End of 4.1 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 19add72c23e..7db78a7d013 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1175,6 +1175,7 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); break; } + thd->set_time(); mysql_parse(thd,thd->query,length); close_thread_tables(thd); // Free tables if (thd->is_fatal_error) From a48276798b77fe4846ba5a7f74281cc1c9814357 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Feb 2007 14:57:54 +0100 Subject: [PATCH 12/55] Bug#23240 --init_file statements with NOW() reports '1970-01-01 11:00:00'as the date time - Starting time of a query sent by bootstrapping wasn't initialized and starting time defaulted to 0. This later used value by NOW- item and was translated to 1970-01-01 11:00:00. - Marketing the time with thd->set_time() before the call to mysql_parse resolves this issue. - set_time was refactored to be part of the thd->init_for_queries- process. mysql-test/r/init_file.result: Manual merge from 4.1 mysql-test/std_data/init_file.dat: Manual merge from 4.1 sql/sql_class.cc: - Moved set_time into init_for_queries process. --- mysql-test/r/init_file.result | 7 +++++++ mysql-test/std_data/init_file.dat | 9 +++++++++ sql/sql_class.cc | 1 + sql/sql_parse.cc | 3 +-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/init_file.result b/mysql-test/r/init_file.result index 1569f2c3d68..6394014f3e5 100644 --- a/mysql-test/r/init_file.result +++ b/mysql-test/r/init_file.result @@ -1,3 +1,10 @@ +INSERT INTO init_file.startup VALUES ( NOW() ); +SELECT * INTO @X FROM init_file.startup limit 0,1; +SELECT * INTO @Y FROM init_file.startup limit 1,1; +SELECT YEAR(@X)-YEAR(@Y); +YEAR(@X)-YEAR(@Y) +0 +DROP DATABASE init_file; ok end of 4.1 tests select * from t1; diff --git a/mysql-test/std_data/init_file.dat b/mysql-test/std_data/init_file.dat index 814e968eb31..cb8e0778438 100644 --- a/mysql-test/std_data/init_file.dat +++ b/mysql-test/std_data/init_file.dat @@ -27,3 +27,12 @@ insert into t2 values (11), (13); drop procedure p1; drop function f1; drop view v1; + +# +# Bug#23240 --init-file statements with NOW() reports '1970-01-01 11:00:00'as the date time +# +CREATE DATABASE IF NOT EXISTS init_file; +CREATE TABLE IF NOT EXISTS init_file.startup ( startdate DATETIME ); +INSERT INTO init_file.startup VALUES ( NOW() ); + + diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3b612dadcd0..48ed6df5178 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -317,6 +317,7 @@ void THD::init(void) void THD::init_for_queries() { + set_time(); ha_enable_transaction(this,TRUE); reset_root_defaults(mem_root, variables.query_alloc_block_size, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index b3f31b7e30c..19d7a87f0ee 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1160,7 +1160,6 @@ pthread_handler_t handle_one_connection(void *arg) thd->version= refresh_version; thd->proc_info= 0; thd->command= COM_SLEEP; - thd->set_time(); thd->init_for_queries(); if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) @@ -1176,7 +1175,6 @@ pthread_handler_t handle_one_connection(void *arg) sql_print_warning("%s", net->last_error); } thd->proc_info=0; - thd->set_time(); thd->init_for_queries(); } @@ -1306,6 +1304,7 @@ pthread_handler_t handle_bootstrap(void *arg) mode we have only one thread. */ thd->query_id=next_query_id(); + thd->set_time(); mysql_parse(thd,thd->query,length); close_thread_tables(thd); // Free tables if (thd->is_fatal_error) From 4bb9efa61030c699e23791fe49f8db1961e3202c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 20 Feb 2007 22:31:50 +0300 Subject: [PATCH 13/55] Fix for BUG#24415: Instance manager test im_daemon_life_cycle fails randomly. The cause of im_daemon_life_cycle.imtest random failures was the following behaviour of some implementations of LINUX threads: let's suppose that a process has several threads (in LINUX threads, there is a separate process for each thread). When the main process gets killed, the parent receives SIGCHLD before all threads (child processes) die. In other words, the parent receives SIGCHLD, when its child is not completely dead. In terms of IM, that means that IM-angel receives SIGCHLD when IM-main is not dead and still holds some resources. After receiving SIGCHLD, IM-angel restarts IM-main, but IM-main failed to initialize, because previous instance (copy) of IM-main still holds server socket (TCP-port). Another problem here was that IM-angel restarted IM-main only if it was killed by signal. If it exited with error, IM-angel thought it's intended / graceful shutdown and exited itself. So, when the second instance of IM-main failed to initialize, IM-angel thought it's intended shutdown and quit. The fix is 1. to change IM-angel so that it restarts IM-main if it exited with error code; 2. to change IM-main so that it returns proper exit code in case of failure. mysql-test/t/disabled.def: Enable im_daemon_life_cycle. server-tools/instance-manager/listener.cc: Set error status if Listener failed to initialize. server-tools/instance-manager/manager.cc: Return exit code from the manager. server-tools/instance-manager/manager.h: Return exit code from the manager. server-tools/instance-manager/mysqlmanager.cc: 1. Restart IM-main if exit code is not EXIT_SUCCESS (0). 2. Log IM-main exit code in case of failure. server-tools/instance-manager/thread_registry.cc: Add support for exit code. server-tools/instance-manager/thread_registry.h: Add support for exit code. --- mysql-test/t/disabled.def | 1 - server-tools/instance-manager/listener.cc | 3 ++ server-tools/instance-manager/manager.cc | 14 ++++++---- server-tools/instance-manager/manager.h | 2 +- server-tools/instance-manager/mysqlmanager.cc | 28 +++++++++---------- .../instance-manager/thread_registry.cc | 21 ++++++++++++++ .../instance-manager/thread_registry.h | 4 +++ 7 files changed, 51 insertions(+), 22 deletions(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 99ba55a7e2b..eaea7c710b0 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -10,7 +10,6 @@ # ############################################################################## -im_daemon_life_cycle : Bug#24415 see note: [19 Dec 23:17] Trudy Pelzer ndb_load : Bug#17233 user_limits : Bug#23921 random failure of user_limits.test diff --git a/server-tools/instance-manager/listener.cc b/server-tools/instance-manager/listener.cc index 15583b233fb..a055d98656c 100644 --- a/server-tools/instance-manager/listener.cc +++ b/server-tools/instance-manager/listener.cc @@ -210,10 +210,13 @@ void Listener_thread::run() return; err: + log_error("Listener: failed to initialize. Initiate shutdown..."); + // we have to close the ip sockets in case of error for (i= 0; i < num_sockets; i++) closesocket(sockets[i]); + thread_registry.set_error_status(); thread_registry.unregister_thread(&thread_info); thread_registry.request_shutdown(); my_thread_end(); diff --git a/server-tools/instance-manager/manager.cc b/server-tools/instance-manager/manager.cc index 30b6aea8519..cadb7a4aa0c 100644 --- a/server-tools/instance-manager/manager.cc +++ b/server-tools/instance-manager/manager.cc @@ -114,6 +114,9 @@ void stop_all(Guardian_thread *guardian, Thread_registry *registry) pthread_cond_signal(&guardian->COND_guardian); /* stop all threads */ registry->deliver_shutdown(); + + /* Set error status in the thread registry. */ + registry->set_error_status(); } /* @@ -123,7 +126,7 @@ void stop_all(Guardian_thread *guardian, Thread_registry *registry) architecture. */ -void manager(const Options &options) +int manager(const Options &options) { Thread_registry thread_registry; /* @@ -145,10 +148,10 @@ void manager(const Options &options) instance_map.guardian= &guardian_thread; if (instance_map.init() || user_map.init()) - return; + return 1; if (user_map.load(options.password_file_name)) - return; + return 1; /* write Instance Manager pid file */ @@ -157,7 +160,7 @@ void manager(const Options &options) (int) manager_pid); if (create_pid_file(options.pid_file_name, manager_pid)) - return; + return 1; /* Initialize signals and alarm-infrastructure. @@ -301,5 +304,6 @@ err: end_thr_alarm(1); /* don't pthread_exit to kill all threads who did not shut down in time */ #endif -} + return thread_registry.get_error_status() ? 1 : 0; +} diff --git a/server-tools/instance-manager/manager.h b/server-tools/instance-manager/manager.h index 0d459d9cee1..22af0d39115 100644 --- a/server-tools/instance-manager/manager.h +++ b/server-tools/instance-manager/manager.h @@ -18,7 +18,7 @@ struct Options; -void manager(const Options &options); +int manager(const Options &options); int create_pid_file(const char *pid_file_name, int pid); diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index 2b6921d59aa..83918092454 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -110,8 +110,7 @@ int main(int argc, char *argv[]) else #endif - manager(options); - return_value= 0; + return_value= manager(options); err: options.cleanup(); @@ -254,26 +253,23 @@ static void daemonize(const char *log_file_name) enum { CHILD_OK= 0, CHILD_NEED_RESPAWN, CHILD_EXIT_ANGEL }; static volatile sig_atomic_t child_status= CHILD_OK; +static volatile sig_atomic_t child_exit_code= 0; /* - Signal handler for SIGCHLD: reap child, analyze child exit status, and set + Signal handler for SIGCHLD: reap child, analyze child exit code, and set child_status appropriately. */ void reap_child(int __attribute__((unused)) signo) { - int child_exit_status; - /* As we have only one child, no need to cycle waitpid */ - if (waitpid(0, &child_exit_status, WNOHANG) > 0) + /* NOTE: As we have only one child, no need to cycle waitpid(). */ + + int exit_code; + + if (waitpid(0, &exit_code, WNOHANG) > 0) { - if (WIFSIGNALED(child_exit_status)) - child_status= CHILD_NEED_RESPAWN; - else - /* - As reap_child is not called for SIGSTOP, we should be here only - if the child exited normally. - */ - child_status= CHILD_EXIT_ANGEL; + child_exit_code= exit_code; + child_status= exit_code ? CHILD_NEED_RESPAWN : CHILD_EXIT_ANGEL; } } @@ -353,7 +349,9 @@ spawn: else if (child_status == CHILD_NEED_RESPAWN) { child_status= CHILD_OK; - log_error("angel(): mysqlmanager exited abnormally: respawning..."); + log_error("angel(): mysqlmanager exited abnormally (exit code: %d):" + "respawning...", + (int) child_exit_code); sleep(1); /* don't respawn too fast */ goto spawn; } diff --git a/server-tools/instance-manager/thread_registry.cc b/server-tools/instance-manager/thread_registry.cc index e061bb3384b..5bb4206982e 100644 --- a/server-tools/instance-manager/thread_registry.cc +++ b/server-tools/instance-manager/thread_registry.cc @@ -53,6 +53,7 @@ Thread_info::Thread_info(pthread_t thread_id_arg) : Thread_registry::Thread_registry() : shutdown_in_progress(false) ,sigwait_thread_pid(pthread_self()) + ,error_status(FALSE) { pthread_mutex_init(&LOCK_thread_registry, 0); pthread_cond_init(&COND_thread_registry_is_empty, 0); @@ -243,3 +244,23 @@ void Thread_registry::request_shutdown() { pthread_kill(sigwait_thread_pid, SIGTERM); } + + +int Thread_registry::get_error_status() +{ + int ret_error_status; + + pthread_mutex_lock(&LOCK_thread_registry); + ret_error_status= error_status; + pthread_mutex_unlock(&LOCK_thread_registry); + + return ret_error_status; +} + + +void Thread_registry::set_error_status() +{ + pthread_mutex_lock(&LOCK_thread_registry); + error_status= TRUE; + pthread_mutex_unlock(&LOCK_thread_registry); +} diff --git a/server-tools/instance-manager/thread_registry.h b/server-tools/instance-manager/thread_registry.h index 694fa57378e..f6de49cd9ad 100644 --- a/server-tools/instance-manager/thread_registry.h +++ b/server-tools/instance-manager/thread_registry.h @@ -97,12 +97,16 @@ public: pthread_mutex_t *mutex); int cond_timedwait(Thread_info *info, pthread_cond_t *cond, pthread_mutex_t *mutex, struct timespec *wait_time); + int get_error_status(); + void set_error_status(); + private: Thread_info head; bool shutdown_in_progress; pthread_mutex_t LOCK_thread_registry; pthread_cond_t COND_thread_registry_is_empty; pthread_t sigwait_thread_pid; + bool error_status; }; From cbb38476e19e8c5582d7d14ce98a8889132110d4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Feb 2007 14:45:19 +0400 Subject: [PATCH 14/55] Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL Having maybe_null flag unset for geometry/spatial functions leads to wrong Item_func_isnull::val_int()'s results. Fix: set maybe_null flag and add is_null() methods. mysql-test/r/gis.result: Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL - test result. mysql-test/t/gis.test: Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL - test case. sql/item_geofunc.cc: Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL - set maybe_null flag for Item_geometry_func and Item_func_as_wkt. - moved length check to the beginnig of the Item_func_spatial_collection::val_str() to affect geometry collection objects at once. - changed Item_func_isempty::val_int() and Item_func_issimple::val_int() to properly handle null_value. sql/item_geofunc.h: Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL - set maybe_null flag for geometry/spatial functions. - added is_null() to Item_geometry_func and Item_func_spatial_rel classes. sql/spatial.cc: Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL - changed return type of Geometry::create_from_wkb() to be consistent with Geometry::create_from_wkt(), now it returns Geometry object or NULL in case of error. sql/spatial.h: Fix for bug #26038: X() value of empty NOT NULL POINT is neither NULL nor NOT NULL - changed return type of Geometry::create_from_wkb() to be consistent with Geometry::create_from_wkt(), now it returns Geometry object or NULL in case of error. --- mysql-test/r/gis.result | 44 ++++++++++++++++++++++++++++++++++++++++- mysql-test/t/gis.test | 36 ++++++++++++++++++++++++++++++++- sql/item_geofunc.cc | 29 ++++++++++++++++----------- sql/item_geofunc.h | 37 +++++++++++++++++++++++++++++----- sql/spatial.cc | 13 ++++++------ sql/spatial.h | 4 ++-- 6 files changed, 136 insertions(+), 27 deletions(-) diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index ce2b5deadbd..de7e44ed7b2 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -578,7 +578,7 @@ create table t1 select POINT(1,3); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `POINT(1,3)` longblob NOT NULL + `POINT(1,3)` longblob ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo` @@ -677,3 +677,45 @@ load data infile '../../std_data/bad_gis_data.dat' into table t1; ERROR 01000: Data truncated; NULL supplied to NOT NULL column 'b' at row 1 alter table t1 enable keys; drop table t1; +create table t1 (a int, b blob); +insert into t1 values (1, ''), (2, NULL), (3, '1'); +select * from t1; +a b +1 +2 NULL +3 1 +select +geometryfromtext(b) IS NULL, geometryfromwkb(b) IS NULL, astext(b) IS NULL, +aswkb(b) IS NULL, geometrytype(b) IS NULL, centroid(b) IS NULL, +envelope(b) IS NULL, startpoint(b) IS NULL, endpoint(b) IS NULL, +exteriorring(b) IS NULL, pointn(b, 1) IS NULL, geometryn(b, 1) IS NULL, +interiorringn(b, 1) IS NULL, multipoint(b) IS NULL, isempty(b) IS NULL, +issimple(b) IS NULL, isclosed(b) IS NULL, dimension(b) IS NULL, +numgeometries(b) IS NULL, numinteriorrings(b) IS NULL, numpoints(b) IS NULL, +area(b) IS NULL, glength(b) IS NULL, srid(b) IS NULL, x(b) IS NULL, +y(b) IS NULL +from t1; +geometryfromtext(b) IS NULL geometryfromwkb(b) IS NULL astext(b) IS NULL aswkb(b) IS NULL geometrytype(b) IS NULL centroid(b) IS NULL envelope(b) IS NULL startpoint(b) IS NULL endpoint(b) IS NULL exteriorring(b) IS NULL pointn(b, 1) IS NULL geometryn(b, 1) IS NULL interiorringn(b, 1) IS NULL multipoint(b) IS NULL isempty(b) IS NULL issimple(b) IS NULL isclosed(b) IS NULL dimension(b) IS NULL numgeometries(b) IS NULL numinteriorrings(b) IS NULL numpoints(b) IS NULL area(b) IS NULL glength(b) IS NULL srid(b) IS NULL x(b) IS NULL y(b) IS NULL +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +select +within(b, b) IS NULL, contains(b, b) IS NULL, overlaps(b, b) IS NULL, +equals(b, b) IS NULL, disjoint(b, b) IS NULL, touches(b, b) IS NULL, +intersects(b, b) IS NULL, crosses(b, b) IS NULL +from t1; +within(b, b) IS NULL contains(b, b) IS NULL overlaps(b, b) IS NULL equals(b, b) IS NULL disjoint(b, b) IS NULL touches(b, b) IS NULL intersects(b, b) IS NULL crosses(b, b) IS NULL +1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 +select +point(b, b) IS NULL, linestring(b) IS NULL, polygon(b) IS NULL, multipoint(b) IS NULL, +multilinestring(b) IS NULL, multipolygon(b) IS NULL, +geometrycollection(b) IS NULL +from t1; +point(b, b) IS NULL linestring(b) IS NULL polygon(b) IS NULL multipoint(b) IS NULL multilinestring(b) IS NULL multipolygon(b) IS NULL geometrycollection(b) IS NULL +0 1 1 1 1 1 1 +1 1 1 1 1 1 1 +0 1 1 1 1 1 1 +drop table t1; +End of 4.1 tests diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index 1ae4f0ae62f..6bd0db92152 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -377,4 +377,38 @@ load data infile '../../std_data/bad_gis_data.dat' into table t1; alter table t1 enable keys; drop table t1; -# End of 4.1 tests +# +# Bug #26038: is null and bad data +# + +create table t1 (a int, b blob); +insert into t1 values (1, ''), (2, NULL), (3, '1'); +select * from t1; + +select + geometryfromtext(b) IS NULL, geometryfromwkb(b) IS NULL, astext(b) IS NULL, + aswkb(b) IS NULL, geometrytype(b) IS NULL, centroid(b) IS NULL, + envelope(b) IS NULL, startpoint(b) IS NULL, endpoint(b) IS NULL, + exteriorring(b) IS NULL, pointn(b, 1) IS NULL, geometryn(b, 1) IS NULL, + interiorringn(b, 1) IS NULL, multipoint(b) IS NULL, isempty(b) IS NULL, + issimple(b) IS NULL, isclosed(b) IS NULL, dimension(b) IS NULL, + numgeometries(b) IS NULL, numinteriorrings(b) IS NULL, numpoints(b) IS NULL, + area(b) IS NULL, glength(b) IS NULL, srid(b) IS NULL, x(b) IS NULL, + y(b) IS NULL +from t1; + +select + within(b, b) IS NULL, contains(b, b) IS NULL, overlaps(b, b) IS NULL, + equals(b, b) IS NULL, disjoint(b, b) IS NULL, touches(b, b) IS NULL, + intersects(b, b) IS NULL, crosses(b, b) IS NULL +from t1; + +select + point(b, b) IS NULL, linestring(b) IS NULL, polygon(b) IS NULL, multipoint(b) IS NULL, + multilinestring(b) IS NULL, multipolygon(b) IS NULL, + geometrycollection(b) IS NULL +from t1; + +drop table t1; + +--echo End of 4.1 tests diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 6bd2e65632f..6cb8c790319 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -30,6 +30,7 @@ void Item_geometry_func::fix_length_and_dec() collation.set(&my_charset_bin); decimals=0; max_length=MAX_BLOB_WIDTH; + maybe_null= 1; } @@ -109,6 +110,7 @@ String *Item_func_as_wkt::val_str(String *str) void Item_func_as_wkt::fix_length_and_dec() { max_length=MAX_BLOB_WIDTH; + maybe_null= 1; } @@ -356,7 +358,8 @@ String *Item_func_spatial_collection::val_str(String *str) for (i= 0; i < arg_count; ++i) { String *res= args[i]->val_str(&arg_value); - if (args[i]->null_value) + uint32 len; + if (args[i]->null_value || ((len= res->length()) < WKB_HEADER_SIZE)) goto err; if (coll_type == Geometry::wkb_geometrycollection) @@ -365,13 +368,12 @@ String *Item_func_spatial_collection::val_str(String *str) In the case of GeometryCollection we don't need any checkings for item types, so just copy them into target collection */ - if (str->append(res->ptr(), res->length(), (uint32) 512)) + if (str->append(res->ptr(), len, (uint32) 512)) goto err; } else { enum Geometry::wkbType wkb_type; - uint32 len=res->length(); const char *data= res->ptr() + 1; /* @@ -379,8 +381,6 @@ String *Item_func_spatial_collection::val_str(String *str) are of specific type, let's do this checking now */ - if (len < 5) - goto err; wkb_type= (Geometry::wkbType) uint4korr(data); data+= 4; len-= 5; @@ -502,9 +502,13 @@ longlong Item_func_spatial_rel::val_int() longlong Item_func_isempty::val_int() { DBUG_ASSERT(fixed == 1); - String tmp; - null_value=0; - return args[0]->null_value ? 1 : 0; + String tmp; + String *swkb= args[0]->val_str(&tmp); + Geometry_buffer buffer; + + null_value= args[0]->null_value || + !(Geometry::construct(&buffer, swkb->ptr(), swkb->length())); + return null_value ? 1 : 0; } @@ -512,10 +516,11 @@ longlong Item_func_issimple::val_int() { DBUG_ASSERT(fixed == 1); String tmp; - String *wkb=args[0]->val_str(&tmp); - - if ((null_value= (!wkb || args[0]->null_value))) - return 0; + String *swkb= args[0]->val_str(&tmp); + Geometry_buffer buffer; + + null_value= args[0]->null_value || + !(Geometry::construct(&buffer, swkb->ptr(), swkb->length())); /* TODO: Ramil or Holyfoot, add real IsSimple calculation */ return 0; } diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index a466b606dc1..2719cbb0bab 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -33,6 +33,7 @@ public: Item_geometry_func(List &list) :Item_str_func(list) {} void fix_length_and_dec(); enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } + bool is_null() { (void) val_int(); return null_value; } }; class Item_func_geometry_from_text: public Item_geometry_func @@ -80,6 +81,7 @@ public: void fix_length_and_dec() { max_length=20; // "GeometryCollection" is the most long + maybe_null= 1; }; }; @@ -221,6 +223,8 @@ public: } } void print(String *str) { Item_func::print(str); } + void fix_length_and_dec() { maybe_null= 1; } + bool is_null() { (void) val_int(); return null_value; } }; class Item_func_isempty: public Item_bool_func @@ -230,6 +234,7 @@ public: longlong val_int(); optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "isempty"; } + void fix_length_and_dec() { maybe_null= 1; } }; class Item_func_issimple: public Item_bool_func @@ -239,6 +244,7 @@ public: longlong val_int(); optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "issimple"; } + void fix_length_and_dec() { maybe_null= 1; } }; class Item_func_isclosed: public Item_bool_func @@ -248,6 +254,7 @@ public: longlong val_int(); optimize_type select_optimize() const { return OPTIMIZE_NONE; } const char *func_name() const { return "isclosed"; } + void fix_length_and_dec() { maybe_null= 1; } }; class Item_func_dimension: public Item_int_func @@ -257,7 +264,7 @@ public: Item_func_dimension(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "dimension"; } - void fix_length_and_dec() { max_length=10; } + void fix_length_and_dec() { max_length= 10; maybe_null= 1; } }; class Item_func_x: public Item_real_func @@ -267,6 +274,11 @@ public: Item_func_x(Item *a): Item_real_func(a) {} double val(); const char *func_name() const { return "x"; } + void fix_length_and_dec() + { + Item_real_func::fix_length_and_dec(); + maybe_null= 1; + } }; @@ -277,6 +289,11 @@ public: Item_func_y(Item *a): Item_real_func(a) {} double val(); const char *func_name() const { return "y"; } + void fix_length_and_dec() + { + Item_real_func::fix_length_and_dec(); + maybe_null= 1; + } }; @@ -287,7 +304,7 @@ public: Item_func_numgeometries(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "numgeometries"; } - void fix_length_and_dec() { max_length=10; } + void fix_length_and_dec() { max_length= 10; maybe_null= 1; } }; @@ -298,7 +315,7 @@ public: Item_func_numinteriorring(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "numinteriorrings"; } - void fix_length_and_dec() { max_length=10; } + void fix_length_and_dec() { max_length= 10; maybe_null= 1; } }; @@ -309,7 +326,7 @@ public: Item_func_numpoints(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "numpoints"; } - void fix_length_and_dec() { max_length=10; } + void fix_length_and_dec() { max_length= 10; maybe_null= 1; } }; @@ -320,6 +337,11 @@ public: Item_func_area(Item *a): Item_real_func(a) {} double val(); const char *func_name() const { return "area"; } + void fix_length_and_dec() + { + Item_real_func::fix_length_and_dec(); + maybe_null= 1; + } }; @@ -330,6 +352,11 @@ public: Item_func_glength(Item *a): Item_real_func(a) {} double val(); const char *func_name() const { return "glength"; } + void fix_length_and_dec() + { + Item_real_func::fix_length_and_dec(); + maybe_null= 1; + } }; @@ -340,7 +367,7 @@ public: Item_func_srid(Item *a): Item_int_func(a) {} longlong val_int(); const char *func_name() const { return "srid"; } - void fix_length_and_dec() { max_length= 10; } + void fix_length_and_dec() { max_length= 10; maybe_null= 1; } }; #define GEOM_NEW(obj_constructor) new obj_constructor diff --git a/sql/spatial.cc b/sql/spatial.cc index 684f7e9ecf3..4e17e766090 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -210,23 +210,24 @@ static uint32 wkb_get_uint(const char *ptr, Geometry::wkbByteOrder bo) } -int Geometry::create_from_wkb(Geometry_buffer *buffer, - const char *wkb, uint32 len, String *res) +Geometry *Geometry::create_from_wkb(Geometry_buffer *buffer, + const char *wkb, uint32 len, String *res) { uint32 geom_type; Geometry *geom; if (len < WKB_HEADER_SIZE) - return 1; + return NULL; geom_type= wkb_get_uint(wkb+1, (wkbByteOrder)wkb[0]); if (!(geom= create_by_typeid(buffer, (int) geom_type)) || res->reserve(WKB_HEADER_SIZE, 512)) - return 1; + return NULL; res->q_append((char) wkb_ndr); res->q_append(geom_type); - return geom->init_from_wkb(wkb+WKB_HEADER_SIZE, len - WKB_HEADER_SIZE, - (wkbByteOrder) wkb[0], res); + + return geom->init_from_wkb(wkb + WKB_HEADER_SIZE, len - WKB_HEADER_SIZE, + (wkbByteOrder) wkb[0], res) ? geom : NULL; } diff --git a/sql/spatial.h b/sql/spatial.h index 378233a2156..553544d4c3f 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -244,8 +244,8 @@ public: static Geometry *create_from_wkt(Geometry_buffer *buffer, Gis_read_stream *trs, String *wkt, bool init_stream=1); - static int create_from_wkb(Geometry_buffer *buffer, - const char *wkb, uint32 len, String *res); + static Geometry *create_from_wkb(Geometry_buffer *buffer, const char *wkb, + uint32 len, String *res); int as_wkt(String *wkt, const char **end) { uint32 len= get_class_info()->m_name.length; From a62c32bd7d3bb13a78fe513d15c833b9e09292a6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Feb 2007 18:00:12 +0100 Subject: [PATCH 15/55] ndb - bug#26515 make sure logPartPtr is correctly initialized ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: fix bug#26515 make sure logPartPtr is correctly initialized --- ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index ab5deca27b5..796b7245def 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -11950,6 +11950,10 @@ void Dblqh::execFSCLOSECONF(Signal* signal) // Set the prev file to check if we shall close it. logFilePtr.i = logFilePtr.p->prevLogFile; ptrCheckGuard(logFilePtr, clogFileFileSize, logFileRecord); + + logPartPtr.i = logFilePtr.p->logPartRec; + ptrCheckGuard(logPartPtr, clogPartFileSize, logPartRecord); + exitFromInvalidate(signal); return; case LogFileRecord::CLOSING_INIT: From 40bfc4c018414614da5d91b0c47c67f33f269e77 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 21 Feb 2007 18:01:04 +0100 Subject: [PATCH 16/55] ndb - Make StartREDO come up as default in cluster log ndb/src/common/debugger/EventLogger.cpp: Make StartREDO come up as default in cluster log --- ndb/src/common/debugger/EventLogger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp index c6f02a7807a..2defdfc8de5 100644 --- a/ndb/src/common/debugger/EventLogger.cpp +++ b/ndb/src/common/debugger/EventLogger.cpp @@ -836,7 +836,7 @@ const EventLoggerBase::EventRepLogLevelMatrix EventLoggerBase::matrix[] = { ROW(NDBStopCompleted, LogLevel::llStartUp, 1, Logger::LL_INFO ), ROW(NDBStopForced, LogLevel::llStartUp, 1, Logger::LL_ALERT ), ROW(NDBStopAborted, LogLevel::llStartUp, 1, Logger::LL_INFO ), - ROW(StartREDOLog, LogLevel::llStartUp, 10, Logger::LL_INFO ), + ROW(StartREDOLog, LogLevel::llStartUp, 4, Logger::LL_INFO ), ROW(StartLog, LogLevel::llStartUp, 10, Logger::LL_INFO ), ROW(UNDORecordsExecuted, LogLevel::llStartUp, 15, Logger::LL_INFO ), ROW(StartReport, LogLevel::llStartUp, 4, Logger::LL_INFO ), From b5b3c616d55c385fa29950581f0e1e7846441704 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Feb 2007 15:31:21 +0100 Subject: [PATCH 17/55] ndb - bug#26481 - fix of bug fix 5.0 version --- ndb/src/kernel/blocks/dblqh/DblqhMain.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp index 796b7245def..698e5ac292c 100644 --- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp +++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp @@ -457,6 +457,7 @@ void Dblqh::execCONTINUEB(Signal* signal) else { jam(); + cstartRecReq = 2; StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); conf->startingNodeId = getOwnNodeId(); sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, @@ -11673,7 +11674,7 @@ void Dblqh::execGCP_SAVEREQ(Signal* signal) return; } - if(getNodeState().getNodeRestartInProgress() && cstartRecReq == ZFALSE) + if(getNodeState().getNodeRestartInProgress() && cstartRecReq < 2) { GCPSaveRef * const saveRef = (GCPSaveRef*)&signal->theData[0]; saveRef->dihPtr = dihPtr; @@ -13822,7 +13823,7 @@ void Dblqh::srCompletedLab(Signal* signal) * NO MORE FRAGMENTS ARE WAITING FOR SYSTEM RESTART. * -------------------------------------------------------------------- */ lcpPtr.p->lcpState = LcpRecord::LCP_IDLE; - if (cstartRecReq == ZTRUE) { + if (cstartRecReq == 1) { jam(); /* ---------------------------------------------------------------- * WE HAVE ALSO RECEIVED AN INDICATION THAT NO MORE FRAGMENTS @@ -13892,7 +13893,7 @@ void Dblqh::execSTART_RECREQ(Signal* signal) ndbrequire(req->receivingNodeId == cownNodeid); cnewestCompletedGci = cnewestGci; - cstartRecReq = ZTRUE; + cstartRecReq = 1; for (logPartPtr.i = 0; logPartPtr.i < 4; logPartPtr.i++) { ptrAss(logPartPtr, logPartRecord); logPartPtr.p->logPartNewestCompletedGCI = cnewestCompletedGci; @@ -13913,6 +13914,7 @@ void Dblqh::execSTART_RECREQ(Signal* signal) }//if if(cstartType == NodeState::ST_INITIAL_NODE_RESTART){ jam(); + cstartRecReq = 2; StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); conf->startingNodeId = getOwnNodeId(); sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, @@ -15733,6 +15735,7 @@ void Dblqh::srFourthComp(Signal* signal) else { jam(); + cstartRecReq = 2; StartRecConf * conf = (StartRecConf*)signal->getDataPtrSend(); conf->startingNodeId = getOwnNodeId(); sendSignal(cmasterDihBlockref, GSN_START_RECCONF, signal, @@ -16699,7 +16702,7 @@ void Dblqh::initialiseRecordsLab(Signal* signal, Uint32 data, cCommitBlocked = false; ccurrentGcprec = RNIL; caddNodeState = ZFALSE; - cstartRecReq = ZFALSE; + cstartRecReq = 0; cnewestGci = (UintR)-1; cnewestCompletedGci = (UintR)-1; crestartOldestGci = 0; From df1104ff4536f5a4bffefa19f3424d0d8506ade2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Feb 2007 20:24:32 +0300 Subject: [PATCH 18/55] BUG#24415: im_daemon_life_cycle.imtest fails Fix timeouts. Only test suite is changed. mysql-test/mysql-test-run.pl: Decrease MySQL server shutdown delay. Trasactional storage engines are not used here, so it should be enough. mysql-test/t/im_daemon_life_cycle.imtest: Increase wait-timeout. --- mysql-test/mysql-test-run.pl | 1 + mysql-test/t/im_daemon_life_cycle.imtest | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 2c66b148dcd..a2460edec73 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2993,6 +2993,7 @@ language = $path_language character-sets-dir = $path_charsetsdir basedir = $path_my_basedir server_id = $server_id +shutdown-delay = 10 skip-stack-trace skip-innodb skip-ndbcluster diff --git a/mysql-test/t/im_daemon_life_cycle.imtest b/mysql-test/t/im_daemon_life_cycle.imtest index acd615809f3..0ecc3f18f40 100644 --- a/mysql-test/t/im_daemon_life_cycle.imtest +++ b/mysql-test/t/im_daemon_life_cycle.imtest @@ -23,15 +23,20 @@ # - wait for IM-main to start accepting connections before continue test # case; # +# NOTE: timeout is 55 seconds. Timeout should be more than shutdown-delay +# specified for managed MySQL instance. Now shutdown-delay is 10 seconds +# (set in mysql-test-run.pl). So, 55 seconds should be enough to make 5 +# attempts. +# ########################################################################### --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Main-test: starting... --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Killing IM-main... ---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 55 im_daemon_life_cycle --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections... ---exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 55 im_daemon_life_cycle --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Main-test: done. @@ -58,23 +63,23 @@ START INSTANCE mysqld2; --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: waiting to start... ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 started im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 55 started im_daemon_life_cycle --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: started. # 2. Restart IM-main; --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Killing IM-main... ---exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 30 im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/kill_n_check.sh $IM_PATH_PID restarted 55 im_daemon_life_cycle --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Waiting for IM-main to start accepting connections... ---exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 30 im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/wait_for_socket.sh $EXE_MYSQL $IM_PATH_SOCK $IM_USERNAME $IM_PASSWORD '' 55 im_daemon_life_cycle # 3. Issue some statement -- connection should be re-established. --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle Checking that IM-main processing commands... ---replace_column 3 VERSION +--replace_column 2 STATE 3 VERSION SHOW INSTANCE STATUS mysqld1; # 4. Stop mysqld2, because it will not be stopped by IM, as it is nonguarded. @@ -85,7 +90,7 @@ SHOW INSTANCE STATUS mysqld1; STOP INSTANCE mysqld2; --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: waiting to stop... ---exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 30 stopped im_daemon_life_cycle +--exec $MYSQL_TEST_DIR/t/wait_for_process.sh $IM_MYSQLD2_PATH_PID 55 stopped im_daemon_life_cycle --exec $MYSQL_TEST_DIR/t/log.sh im_daemon_life_cycle mysqld2: stopped. ########################################################################### From 49b66418a0c35600839f8dda07bb70e248a392ea Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Feb 2007 20:49:01 +0300 Subject: [PATCH 19/55] Fix test for views with national characters, which accidentally got broken during the merge on 16-Feb-2007. mysql-test/r/view.result: Updated result file. mysql-test/t/view.test: Fix test for views with national characters, which accidentally got broken during the merge on 16-Feb-2007. Now view.test is in UTF8 character set, so SET NAMES is required. --- mysql-test/r/view.result | 18 ++++++++++-------- mysql-test/t/view.test | 14 ++++++++------ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 6dad86712e4..34bcf37f091 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -834,14 +834,16 @@ show create view v1; View Create View v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 99999999999999999999999999999999999999999999999999999 AS `col1` drop view v1; -create table t (c char); -create view v as select c from t; -insert into v values (''); -select * from v; -c - -drop view v; -drop table t; +set names utf8; +create table tü (cü char); +create view vü as select cü from tü; +insert into vü values ('ü'); +select * from vü; +cü +ü +drop view vü; +drop table tü; +set names latin1; create table t1 (a int, b int); insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10); create view v1(c) as select a+1 from t1 where b >= 4; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d100630cf24..90a3c6a1e2d 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -748,12 +748,14 @@ drop view v1; # # VIEWs with national characters # -create table t (c char); -create view v as select c from t; -insert into v values (''); -select * from v; -drop view v; -drop table t; +set names utf8; +create table tü (cü char); +create view vü as select cü from tü; +insert into vü values ('ü'); +select * from vü; +drop view vü; +drop table tü; +set names latin1; # # problem with used_tables() of outer reference resolved in VIEW From 17fca8e3332b086cf76c3f42a463fcea6bf1bb79 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Feb 2007 21:13:21 +0300 Subject: [PATCH 20/55] Fix result file. --- mysql-test/r/im_daemon_life_cycle.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/im_daemon_life_cycle.result b/mysql-test/r/im_daemon_life_cycle.result index d80a34f8427..1a0741e7caf 100644 --- a/mysql-test/r/im_daemon_life_cycle.result +++ b/mysql-test/r/im_daemon_life_cycle.result @@ -21,6 +21,6 @@ Success: the process was restarted. Success: server is ready to accept connection on socket. SHOW INSTANCE STATUS mysqld1; instance_name status version -mysqld1 online VERSION +mysqld1 STATE VERSION STOP INSTANCE mysqld2; Success: the process has been stopped. From 37a5703bc7d815cd93a4c6deee2f8ad266784098 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Feb 2007 21:51:33 +0300 Subject: [PATCH 21/55] Fix mysql-test-run.pl: IM in 5.0 uses old incorrect 'shutdown_delay' option name. mysql-test/mysql-test-run.pl: IM in 5.0 uses old incorrect 'shutdown_delay' option name. --- mysql-test/mysql-test-run.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a2460edec73..a64808cfb87 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2993,7 +2993,7 @@ language = $path_language character-sets-dir = $path_charsetsdir basedir = $path_my_basedir server_id = $server_id -shutdown-delay = 10 +shutdown_delay = 10 skip-stack-trace skip-innodb skip-ndbcluster From 94d4f324eca7dade5c18fa3ed567a8f624e7e1ba Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Feb 2007 13:10:04 +0300 Subject: [PATCH 22/55] Fix shutdown delay option name according to The Manual. --- mysql-test/mysql-test-run.pl | 2 +- server-tools/instance-manager/instance_options.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a64808cfb87..a2460edec73 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2993,7 +2993,7 @@ language = $path_language character-sets-dir = $path_charsetsdir basedir = $path_my_basedir server_id = $server_id -shutdown_delay = 10 +shutdown-delay = 10 skip-stack-trace skip-innodb skip-ndbcluster diff --git a/server-tools/instance-manager/instance_options.cc b/server-tools/instance-manager/instance_options.cc index c816069c51e..f19700de64d 100644 --- a/server-tools/instance-manager/instance_options.cc +++ b/server-tools/instance-manager/instance_options.cc @@ -510,7 +510,7 @@ int Instance_options::add_option(const char* option) {"--pid-file=", 11, &mysqld_pid_file, SAVE_WHOLE_AND_ADD}, {"--mysqld-path=", 14, &mysqld_path, SAVE_VALUE}, {"--nonguarded", 9, &nonguarded, SAVE_WHOLE}, - {"--shutdown_delay", 9, &shutdown_delay, SAVE_VALUE}, + {"--shutdown-delay", 9, &shutdown_delay, SAVE_VALUE}, {NULL, 0, NULL, 0} }; struct selected_options_st *selected_options; From f44759c71d870585b661ff6e6aa746a3c1fa4ede Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Feb 2007 13:12:20 +0300 Subject: [PATCH 23/55] IM test suite fix. Log messages from shell-scripts were put to var/log/.log file. Now, this file is used by mysql-test-run.pl. So, move log messages to var/log/.script.log. mysql-test/t/kill_n_check.sh: Log messages from shell-scripts were put to var/log/.log file. Now, this file is used by mysql-test-run.pl. So, move log messages to var/log/.script.log. mysql-test/t/log.sh: Log messages from shell-scripts were put to var/log/.log file. Now, this file is used by mysql-test-run.pl. So, move log messages to var/log/.script.log. mysql-test/t/wait_for_process.sh: Log messages from shell-scripts were put to var/log/.log file. Now, this file is used by mysql-test-run.pl. So, move log messages to var/log/.script.log. mysql-test/t/wait_for_socket.sh: Log messages from shell-scripts were put to var/log/.log file. Now, this file is used by mysql-test-run.pl. So, move log messages to var/log/.script.log. --- mysql-test/t/kill_n_check.sh | 2 +- mysql-test/t/log.sh | 2 +- mysql-test/t/wait_for_process.sh | 2 +- mysql-test/t/wait_for_socket.sh | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/t/kill_n_check.sh b/mysql-test/t/kill_n_check.sh index 96c402a638c..6f2a0825dcd 100755 --- a/mysql-test/t/kill_n_check.sh +++ b/mysql-test/t/kill_n_check.sh @@ -53,7 +53,7 @@ pid_path="$1" expected_result="$2" total_timeout="$3" test_id="$4" -log_file="$MYSQLTEST_VARDIR/log/$test_id.log" +log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log" log_debug "-- $basename: starting --" log_debug "pid_path: '$pid_path'" diff --git a/mysql-test/t/log.sh b/mysql-test/t/log.sh index 29cf8d3e1a3..33ef6d6701f 100755 --- a/mysql-test/t/log.sh +++ b/mysql-test/t/log.sh @@ -17,7 +17,7 @@ if [ $# -lt 2 ]; then fi test_id="$1" -log_file="$MYSQLTEST_VARDIR/log/$test_id.log" +log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log" shift diff --git a/mysql-test/t/wait_for_process.sh b/mysql-test/t/wait_for_process.sh index 4c2d89cfea6..2143ab2002f 100755 --- a/mysql-test/t/wait_for_process.sh +++ b/mysql-test/t/wait_for_process.sh @@ -63,7 +63,7 @@ pid_path="$1" total_attempts="$2" event="$3" test_id="$4" -log_file="$MYSQLTEST_VARDIR/log/$test_id.log" +log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log" log_debug "-- $basename: starting --" log_debug "pid_path: '$pid_path'" diff --git a/mysql-test/t/wait_for_socket.sh b/mysql-test/t/wait_for_socket.sh index 1bce74dfd3a..8c17c8ac0ac 100755 --- a/mysql-test/t/wait_for_socket.sh +++ b/mysql-test/t/wait_for_socket.sh @@ -30,7 +30,7 @@ password="$4" db="$5" total_timeout="$6" test_id="$7" -log_file="$MYSQLTEST_VARDIR/log/$test_id.log" +log_file="$MYSQLTEST_VARDIR/log/$test_id.script.log" log_debug "-- $basename: starting --" log_debug "client_exe: '$client_exe'" From 8251e016d7ddc5efbefab0edbcef461d4b60d747 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Feb 2007 13:18:09 +0300 Subject: [PATCH 24/55] Fix for BUG#22511: IM does not remove angel-pid-file on clean shutdown server-tools/instance-manager/mysqlmanager.cc: Delete IM-angel pid file on exit. --- server-tools/instance-manager/mysqlmanager.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc index 83918092454..4f378c61ca4 100644 --- a/server-tools/instance-manager/mysqlmanager.cc +++ b/server-tools/instance-manager/mysqlmanager.cc @@ -355,6 +355,10 @@ spawn: sleep(1); /* don't respawn too fast */ goto spawn; } + + /* Delete IM-angel pid file. */ + my_delete(Options::angel_pid_file_name, MYF(0)); + /* mysqlmanager successfully exited, let's silently evaporate If we return to main we fall into the manager() function, so let's From e1426fee11d656f041e2b1f5d32ee91eec17583f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Feb 2007 11:23:00 +0100 Subject: [PATCH 25/55] A binary package should also contain the "mysqld-debug" server (backport from 5.1). --- scripts/make_binary_distribution.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/make_binary_distribution.sh b/scripts/make_binary_distribution.sh index 008520ef000..96cd1868862 100644 --- a/scripts/make_binary_distribution.sh +++ b/scripts/make_binary_distribution.sh @@ -143,7 +143,8 @@ BIN_FILES="extra/comp_err$BS extra/replace$BS extra/perror$BS \ extra/resolve_stack_dump$BS extra/mysql_waitpid$BS \ myisam/myisamchk$BS myisam/myisampack$BS myisam/myisamlog$BS \ myisam/myisam_ftdump$BS \ - sql/mysqld$BS sql/mysql_tzinfo_to_sql$BS \ + sql/mysqld$BS sql/mysqld-debug$BS \ + sql/mysql_tzinfo_to_sql$BS \ server-tools/instance-manager/mysqlmanager$BS \ client/mysql$BS client/mysqlshow$BS client/mysqladmin$BS \ client/mysqldump$BS client/mysqlimport$BS \ From d9227f159fccfc5167920f48297d5a7ac24a7a1b Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Feb 2007 16:03:38 +0300 Subject: [PATCH 26/55] Add more comments to open_table and open_tables. No real changes. --- sql/sql_base.cc | 116 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 5 deletions(-) diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ad9cd5985d1..b324c1a2e42 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1210,6 +1210,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, int4store(key + key_length, thd->server_id); int4store(key + key_length + 4, thd->variables.pseudo_thread_id); + /* + Unless requested otherwise, try to resolve this table in the list + of temporary tables of this thread. In MySQL temporary tables + are always thread-local and "shadow" possible base tables with the + same name. This block implements the behaviour. + TODO: move this block into a separate function. + */ if (!table_list->skip_temporary) { for (table= thd->temporary_tables; table ; table=table->next) @@ -1218,6 +1225,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, !memcmp(table->s->table_cache_key, key, key_length + TMP_TABLE_KEY_EXTRA)) { + /* + We're trying to use the same temporary table twice in a query. + Right now we don't support this because a temporary table + is always represented by only one TABLE object in THD, and + it can not be cloned. Emit an error for an unsupported behaviour. + */ if (table->query_id == thd->query_id || thd->prelocked_mode && table->query_id) { @@ -1233,6 +1246,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } } + /* + The table is not temporary - if we're in pre-locked or LOCK TABLES + mode, let's try to find the requested table in the list of pre-opened + and locked tables. If the table is not there, return an error - we can't + open not pre-opened tables in pre-locked/LOCK TABLES mode. + TODO: move this block into a separate function. + */ if (!(flags & MYSQL_OPEN_IGNORE_LOCKED_TABLES) && (thd->locked_tables || thd->prelocked_mode)) { // Using table locks @@ -1304,7 +1324,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, goto reset; } /* - is it view? + Is this table a view and not a base table? (it is work around to allow to open view with locked tables, real fix will be made after definition cache will be made) */ @@ -1338,8 +1358,32 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, DBUG_RETURN(0); } + /* + Non pre-locked/LOCK TABLES mode, and the table is not temporary: + this is the normal use case. + Now we should: + - try to find the table in the table cache. + - if one of the discovered TABLE instances is name-locked + (table->s->version == 0) or some thread has started FLUSH TABLES + (refresh_version > table->s->version), back off -- we have to wait + until no one holds a name lock on the table. + - if there is no such TABLE in the name cache, read the table definition + and insert it into the cache. + We perform all of the above under LOCK_open which currently protects + the open cache (also known as table cache) and table definitions stored + on disk. + */ + VOID(pthread_mutex_lock(&LOCK_open)); + /* + If it's the first table from a list of tables used in a query, + remember refresh_version (the version of open_cache state). + If the version changes while we're opening the remaining tables, + we will have to back off, close all the tables opened-so-far, + and try to reopen them. + Note: refresh_version is currently changed only during FLUSH TABLES. + */ if (!thd->open_tables) thd->version=refresh_version; else if ((thd->version != refresh_version) && @@ -1356,12 +1400,39 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, if (thd->handler_tables) mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE); + /* + Actually try to find the table in the open_cache. + The cache may contain several "TABLE" instances for the same + physical table. The instances that are currently "in use" by + some thread have their "in_use" member != NULL. + There is no good reason for having more than one entry in the + hash for the same physical table, except that we use this as + an implicit "pending locks queue" - see + wait_for_locked_table_names for details. + */ for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length, &state); table && table->in_use ; table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length, &state)) { + /* + Normally, table->s->version contains the value of + refresh_version from the moment when this table was + (re-)opened and added to the cache. + If since then we did (or just started) FLUSH TABLES + statement, refresh_version has been increased. + For "name-locked" TABLE instances, table->s->version is set + to 0 (see lock_table_name for details). + In case there is a pending FLUSH TABLES or a name lock, we + need to back off and re-start opening tables. + If we do not back off now, we may dead lock in case of lock + order mismatch with some other thread: + c1: name lock t1; -- sort of exclusive lock + c2: open t2; -- sort of shared lock + c1: name lock t2; -- blocks + c2: open t1; -- blocks + */ if (table->s->version != refresh_version) { DBUG_PRINT("note", @@ -1375,16 +1446,35 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } /* - There is a refresh in progress for this table - Wait until the table is freed or the thread is killed. + Back off, part 1: mark the table as "unused" for the + purpose of name-locking by setting table->db_stat to 0. Do + that only for the tables in this thread that have an old + table->s->version (this is an optimization (?)). + table->db_stat == 0 signals wait_for_locked_table_names + that the tables in question are not used any more. See + table_is_used call for details. */ close_old_data_files(thd,thd->open_tables,0,0); + /* + Back-off part 2: try to avoid "busy waiting" on the table: + if the table is in use by some other thread, we suspend + and wait till the operation is complete: when any + operation that juggles with table->s->version completes, + it broadcasts COND_refresh condition variable. + */ if (table->in_use != thd) + { wait_for_refresh(thd); + /* wait_for_refresh will unlock LOCK_open for us */ + } else { VOID(pthread_mutex_unlock(&LOCK_open)); } + /* + There is a refresh in progress for this table. + Signal the caller that it has to try again. + */ if (refresh) *refresh=1; DBUG_RETURN(0); @@ -1392,6 +1482,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } if (table) { + /* Unlink the table from "unused_tables" list. */ if (table == unused_tables) { // First unused unused_tables=unused_tables->next; // Remove from link @@ -1404,6 +1495,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, } else { + /* Insert a new TABLE instance into the open cache */ TABLE_SHARE *share; int error; /* Free cache if too big */ @@ -2145,6 +2237,10 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) } } + /* + For every table in the list of tables to open, try to find or open + a table. + */ for (tables= *start; tables ;tables= tables->next_global) { /* @@ -2159,6 +2255,12 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) goto process_view_routines; continue; } + /* + If this TABLE_LIST object is a placeholder for an information_schema + table, create a temporary table to represent the information_schema + table in the query. Do not fill it yet - will be filled during + execution. + */ if (tables->schema_table) { if (!mysql_schema_table(thd, thd->lex, tables)) @@ -2166,7 +2268,11 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) DBUG_RETURN(-1); } (*counter)++; - + + /* + Not a placeholder: must be a base table or a view, and the table is + not opened yet. Try to open the table. + */ if (!tables->table && !(tables->table= open_table(thd, tables, &new_frm_mem, &refresh, flags))) { @@ -2273,7 +2379,7 @@ process_view_routines: { /* Serious error during reading stored routines from mysql.proc table. - Something's wrong with the table or its contents, and an error has + Something is wrong with the table or its contents, and an error has been emitted; we must abort. */ result= -1; From 5a232872eb223610325eed3bb57c221a6bfd4af6 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Feb 2007 22:09:09 +0100 Subject: [PATCH 27/55] Makefile.am: EXCEPTIONS-CLIENT is now static part of repository EXCEPTIONS-CLIENT: BitKeeper file /home/kent/bk/tmp/mysql-4.0/EXCEPTIONS-CLIENT EXCEPTIONS-CLIENT: BitKeeper file /home/kent/bk/tmp/mysql-4.0/EXCEPTIONS-CLIENT Docs/Makefile.am: EXCEPTIONS-CLIENT is now static part of repository --- Docs/Makefile.am | 3 -- EXCEPTIONS-CLIENT | 117 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 EXCEPTIONS-CLIENT diff --git a/Docs/Makefile.am b/Docs/Makefile.am index dba3a4f819c..b329b574f6a 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -44,9 +44,6 @@ GT = $(srcdir)/Support/generate-text-files.pl INSTALL-BINARY: mysql.info $(GT) perl -w $(GT) mysql.info "installing-binary" "installing-source" > $@ -../EXCEPTIONS-CLIENT: mysql.info $(GT) - perl -w $(GT) mysql.info "mysql-floss-license-exception" "function-index" > $@ - ../support-files/MacOSX/ReadMe.txt: mysql.info $(GT) perl -w $(GT) mysql.info "mac-os-x-installation" "netware-installation" > $@ diff --git a/EXCEPTIONS-CLIENT b/EXCEPTIONS-CLIENT new file mode 100644 index 00000000000..19b86cab32b --- /dev/null +++ b/EXCEPTIONS-CLIENT @@ -0,0 +1,117 @@ +MySQL FLOSS License Exception + +The MySQL AB Exception for Free/Libre and Open Source +Software-only Applications Using MySQL Client Libraries (the +"FLOSS Exception"). + +Version 0.5, 30 August 2006 + +Exception Intent + +We want specified Free/Libre and Open Source Software (``FLOSS'') +applications to be able to use specified GPL-licensed MySQL client +libraries (the ``Program'') despite the fact that not all FLOSS +licenses are compatible with version 2 of the GNU General Public +License (the ``GPL''). + +Legal Terms and Conditions + +As a special exception to the terms and conditions of version 2.0 +of the GPL: + + 1. You are free to distribute a Derivative Work that is formed + entirely from the Program and one or more works (each, a + "FLOSS Work") licensed under one or more of the licenses + listed below in section 1, as long as: + a. You obey the GPL in all respects for the Program and the + Derivative Work, except for identifiable sections of the + Derivative Work which are not derived from the Program, + and which can reasonably be considered independent and + separate works in themselves, + b. all identifiable sections of the Derivative Work which + are not derived from the Program, and which can + reasonably be considered independent and separate works + in themselves, + i. are distributed subject to one of the FLOSS licenses + listed below, and + ii. the object code or executable form of those sections + are accompanied by the complete corresponding + machine-readable source code for those sections on + the same medium and under the same FLOSS license as + the corresponding object code or executable forms of + those sections, and + c. any works which are aggregated with the Program or with a + Derivative Work on a volume of a storage or distribution + medium in accordance with the GPL, can reasonably be + considered independent and separate works in themselves + which are not derivatives of either the Program, a + Derivative Work or a FLOSS Work. + If the above conditions are not met, then the Program may only + be copied, modified, distributed or used under the terms and + conditions of the GPL or another valid licensing option from + MySQL AB. + + 2. FLOSS License List + +License name Version(s)/Copyright Date +Academic Free License 2.0 +Apache Software License 1.0/1.1/2.0 +Apple Public Source License 2.0 +Artistic license From Perl 5.8.0 +BSD license "July 22 1999" +Common Public License 1.0 +GNU Library or "Lesser" General Public License (LGPL) 2.0/2.1 +Jabber Open Source License 1.0 +MIT license --- +Mozilla Public License (MPL) 1.0/1.1 +Open Software License 2.0 +OpenSSL license (with original SSLeay license) "2003" ("1998") +PHP License 3.0 +Python license (CNRI Python License) --- +Python Software Foundation License 2.1.1 +Sleepycat License "1999" +University of Illinois/NCSA Open Source License --- +W3C License "2001" +X11 License "2001" +Zlib/libpng License --- +Zope Public License 2.0 + + Due to the many variants of some of the above licenses, we + require that any version follow the 2003 version of the Free + Software Foundation's Free Software Definition + (http://www.gnu.org/philosophy/free-sw.html) or version 1.9 of + the Open Source Definition by the Open Source Initiative + (http://www.opensource.org/docs/definition.php). + + 3. Definitions + + a. Terms used, but not defined, herein shall have the + meaning provided in the GPL. + b. Derivative Work means a derivative work under copyright + law. + + 4. Applicability: This FLOSS Exception applies to all Programs + that contain a notice placed by MySQL AB saying that the + Program may be distributed under the terms of this FLOSS + Exception. If you create or distribute a work which is a + Derivative Work of both the Program and any other work + licensed under the GPL, then this FLOSS Exception is not + available for that work; thus, you must remove the FLOSS + Exception notice from that work and comply with the GPL in all + respects, including by retaining all GPL notices. You may + choose to redistribute a copy of the Program exclusively under + the terms of the GPL by removing the FLOSS Exception notice + from that copy of the Program, provided that the copy has + never been modified by you or any third party. + +Appendix A. Qualified Libraries and Packages + +The following is a non-exhaustive list of libraries and packages +which are covered by the FLOSS License Exception. Please note that +this appendix is provided merely as an additional service to +specific FLOSS projects wishing to simplify licensing information +for their users. Compliance with one of the licenses noted under +the "FLOSS license list" section remains a prerequisite. + +Package Name Qualifying License and Version +Apache Portable Runtime (APR) Apache Software License 2.0 From 48c3d361e4f4e3514e8239e1352c5dbc95b90d0d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 Feb 2007 22:30:50 +0100 Subject: [PATCH 28/55] Makefile.am: EXCEPTIONS-CLIENT is now static part of repository Docs/Makefile.am: EXCEPTIONS-CLIENT is now static part of repository --- Docs/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Makefile.am b/Docs/Makefile.am index b329b574f6a..6a1ee131d1a 100644 --- a/Docs/Makefile.am +++ b/Docs/Makefile.am @@ -20,7 +20,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) mysql.info INSTALL-BINARY all: txt_files -txt_files: ../INSTALL-SOURCE ../EXCEPTIONS-CLIENT \ +txt_files: ../INSTALL-SOURCE \ INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt # make sure that "make install" installs the info page, too From f9bfa7806ea6af3e849673a8b6a70aacc16b6a02 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Mar 2007 08:34:59 +0700 Subject: [PATCH 29/55] ndb - rel5.1.16 NdbRecAttr print of blob length assumed uint64 aligned buffer ndb - 5.1.16 uint64 align for ndb_restore (backport) ndb/src/ndbapi/NdbRecAttr.cpp: ndb - rel5.1.16 NdbRecAttr print of blob length assumed uint64 aligned buffer (backport) ndb/tools/restore/Restore.cpp: ndb - 5.1.16 uint64 align for ndb_restore (backport) --- ndb/src/ndbapi/NdbRecAttr.cpp | 38 +++++++++++++++++------------------ ndb/tools/restore/Restore.cpp | 7 ++++++- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/ndb/src/ndbapi/NdbRecAttr.cpp b/ndb/src/ndbapi/NdbRecAttr.cpp index e1b0ef3a350..18e17071777 100644 --- a/ndb/src/ndbapi/NdbRecAttr.cpp +++ b/ndb/src/ndbapi/NdbRecAttr.cpp @@ -346,27 +346,27 @@ NdbOut& operator<<(NdbOut& out, const NdbRecAttr &r) } break; case NdbDictionary::Column::Blob: - { - const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef(); - out << h->length << ":"; - const unsigned char* p = (const unsigned char*)(h + 1); - unsigned n = r.arraySize() - sizeof(*h); - for (unsigned k = 0; k < n && k < h->length; k++) - out.print("%02X", (int)p[k]); - j = length; - } - break; case NdbDictionary::Column::Text: - { - const NdbBlob::Head* h = (const NdbBlob::Head*)r.aRef(); - out << h->length << ":"; - const unsigned char* p = (const unsigned char*)(h + 1); - unsigned n = r.arraySize() - sizeof(*h); - for (unsigned k = 0; k < n && k < h->length; k++) - out.print("%c", (int)p[k]); - j = length; + { + // user defined aRef() may not be aligned to Uint64 + NdbBlob::Head head; + memcpy(&head, r.aRef(), sizeof(head)); + out << head.length << ":"; + const unsigned char* p = (const unsigned char*)r.aRef() + sizeof(head); + if (r.arraySize() < sizeof(head)) + out << "***error***"; // really cannot happen + else { + unsigned n = r.arraySize() - sizeof(head); + for (unsigned k = 0; k < n && k < head.length; k++) { + if (r.getType() == NdbDictionary::Column::Blob) + out.print("%02X", (int)p[k]); + else + out.print("%c", (int)p[k]); + } } - break; + j = length; + } + break; case NdbDictionary::Column::Longvarchar: { unsigned len = uint2korr(r.aRef()); diff --git a/ndb/tools/restore/Restore.cpp b/ndb/tools/restore/Restore.cpp index 9aa79f4dc94..8b2e9a799a4 100644 --- a/ndb/tools/restore/Restore.cpp +++ b/ndb/tools/restore/Restore.cpp @@ -54,7 +54,12 @@ BackupFile::Twiddle(const AttributeDesc* attr_desc, AttributeData* attr_data, Ui return true; case 64: for(i = 0; iu_int64_value[i] = Twiddle64(attr_data->u_int64_value[i]); + // allow unaligned + char* p = (char*)&attr_data->u_int64_value[i]; + Uint64 x; + memcpy(&x, p, sizeof(Uint64)); + x = Twiddle64(x); + memcpy(p, &x, sizeof(Uint64)); } return true; default: From 09d82a1a9588bf0655ad0e43e76a2e1c28f336ca Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Mar 2007 15:10:14 -0700 Subject: [PATCH 30/55] Manual merge of 5.0 into 5.0-runtime mysql-test/r/subselect.result: Manual merge mysql-test/t/subselect.test: Manual merge --- mysql-test/r/subselect.result | 60 +++++++++++++++++++++++++++++------ mysql-test/t/subselect.test | 28 ++++++++++++++++ 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 8ba52e81f35..7ff4b9bcf16 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -224,7 +224,7 @@ id select_type table type possible_keys key key_len ref rows Extra 2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 3 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 3 Using where Warnings: -Note 1276 Field or reference 't4.a' of SELECT #3 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t4.a' of SELECT #3 was resolved in SELECT #1 Note 1003 select `test`.`t4`.`b` AS `b`,(select avg((`test`.`t2`.`a` + (select min(`test`.`t3`.`a`) AS `min(t3.a)` from `test`.`t3` where (`test`.`t3`.`a` >= `test`.`t4`.`a`)))) AS `avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a))` from `test`.`t2`) AS `(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)` from `test`.`t4` select * from t3 where exists (select * from t2 where t2.b=t3.a); a @@ -313,8 +313,8 @@ id select_type table type possible_keys key key_len ref rows Extra 3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where NULL UNION RESULT ALL NULL NULL NULL NULL NULL Warnings: -Note 1276 Field or reference 't2.a' of SELECT #2 was resolved in SELECT #1 -Note 1276 Field or reference 't2.a' of SELECT #3 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t2.a' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t2.a' of SELECT #3 was resolved in SELECT #1 Note 1003 select (select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = `test`.`t2`.`a`) union select `test`.`t5`.`a` AS `a` from `test`.`t5` where (`test`.`t5`.`a` = `test`.`t2`.`a`)) AS `(select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a)`,`test`.`t2`.`a` AS `a` from `test`.`t2` select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2; ERROR 21000: Subquery returns more than 1 row @@ -330,9 +330,9 @@ patient_uq clinic_uq explain extended select * from t6 where exists (select * from t7 where uq = clinic_uq); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t6 ALL NULL NULL NULL NULL 4 Using where -2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 Using index +2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 t6.clinic_uq 1 Using where; Using index Warnings: -Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t6.clinic_uq' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where exists(select 1 AS `Not_used` from `test`.`t7` where (`test`.`t7`.`uq` = `test`.`t6`.`clinic_uq`)) select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); ERROR 23000: Column 'a' in field list is ambiguous @@ -868,7 +868,7 @@ explain extended select (select a+1) from t1; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ALL NULL NULL NULL NULL 3 Warnings: -Note 1276 Field or reference 'a' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.t1.a' of SELECT #2 was resolved in SELECT #1 Note 1249 Select 2 was reduced during optimization Note 1003 select (`test`.`t1`.`a` + 1) AS `(select a+1)` from `test`.`t1` select (select a+1) from t1; @@ -1741,9 +1741,9 @@ Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `tes explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where -2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 Using where; Using index +2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 tt.id 1 Using where; Using index Warnings: -Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.tt.id' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where (not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and (`test`.`t1`.`id` = `test`.`tt`.`id`)) having (`test`.`t1`.`id` is not null)))) insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001'); create table t2 (id int not null, text varchar(20) not null default '', primary key (id)); @@ -2279,7 +2279,7 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY up ALL NULL NULL NULL NULL 2 Using where 2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where Warnings: -Note 1276 Field or reference 'up.a' of SELECT #2 was resolved in SELECT #1 +Note 1276 Field or reference 'test.up.a' of SELECT #2 was resolved in SELECT #1 Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where exists(select 1 AS `Not_used` from `test`.`t1` where (`test`.`t1`.`a` = `test`.`up`.`a`)) drop table t1; CREATE TABLE t1 (t1_a int); @@ -3712,6 +3712,48 @@ bb 2 cc 3 dd 1 DROP TABLE t1,t2,t3; +CREATE TABLE t1(f1 int); +CREATE TABLE t2(f2 int, f21 int, f3 timestamp); +INSERT INTO t1 VALUES (1),(1),(2),(2); +INSERT INTO t2 VALUES (1,1,"2004-02-29 11:11:11"), (2,2,"2004-02-29 11:11:11"); +SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1; +sq +2 +4 +SELECT (SELECT SUM(1) FROM t2 ttt GROUP BY t2.f3 LIMIT 1) AS tt FROM t2; +tt +2 +2 +PREPARE stmt1 FROM 'SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1'; +EXECUTE stmt1; +sq +2 +4 +EXECUTE stmt1; +sq +2 +4 +DEALLOCATE PREPARE stmt1; +SELECT f2, AVG(f21), +(SELECT t.f3 FROM t2 AS t WHERE t2.f2=t.f2 AND t.f3=MAX(t2.f3)) AS test +FROM t2 GROUP BY f2; +f2 AVG(f21) test +1 1.0000 2004-02-29 11:11:11 +2 2.0000 2004-02-29 11:11:11 +DROP TABLE t1,t2; +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL); +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'); +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 +DROP TABLE t1; DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; DROP TABLE IF EXISTS t1xt2; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 927adfec231..1deda2a4382 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -2602,6 +2602,34 @@ SELECT * FROM t1 DROP TABLE t1,t2,t3; +# +# Bug#23800: Outer fields in correlated subqueries is used in a temporary +# table created for sorting. +# +CREATE TABLE t1(f1 int); +CREATE TABLE t2(f2 int, f21 int, f3 timestamp); +INSERT INTO t1 VALUES (1),(1),(2),(2); +INSERT INTO t2 VALUES (1,1,"2004-02-29 11:11:11"), (2,2,"2004-02-29 11:11:11"); +SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1; +SELECT (SELECT SUM(1) FROM t2 ttt GROUP BY t2.f3 LIMIT 1) AS tt FROM t2; +PREPARE stmt1 FROM 'SELECT ((SELECT f2 FROM t2 WHERE f21=f1 LIMIT 1) * COUNT(f1)) AS sq FROM t1 GROUP BY f1'; +EXECUTE stmt1; +EXECUTE stmt1; +DEALLOCATE PREPARE stmt1; +SELECT f2, AVG(f21), + (SELECT t.f3 FROM t2 AS t WHERE t2.f2=t.f2 AND t.f3=MAX(t2.f3)) AS test + FROM t2 GROUP BY f2; +DROP TABLE t1,t2; +CREATE TABLE t1 (a int, b INT, c CHAR(10) NOT NULL); +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'); +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; +DROP TABLE t1; + # # Bug#21904 (parser problem when using IN with a double "(())") # From fe3711254c8e355b98144d751b8ebd87dbf4c8a8 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Mar 2007 23:48:22 +0100 Subject: [PATCH 31/55] mysql.sln: Disabled build of all embedded server libraries, "libmysqld.ldd" "mysqldemb.lib" and "mysqlserver.lib" VC++Files/mysql.sln: Disabled build of all embedded server libraries, "libmysqld.ldd" "mysqldemb.lib" and "mysqlserver.lib" --- VC++Files/mysql.sln | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln index 0d4f22862a3..f31343b65e3 100644 --- a/VC++Files/mysql.sln +++ b/VC++Files/mysql.sln @@ -903,32 +903,26 @@ Global {62E85884-3ACF-4F4C-873B-60B878147890}.Release.ActiveCfg = Release|Win32 {62E85884-3ACF-4F4C-873B-60B878147890}.Release.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic.ActiveCfg = classic|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic.Build.0 = classic|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic nt.ActiveCfg = classic|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic nt.Build.0 = classic|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Debug.ActiveCfg = Debug|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Debug.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Classic.ActiveCfg = Release|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Classic.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Debug.ActiveCfg = Debug|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Debug.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Pro.ActiveCfg = Release|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Pro.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_ProGPL.ActiveCfg = Release|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_ProGPL.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Release.ActiveCfg = Release|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Release.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max nt.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max nt.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.nt.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.nt.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro.ActiveCfg = pro|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro.Build.0 = pro|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro gpl.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro gpl.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro gpl nt.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro gpl nt.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro nt.ActiveCfg = pro|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.pro nt.Build.0 = pro|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Release.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Release.Build.0 = Release|Win32 {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic.ActiveCfg = classic|Win32 {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic.Build.0 = classic|Win32 {89F24ECE-9953-40EF-BDF4-B41F5631E92B}.classic nt.ActiveCfg = classic|Win32 @@ -1011,32 +1005,26 @@ Global {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Release.ActiveCfg = Release|Win32 {AD95DAD3-6DB9-4F8B-A345-7A39A83AAD3A}.Release.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.classic.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.classic.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.classic nt.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.classic nt.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Debug.ActiveCfg = Debug|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.Debug.Build.0 = Debug|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Classic.ActiveCfg = Release|Win32 + {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Classic.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Debug.ActiveCfg = Debug|Win32 + {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Debug.Build.0 = Debug|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Pro.ActiveCfg = Release|Win32 + {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Pro.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_ProGPL.ActiveCfg = Release|Win32 + {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_ProGPL.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Release.ActiveCfg = Release|Win32 + {94B86159-C581-42CD-825D-C69CBC237E5C}.Embedded_Release.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Max.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.Max.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Max nt.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.Max nt.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.nt.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.nt.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.pro.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.pro.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.pro gpl.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.pro gpl.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.pro gpl nt.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.pro gpl nt.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.pro nt.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.pro nt.Build.0 = Release|Win32 {94B86159-C581-42CD-825D-C69CBC237E5C}.Release.ActiveCfg = Release|Win32 - {94B86159-C581-42CD-825D-C69CBC237E5C}.Release.Build.0 = Release|Win32 {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic.ActiveCfg = classic|Win32 {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic.Build.0 = classic|Win32 {3737BFE2-EF25-464F-994D-BD28A9F84528}.classic nt.ActiveCfg = classic|Win32 @@ -1303,10 +1291,15 @@ Global {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.classic nt.ActiveCfg = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Debug.ActiveCfg = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Classic.ActiveCfg = Release|Win32 + {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Classic.Build.0 = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Debug.ActiveCfg = Release|Win32 + {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Debug.Build.0 = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Pro.ActiveCfg = Release|Win32 + {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Pro.Build.0 = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_ProGPL.ActiveCfg = Release|Win32 + {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_ProGPL.Build.0 = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Release.ActiveCfg = Release|Win32 + {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Embedded_Release.Build.0 = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max.ActiveCfg = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.Max nt.ActiveCfg = Release|Win32 {6F01B69C-B1A5-4C45-B3A9-744E1EB0BED5}.nt.ActiveCfg = Release|Win32 From 10f632a1cbca216584e45f6228c176cf5b021716 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 00:54:02 +0100 Subject: [PATCH 32/55] mysql.sln: Correction of embedded build types VC++Files/mysql.sln: Correction of embedded build types --- VC++Files/mysql.sln | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/VC++Files/mysql.sln b/VC++Files/mysql.sln index f31343b65e3..bee2f16c751 100644 --- a/VC++Files/mysql.sln +++ b/VC++Files/mysql.sln @@ -906,15 +906,15 @@ Global {37D9BA79-302E-4582-A545-CB5FF7982EA3}.classic nt.ActiveCfg = classic|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Debug.ActiveCfg = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Classic.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Classic.Build.0 = Debug|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Classic.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Debug.ActiveCfg = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Debug.Build.0 = Debug|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Pro.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Pro.Build.0 = Debug|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Pro.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_ProGPL.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_ProGPL.Build.0 = Debug|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_ProGPL.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Release.ActiveCfg = Release|Win32 - {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Release.Build.0 = Debug|Win32 + {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Embedded_Release.Build.0 = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max.ActiveCfg = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.Max nt.ActiveCfg = Release|Win32 {37D9BA79-302E-4582-A545-CB5FF7982EA3}.nt.ActiveCfg = Release|Win32 From 1301de42c1ce4504c94d75d485d4b8aef5df57a4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 08:56:22 +0700 Subject: [PATCH 33/55] Bug #26720 Infinite loop on unknown signal in logging function - terminate printing --- ndb/src/common/debugger/signaldata/PackedSignal.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ndb/src/common/debugger/signaldata/PackedSignal.cpp b/ndb/src/common/debugger/signaldata/PackedSignal.cpp index 54048bcbb35..a5f585c23f0 100644 --- a/ndb/src/common/debugger/signaldata/PackedSignal.cpp +++ b/ndb/src/common/debugger/signaldata/PackedSignal.cpp @@ -96,6 +96,8 @@ printPACKED_SIGNAL(FILE * output, const Uint32 * theData, Uint32 len, Uint16 rec } default: fprintf(output, "Unknown signal type\n"); + i = len; // terminate printing + break; } }//for fprintf(output, "--------- End Packed Signals ----------\n"); From 87c5e84f93ddba816c723ff0d085f83ca4e53d88 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 09:06:05 +0700 Subject: [PATCH 34/55] Bug #25275 SINGLE USER MODE prevents ALTER on non-ndb tables for other mysqld nodes (part 1) - add signal data - add ref in dict on create/drop table/index --- ndb/include/kernel/signaldata/AlterTable.hpp | 3 +- ndb/include/kernel/signaldata/CreateIndx.hpp | 3 +- ndb/include/kernel/signaldata/CreateTable.hpp | 3 +- ndb/include/kernel/signaldata/DropIndx.hpp | 3 +- ndb/include/kernel/signaldata/DropTable.hpp | 3 +- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 41 +++++++++++++++++++ ndb/src/ndbapi/ndberror.c | 1 + 7 files changed, 52 insertions(+), 5 deletions(-) diff --git a/ndb/include/kernel/signaldata/AlterTable.hpp b/ndb/include/kernel/signaldata/AlterTable.hpp index 6042b7233f6..c2fd742c234 100644 --- a/ndb/include/kernel/signaldata/AlterTable.hpp +++ b/ndb/include/kernel/signaldata/AlterTable.hpp @@ -130,7 +130,8 @@ public: NullablePrimaryKey = 740, UnsupportedChange = 741, BackupInProgress = 762, - IncompatibleVersions = 763 + IncompatibleVersions = 763, + SingleUser = 299 }; private: diff --git a/ndb/include/kernel/signaldata/CreateIndx.hpp b/ndb/include/kernel/signaldata/CreateIndx.hpp index 8a2054a1a42..f6168959d1a 100644 --- a/ndb/include/kernel/signaldata/CreateIndx.hpp +++ b/ndb/include/kernel/signaldata/CreateIndx.hpp @@ -206,7 +206,8 @@ public: NotUnique = 4251, AllocationError = 4252, CreateIndexTableFailed = 4253, - DuplicateAttributes = 4258 + DuplicateAttributes = 4258, + SingleUser = 299 }; CreateIndxConf m_conf; diff --git a/ndb/include/kernel/signaldata/CreateTable.hpp b/ndb/include/kernel/signaldata/CreateTable.hpp index d29a06c751e..3f33da1e9b4 100644 --- a/ndb/include/kernel/signaldata/CreateTable.hpp +++ b/ndb/include/kernel/signaldata/CreateTable.hpp @@ -91,7 +91,8 @@ public: RecordTooBig = 738, InvalidPrimaryKeySize = 739, NullablePrimaryKey = 740, - InvalidCharset = 743 + InvalidCharset = 743, + SingleUser = 299 }; private: diff --git a/ndb/include/kernel/signaldata/DropIndx.hpp b/ndb/include/kernel/signaldata/DropIndx.hpp index 01d500f2d84..6e3b183995f 100644 --- a/ndb/include/kernel/signaldata/DropIndx.hpp +++ b/ndb/include/kernel/signaldata/DropIndx.hpp @@ -172,7 +172,8 @@ public: IndexNotFound = 4243, BadRequestType = 4247, InvalidName = 4248, - NotAnIndex = 4254 + NotAnIndex = 4254, + SingleUser = 299 }; STATIC_CONST( SignalLength = DropIndxConf::SignalLength + 3 ); diff --git a/ndb/include/kernel/signaldata/DropTable.hpp b/ndb/include/kernel/signaldata/DropTable.hpp index 36268b23be1..c0a4596e1dc 100644 --- a/ndb/include/kernel/signaldata/DropTable.hpp +++ b/ndb/include/kernel/signaldata/DropTable.hpp @@ -58,7 +58,8 @@ public: InvalidTableVersion = 241, DropInProgress = 283, NoDropTableRecordAvailable = 1229, - BackupInProgress = 761 + BackupInProgress = 761, + SingleUser = 299 }; }; diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 7b82631884f..16964ec443f 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -2910,6 +2910,15 @@ Dbdict::execCREATE_TABLE_REQ(Signal* signal){ break; } + if(getNodeState().getSingleUserMode() && + (refToNode(signal->getSendersBlockRef()) != + getNodeState().getSingleUserApi())) + { + jam(); + parseRecord.errorCode = CreateTableRef::SingleUser; + break; + } + CreateTableRecordPtr createTabPtr; c_opCreateTable.seize(createTabPtr); @@ -3072,6 +3081,15 @@ Dbdict::execALTER_TABLE_REQ(Signal* signal) return; } + if(getNodeState().getSingleUserMode() && + (refToNode(signal->getSendersBlockRef()) != + getNodeState().getSingleUserApi())) + { + jam(); + alterTableRef(signal, req, AlterTableRef::SingleUser); + return; + } + const TableRecord::TabState tabState = tablePtr.p->tabState; bool ok = false; switch(tabState){ @@ -5401,6 +5419,15 @@ Dbdict::execDROP_TABLE_REQ(Signal* signal){ return; } + if(getNodeState().getSingleUserMode() && + (refToNode(signal->getSendersBlockRef()) != + getNodeState().getSingleUserApi())) + { + jam(); + dropTableRef(signal, req, DropTableRef::SingleUser); + return; + } + const TableRecord::TabState tabState = tablePtr.p->tabState; bool ok = false; switch(tabState){ @@ -6531,6 +6558,13 @@ Dbdict::execCREATE_INDX_REQ(Signal* signal) jam(); tmperr = CreateIndxRef::Busy; } + else if(getNodeState().getSingleUserMode() && + (refToNode(senderRef) != + getNodeState().getSingleUserApi())) + { + jam(); + tmperr = CreateIndxRef::SingleUser; + } if (tmperr != CreateIndxRef::NoError) { releaseSections(signal); OpCreateIndex opBusy; @@ -7101,6 +7135,13 @@ Dbdict::execDROP_INDX_REQ(Signal* signal) jam(); tmperr = DropIndxRef::Busy; } + else if(getNodeState().getSingleUserMode() && + (refToNode(senderRef) != + getNodeState().getSingleUserApi())) + { + jam(); + tmperr = DropIndxRef::SingleUser; + } if (tmperr != DropIndxRef::NoError) { err = tmperr; goto error; diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c index 45248000703..15445620ce9 100644 --- a/ndb/src/ndbapi/ndberror.c +++ b/ndb/src/ndbapi/ndberror.c @@ -264,6 +264,7 @@ ErrorBundle ErrorCodes[] = { /** * Application error */ + { 299, AE, "Operation not allowed or aborted due to single user mode" }, { 763, AE, "Alter table requires cluster nodes to have exact same version" }, { 823, AE, "Too much attrinfo from application in tuple manager" }, { 831, AE, "Too many nullable/bitfields in table definition" }, From 0a93be2869be5eb801d7955ad512504190dd0479 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Mar 2007 19:20:47 -0700 Subject: [PATCH 35/55] Bug#26093 (SELECT BENCHMARK() for SELECT statements does not produce valid results) Before this fix, the function BENCHMARK() would fail to evaluate expressions like "(select avg(a) from t1)" in debug builds (with an assert), or would report a time of zero in non debug builds. The root cause is that evaluation of DECIMAL_RESULT expressions was not supported in Item_func_benchmark::val_int(). This has been fixed by this change. mysql-test/r/func_misc.result: Added support for DECIMAL_RESULT in Item_func_benchmark::val_int() mysql-test/t/func_misc.test: Added support for DECIMAL_RESULT in Item_func_benchmark::val_int() sql/item_func.cc: Added support for DECIMAL_RESULT in Item_func_benchmark::val_int() --- mysql-test/r/func_misc.result | 44 +++++++++++++++++++++++++++ mysql-test/t/func_misc.test | 57 +++++++++++++++++++++++++++++++++++ sql/item_func.cc | 4 +++ 3 files changed, 105 insertions(+) diff --git a/mysql-test/r/func_misc.result b/mysql-test/r/func_misc.result index 5c6162b7c28..35101e26ff6 100644 --- a/mysql-test/r/func_misc.result +++ b/mysql-test/r/func_misc.result @@ -141,4 +141,48 @@ t1 CREATE TABLE `t1` ( `a` bigint(21) unsigned default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +drop table if exists table_26093; +drop function if exists func_26093_a; +drop function if exists func_26093_b; +create table table_26093(a int); +insert into table_26093 values +(1), (2), (3), (4), (5), +(6), (7), (8), (9), (10); +create function func_26093_a(x int) returns int +begin +set @invoked := @invoked + 1; +return x; +end// +create function func_26093_b(x int, y int) returns int +begin +set @invoked := @invoked + 1; +return x; +end// +select avg(a) from table_26093; +avg(a) +5.5000 +select benchmark(100, (select avg(a) from table_26093)); +benchmark(100, (select avg(a) from table_26093)) +0 +set @invoked := 0; +select benchmark(100, (select avg(func_26093_a(a)) from table_26093)); +benchmark(100, (select avg(func_26093_a(a)) from table_26093)) +0 +select @invoked; +@invoked +10 +set @invoked := 0; +select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)); +benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)) +0 +select @invoked; +@invoked +1000 +select benchmark(100, (select (a) from table_26093)); +ERROR 21000: Subquery returns more than 1 row +select benchmark(100, (select 1, 1)); +ERROR 21000: Operand should contain 1 column(s) +drop table table_26093; +drop function func_26093_a; +drop function func_26093_b; End of 5.0 tests diff --git a/mysql-test/t/func_misc.test b/mysql-test/t/func_misc.test index 5cac6c45f65..8ff62f68e45 100644 --- a/mysql-test/t/func_misc.test +++ b/mysql-test/t/func_misc.test @@ -132,4 +132,61 @@ set global query_cache_size=default; create table t1 select INET_ATON('255.255.0.1') as `a`; show create table t1; drop table t1; + +# +# Bug#26093 (SELECT BENCHMARK() for SELECT statements does not produce +# valid results) +# + +--disable_warnings +drop table if exists table_26093; +drop function if exists func_26093_a; +drop function if exists func_26093_b; +--enable_warnings + +create table table_26093(a int); +insert into table_26093 values +(1), (2), (3), (4), (5), +(6), (7), (8), (9), (10); + +delimiter //; + +create function func_26093_a(x int) returns int +begin + set @invoked := @invoked + 1; + return x; +end// + +create function func_26093_b(x int, y int) returns int +begin + set @invoked := @invoked + 1; + return x; +end// + +delimiter ;// + +select avg(a) from table_26093; + +select benchmark(100, (select avg(a) from table_26093)); + +set @invoked := 0; +select benchmark(100, (select avg(func_26093_a(a)) from table_26093)); +# Returns only 10, since intermediate results are cached. +select @invoked; + +set @invoked := 0; +select benchmark(100, (select avg(func_26093_b(a, rand())) from table_26093)); +# Returns 1000, due to rand() preventing caching. +select @invoked; + +--error ER_SUBQUERY_NO_1_ROW +select benchmark(100, (select (a) from table_26093)); + +--error ER_OPERAND_COLUMNS +select benchmark(100, (select 1, 1)); + +drop table table_26093; +drop function func_26093_a; +drop function func_26093_b; + --echo End of 5.0 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 1ef77208469..1538d0ed390 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -3456,6 +3456,7 @@ longlong Item_func_benchmark::val_int() DBUG_ASSERT(fixed == 1); char buff[MAX_FIELD_WIDTH]; String tmp(buff,sizeof(buff), &my_charset_bin); + my_decimal tmp_decimal; THD *thd=current_thd; for (ulong loop=0 ; loop < loop_count && !thd->killed; loop++) @@ -3470,6 +3471,9 @@ longlong Item_func_benchmark::val_int() case STRING_RESULT: (void) args[0]->val_str(&tmp); break; + case DECIMAL_RESULT: + (void) args[0]->val_decimal(&tmp_decimal); + break; case ROW_RESULT: default: // This case should never be chosen From d4272a16deb9aa1b2428e446b2321697aebf9d94 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 15:09:44 +0400 Subject: [PATCH 36/55] after merge fix (bug #26038) Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. mysql-test/include/gis_generic.inc: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. mysql-test/r/archive_gis.result: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. mysql-test/r/gis.result: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. mysql-test/r/innodb_gis.result: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. mysql-test/r/ndb_gis.result: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. mysql-test/t/gis.test: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. sql/item_geofunc.cc: after merge fix Item_func_geometry_from_text::val_str() should set null_value in case of wrong data. --- mysql-test/include/gis_generic.inc | 4 +-- mysql-test/r/archive_gis.result | 4 +-- mysql-test/r/gis.result | 50 +++++++++++++++++++++++++++--- mysql-test/r/innodb_gis.result | 4 +-- mysql-test/r/ndb_gis.result | 8 ++--- mysql-test/t/gis.test | 4 +-- sql/item_geofunc.cc | 7 ++--- 7 files changed, 60 insertions(+), 21 deletions(-) diff --git a/mysql-test/include/gis_generic.inc b/mysql-test/include/gis_generic.inc index e5e7283e0e6..dc5d95baad9 100644 --- a/mysql-test/include/gis_generic.inc +++ b/mysql-test/include/gis_generic.inc @@ -165,14 +165,14 @@ insert IGNORE into t1 values ('Garbage'); drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); --error 1416 insert into t1 values (1); --error 1416 insert into t1 values (1.11); --error 1416 insert into t1 values ("qwerty"); ---error 1416 +--error 1048 insert into t1 values (pointfromtext('point(1,1)')); drop table t1; diff --git a/mysql-test/r/archive_gis.result b/mysql-test/r/archive_gis.result index 25a77bc9c75..7fb69e54a4c 100644 --- a/mysql-test/r/archive_gis.result +++ b/mysql-test/r/archive_gis.result @@ -446,7 +446,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert IGNORE into t1 values ('Garbage'); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); insert into t1 values (1); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (1.11); @@ -454,5 +454,5 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values ("qwerty"); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); -ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ERROR 23000: Column 'fl' cannot be null drop table t1; diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result index df39a4d8ca2..de034d93dc5 100644 --- a/mysql-test/r/gis.result +++ b/mysql-test/r/gis.result @@ -578,7 +578,7 @@ create table t1 select GeomFromWKB(POINT(1,3)); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( - `GeomFromWKB(POINT(1,3))` geometry NOT NULL default '' + `GeomFromWKB(POINT(1,3))` geometry default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo` @@ -657,7 +657,7 @@ t1 where object_id=85984; object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo)) 85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469) drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); insert into t1 values (1); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (1.11); @@ -665,7 +665,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values ("qwerty"); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); -ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ERROR 23000: Column 'fl' cannot be null drop table t1; select (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))); (asWKT(geomfromwkb((0x000000000140240000000000004024000000000000)))) @@ -689,6 +689,48 @@ load data infile '../std_data_ln/bad_gis_data.dat' into table t1; ERROR 22004: Column was set to data type implicit default; NULL supplied for NOT NULL column 'b' at row 1 alter table t1 enable keys; drop table t1; +create table t1 (a int, b blob); +insert into t1 values (1, ''), (2, NULL), (3, '1'); +select * from t1; +a b +1 +2 NULL +3 1 +select +geometryfromtext(b) IS NULL, geometryfromwkb(b) IS NULL, astext(b) IS NULL, +aswkb(b) IS NULL, geometrytype(b) IS NULL, centroid(b) IS NULL, +envelope(b) IS NULL, startpoint(b) IS NULL, endpoint(b) IS NULL, +exteriorring(b) IS NULL, pointn(b, 1) IS NULL, geometryn(b, 1) IS NULL, +interiorringn(b, 1) IS NULL, multipoint(b) IS NULL, isempty(b) IS NULL, +issimple(b) IS NULL, isclosed(b) IS NULL, dimension(b) IS NULL, +numgeometries(b) IS NULL, numinteriorrings(b) IS NULL, numpoints(b) IS NULL, +area(b) IS NULL, glength(b) IS NULL, srid(b) IS NULL, x(b) IS NULL, +y(b) IS NULL +from t1; +geometryfromtext(b) IS NULL geometryfromwkb(b) IS NULL astext(b) IS NULL aswkb(b) IS NULL geometrytype(b) IS NULL centroid(b) IS NULL envelope(b) IS NULL startpoint(b) IS NULL endpoint(b) IS NULL exteriorring(b) IS NULL pointn(b, 1) IS NULL geometryn(b, 1) IS NULL interiorringn(b, 1) IS NULL multipoint(b) IS NULL isempty(b) IS NULL issimple(b) IS NULL isclosed(b) IS NULL dimension(b) IS NULL numgeometries(b) IS NULL numinteriorrings(b) IS NULL numpoints(b) IS NULL area(b) IS NULL glength(b) IS NULL srid(b) IS NULL x(b) IS NULL y(b) IS NULL +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +select +within(b, b) IS NULL, contains(b, b) IS NULL, overlaps(b, b) IS NULL, +equals(b, b) IS NULL, disjoint(b, b) IS NULL, touches(b, b) IS NULL, +intersects(b, b) IS NULL, crosses(b, b) IS NULL +from t1; +within(b, b) IS NULL contains(b, b) IS NULL overlaps(b, b) IS NULL equals(b, b) IS NULL disjoint(b, b) IS NULL touches(b, b) IS NULL intersects(b, b) IS NULL crosses(b, b) IS NULL +1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 +select +point(b, b) IS NULL, linestring(b) IS NULL, polygon(b) IS NULL, multipoint(b) IS NULL, +multilinestring(b) IS NULL, multipolygon(b) IS NULL, +geometrycollection(b) IS NULL +from t1; +point(b, b) IS NULL linestring(b) IS NULL polygon(b) IS NULL multipoint(b) IS NULL multilinestring(b) IS NULL multipolygon(b) IS NULL geometrycollection(b) IS NULL +0 1 1 1 1 1 1 +1 1 1 1 1 1 1 +0 1 1 1 1 1 1 +drop table t1; +End of 4.1 tests create table t1 (s1 geometry not null,s2 char(100)); create trigger t1_bu before update on t1 for each row set new.s1 = null; insert into t1 values (null,null); @@ -715,7 +757,7 @@ drop table t1; create table t1 select GeomFromText('point(1 1)'); desc t1; Field Type Null Key Default Extra -GeomFromText('point(1 1)') geometry NO +GeomFromText('point(1 1)') geometry YES NULL drop table t1; create table t1 (g geometry not null); insert into t1 values(default); diff --git a/mysql-test/r/innodb_gis.result b/mysql-test/r/innodb_gis.result index 826a17cb60d..41a227a2850 100644 --- a/mysql-test/r/innodb_gis.result +++ b/mysql-test/r/innodb_gis.result @@ -446,7 +446,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert IGNORE into t1 values ('Garbage'); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); insert into t1 values (1); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (1.11); @@ -454,5 +454,5 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values ("qwerty"); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); -ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ERROR 23000: Column 'fl' cannot be null drop table t1; diff --git a/mysql-test/r/ndb_gis.result b/mysql-test/r/ndb_gis.result index 43075306bd2..bdbbc65dd85 100644 --- a/mysql-test/r/ndb_gis.result +++ b/mysql-test/r/ndb_gis.result @@ -446,7 +446,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert IGNORE into t1 values ('Garbage'); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); insert into t1 values (1); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (1.11); @@ -454,7 +454,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values ("qwerty"); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); -ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ERROR 23000: Column 'fl' cannot be null drop table t1; set engine_condition_pushdown = on; DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon, gis_multi_point, gis_multi_line, gis_multi_polygon, gis_geometrycollection, gis_geometry; @@ -904,7 +904,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert IGNORE into t1 values ('Garbage'); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); insert into t1 values (1); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (1.11); @@ -912,5 +912,5 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values ("qwerty"); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); -ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ERROR 23000: Column 'fl' cannot be null drop table t1; diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test index e90d988133b..b32764f1f62 100644 --- a/mysql-test/t/gis.test +++ b/mysql-test/t/gis.test @@ -360,14 +360,14 @@ t1 where object_id=85984; drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); --error 1416 insert into t1 values (1); --error 1416 insert into t1 values (1.11); --error 1416 insert into t1 values ("qwerty"); ---error 1416 +--error 1048 insert into t1 values (pointfromtext('point(1,1)')); drop table t1; diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index 955ba0ef67a..11cb8ad935b 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -64,11 +64,8 @@ String *Item_func_geometry_from_text::val_str(String *str) return 0; str->length(0); str->q_append(srid); - if (!Geometry::create_from_wkt(&buffer, &trs, str, 0)) - /* We shouldn't return NULL here as NULL is a legal spatial object */ - /* Geometry::bad_spatial_data will produce error message beeing stored*/ - /* in GEOMETRY field */ - return &Geometry::bad_geometry_data; + if ((null_value= !Geometry::create_from_wkt(&buffer, &trs, str, 0))) + return 0; return str; } From b0e07932c65f70ff2571fa4045f464b4e3defcdc Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 14:29:51 +0300 Subject: [PATCH 37/55] Rename a macro to better reflect the action taken. sql/sql_yacc.yy: Rename: YYERROR_UNLESS -> YYABORT_UNLESS yyerror doesn't have to abort of the parser, whereas this macro does explicitly call YYABORT. --- sql/sql_yacc.yy | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a9921581f0c..f043d48b186 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -52,7 +52,7 @@ const LEX_STRING null_lex_str={0,0}; ER_WARN_DEPRECATED_SYNTAX, \ ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); -#define YYERROR_UNLESS(A) \ +#define YYABORT_UNLESS(A) \ if (!(A)) \ { \ yyerror(ER(ER_SYNTAX_ERROR)); \ @@ -5485,7 +5485,7 @@ table_ref: ; join_table_list: - derived_table_list { YYERROR_UNLESS($$=$1); } + derived_table_list { YYABORT_UNLESS($$=$1); } ; /* Warning - may return NULL in case of incomplete SELECT */ @@ -5493,7 +5493,7 @@ derived_table_list: table_ref { $$=$1; } | derived_table_list ',' table_ref { - YYERROR_UNLESS($1 && ($$=$3)); + YYABORT_UNLESS($1 && ($$=$3)); } ; @@ -5512,13 +5512,13 @@ join_table: left-associative joins. */ table_ref %prec TABLE_REF_PRIORITY normal_join table_ref - { YYERROR_UNLESS($1 && ($$=$3)); } + { YYABORT_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor - { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; } + { YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref ON { - YYERROR_UNLESS($1 && $3); + YYABORT_UNLESS($1 && $3); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; @@ -5533,7 +5533,7 @@ join_table: | table_ref STRAIGHT_JOIN table_factor ON { - YYERROR_UNLESS($1 && $3); + YYABORT_UNLESS($1 && $3); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) YYABORT; @@ -5549,13 +5549,13 @@ join_table: | table_ref normal_join table_ref USING { - YYERROR_UNLESS($1 && $3); + YYABORT_UNLESS($1 && $3); } '(' using_list ')' { add_join_natural($1,$3,$7,Select); $$=$3; } | table_ref NATURAL JOIN_SYM table_factor { - YYERROR_UNLESS($1 && ($$=$4)); + YYABORT_UNLESS($1 && ($$=$4)); add_join_natural($1,$4,NULL,Select); } @@ -5563,7 +5563,7 @@ join_table: | table_ref LEFT opt_outer JOIN_SYM table_ref ON { - YYERROR_UNLESS($1 && $5); + YYABORT_UNLESS($1 && $5); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; @@ -5579,7 +5579,7 @@ join_table: } | table_ref LEFT opt_outer JOIN_SYM table_factor { - YYERROR_UNLESS($1 && $5); + YYABORT_UNLESS($1 && $5); } USING '(' using_list ')' { @@ -5589,7 +5589,7 @@ join_table: } | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { - YYERROR_UNLESS($1 && $6); + YYABORT_UNLESS($1 && $6); add_join_natural($1,$6,NULL,Select); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; @@ -5599,7 +5599,7 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_ref ON { - YYERROR_UNLESS($1 && $5); + YYABORT_UNLESS($1 && $5); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) YYABORT; @@ -5616,7 +5616,7 @@ join_table: } | table_ref RIGHT opt_outer JOIN_SYM table_factor { - YYERROR_UNLESS($1 && $5); + YYABORT_UNLESS($1 && $5); } USING '(' using_list ')' { @@ -5627,7 +5627,7 @@ join_table: } | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { - YYERROR_UNLESS($1 && $6); + YYABORT_UNLESS($1 && $6); add_join_natural($6,$1,NULL,Select); LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) @@ -5670,7 +5670,7 @@ table_factor: expr '}' { LEX *lex= Lex; - YYERROR_UNLESS($3 && $7); + YYABORT_UNLESS($3 && $7); add_join_on($7,$10); Lex->pop_context(); $7->outer_join|=JOIN_TYPE_LEFT; @@ -9722,21 +9722,21 @@ xa: XA_SYM begin_or_start xid opt_join_or_resume xid: text_string { - YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE); + YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE); if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID)))) YYABORT; Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0); } | text_string ',' text_string { - YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); + YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID)))) YYABORT; Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length()); } | text_string ',' text_string ',' ulong_num { - YYERROR_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); + YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID)))) YYABORT; Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length()); From f7f5f0064999d955f94e7f7b8710e92344fcff13 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 15:05:16 +0300 Subject: [PATCH 38/55] Freeze the number of conflicts. We should not introduce any more conflicts without proper analysis and documentation of the nature of the conflict. --- sql/sql_yacc.yy | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index f043d48b186..6b15ccfd729 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -389,6 +389,11 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %} %pure_parser /* We have threads */ +/* + Currently there is 251 shift/reduce conflict. We should not introduce + new conflicts any more. +*/ +%expect 251 %token END_OF_INPUT From d26369327e146cf67614a7e28e5081a29d54df12 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 14:03:28 +0100 Subject: [PATCH 39/55] Add missing man pages to the RPMs. support-files/mysql.spec.sh: Add missing man pages. --- support-files/mysql.spec.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 2958e857049..f2d38718747 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -441,14 +441,19 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/isamchk.1* %doc %attr(644, root, man) %{_mandir}/man1/isamlog.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqlman.1* %doc %attr(644, root, man) %{_mandir}/man1/myisamchk.1* +%doc %attr(644, root, man) %{_mandir}/man1/myisam_ftdump.1* %doc %attr(644, root, man) %{_mandir}/man1/myisamlog.1* %doc %attr(644, root, man) %{_mandir}/man1/myisampack.1* +%doc %attr(644, root, man) %{_mandir}/man1/my_print_defaults.1* %doc %attr(644, root, man) %{_mandir}/man8/mysqld.8* %doc %attr(644, root, man) %{_mandir}/man1/mysqld_multi.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqld_safe.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_explain_log.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_fix_privilege_tables.1* %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql_install_db.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* %doc %attr(644, root, man) %{_mandir}/man1/pack_isam.1* @@ -578,6 +583,10 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Mar 02 2007 Joerg Bruehe + +- Add several man pages which are now created. + * Tue Jun 27 2006 Joerg Bruehe - move "mysqldumpslow" from the client RPM to the server RPM (bug#20216) From 622533fa81fcea289433ea6cae3245ceecdc3b9e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 14:05:43 +0100 Subject: [PATCH 40/55] Add the man pages for NDB to the RPMs. support-files/mysql.spec.sh: Add the man pages for NDB. --- support-files/mysql.spec.sh | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index a9f8d574de9..e0fe8d60aa6 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -651,23 +651,33 @@ fi %files ndb-tools %defattr(-,root,root,0755) +%attr(755, root, root) %{_bindir}/ndb_config +%attr(755, root, root) %{_bindir}/ndb_desc %attr(755, root, root) %{_bindir}/ndb_mgm %attr(755, root, root) %{_bindir}/ndb_restore -%attr(755, root, root) %{_bindir}/ndb_waiter %attr(755, root, root) %{_bindir}/ndb_select_all %attr(755, root, root) %{_bindir}/ndb_select_count -%attr(755, root, root) %{_bindir}/ndb_desc %attr(755, root, root) %{_bindir}/ndb_show_tables -%attr(755, root, root) %{_bindir}/ndb_test_platform -%attr(755, root, root) %{_bindir}/ndb_config %attr(755, root, root) %{_bindir}/ndb_size.pl +%attr(755, root, root) %{_bindir}/ndb_test_platform +%attr(755, root, root) %{_bindir}/ndb_waiter %attr(-, root, root) %{_datadir}/mysql/ndb_size.tmpl +%doc %attr(644, root, man) %{_mandir}/man1/ndb_config.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_desc.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_select_all.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_select_count.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_show_tables.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_size.pl.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_waiter.1* %files ndb-extra %defattr(-,root,root,0755) +%attr(755, root, root) %{_bindir}/ndb_delete_all %attr(755, root, root) %{_bindir}/ndb_drop_index %attr(755, root, root) %{_bindir}/ndb_drop_table -%attr(755, root, root) %{_bindir}/ndb_delete_all +%doc %attr(644, root, man) %{_mandir}/man1/ndb_delete_all.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_drop_index.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_drop_table.1* %files devel %defattr(-, root, root, 0755) @@ -727,6 +737,10 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Mar 02 2007 Joerg Bruehe + +- Add several man pages for NDB which are now created. + * Fri Jan 05 2007 Kent Boortz - Add CFLAGS to gcc call with --print-libgcc-file, to make sure the From 9e290476f85cca717ec64188b6bba4d10d6f1975 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 14:08:32 +0100 Subject: [PATCH 41/55] Add the man pages for NDB to the RPMs. support-files/mysql.spec.sh: Add the man pages for NDB. --- support-files/mysql.spec.sh | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index 6f0285227e4..cef01a8406f 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -693,24 +693,35 @@ fi %files ndb-tools %defattr(-,root,root,0755) +%attr(755, root, root) %{_bindir}/ndb_config +%attr(755, root, root) %{_bindir}/ndb_desc +%attr(755, root, root) %{_bindir}/ndb_error_reporter %attr(755, root, root) %{_bindir}/ndb_mgm %attr(755, root, root) %{_bindir}/ndb_restore -%attr(755, root, root) %{_bindir}/ndb_waiter %attr(755, root, root) %{_bindir}/ndb_select_all %attr(755, root, root) %{_bindir}/ndb_select_count -%attr(755, root, root) %{_bindir}/ndb_desc %attr(755, root, root) %{_bindir}/ndb_show_tables -%attr(755, root, root) %{_bindir}/ndb_test_platform -%attr(755, root, root) %{_bindir}/ndb_config -%attr(755, root, root) %{_bindir}/ndb_error_reporter %attr(755, root, root) %{_bindir}/ndb_size.pl +%attr(755, root, root) %{_bindir}/ndb_test_platform +%attr(755, root, root) %{_bindir}/ndb_waiter %attr(-, root, root) %{_datadir}/mysql/ndb_size.tmpl +%doc %attr(644, root, man) %{_mandir}/man1/ndb_config.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_desc.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_error_reporter.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_select_all.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_select_count.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_show_tables.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_size.pl.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_waiter.1* %files ndb-extra %defattr(-,root,root,0755) +%attr(755, root, root) %{_bindir}/ndb_delete_all %attr(755, root, root) %{_bindir}/ndb_drop_index %attr(755, root, root) %{_bindir}/ndb_drop_table -%attr(755, root, root) %{_bindir}/ndb_delete_all +%doc %attr(644, root, man) %{_mandir}/man1/ndb_delete_all.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_drop_index.1* +%doc %attr(644, root, man) %{_mandir}/man1/ndb_drop_table.1* %files devel %defattr(-, root, root, 0755) @@ -770,6 +781,10 @@ fi # itself - note that they must be ordered by date (important when # merging BK trees) %changelog +* Fri Mar 02 2007 Joerg Bruehe + +- Add several man pages for NDB which are now created. + * Wed Jan 31 2007 Daniel Fischer - add MTR_BUILD_THREAD=auto to test runs. From fed9bb9820fe89a47f355a9027166ccaf58bf336 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 15:23:13 +0100 Subject: [PATCH 42/55] Bug #21103: DATE column not compared as DATE If we compare two items A and B, with B being (a constant) of a larger type, then A gets promoted to B's type for comparison if it's a constant, function, or CAST() column, but B gets demoted to A's type if A is a (not explicitly CAST()) column. This is counter-intuitive and not mandated by the standard. Disabling optimisation where it would be lossy so field value will properly get promoted and compared as binary string (rather than as integers). mysql-test/include/ps_conv.inc: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix certain queries to still work. mysql-test/r/func_time.result: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Show that everything works as expected. mysql-test/r/ps_2myisam.result: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix certain queries to still work. mysql-test/r/ps_3innodb.result: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix certain queries to still work. mysql-test/r/ps_4heap.result: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix certain queries to still work. mysql-test/r/ps_5merge.result: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix certain queries to still work. mysql-test/r/ps_7ndb.result: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix certain queries to still work. mysql-test/t/func_time.test: Bug #21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Show that everything works as expected. sql/field.cc: Bug #21103: DATE column not compared as DATE #0 stores the date only as a 3-byte integer; save_in_field() in #1 saves 'this' in field's format (DATE), #2 "converts a constant item to an int and replaces the original item" -- consequently, this replaces the Item_string "2006-11-06 04:08:36.0" with the Item_int_with_ref 20061106. #0 Field_newdate::store (this=0x8d26880, from=0x8d5e658 "2006-11-06 04:08:36.0", len=21, cs=0x88022c0) at field.cc:5344 #1 0x0817e3b0 in Item_string::save_in_field (this=0x8d5e670, field=0x8d26880, no_conversions=true) at item.cc:4340 #2 0x081b22ae in convert_constant_item (thd=0x8d25240, field=0x8d26880, item=0x8d5e74c) at item_cmpfunc.cc:245 #3 0x081b8a36 in Item_bool_func2::fix_length_and_dec (this=0x8d5e6f8) at item_cmpfunc.cc:309 #4 0x081a3427 in Item_func::fix_fields (this=0x8d5e6f8, thd=0x8d25240, ref=0x8d5f5fc) at item_func.cc:190 #5 0x0825bc2d in setup_conds (thd=0x8d25240, tables=0x8d5e410, leaves=0x8d5e410, conds=0x8d5f5fc) at sql_base.cc:4941 ... Disabling optimisation where it would be lossy so field value will properly get promoted and compared as binary string (rather than as integers). --- mysql-test/include/ps_conv.inc | 12 ++++++------ mysql-test/r/func_time.result | 17 +++++++++++++++++ mysql-test/r/ps_2myisam.result | 12 ++++++------ mysql-test/r/ps_3innodb.result | 12 ++++++------ mysql-test/r/ps_4heap.result | 12 ++++++------ mysql-test/r/ps_5merge.result | 24 ++++++++++++------------ mysql-test/r/ps_7ndb.result | 12 ++++++------ mysql-test/t/func_time.test | 13 +++++++++++++ sql/field.cc | 23 +++++++++++++---------- 9 files changed, 85 insertions(+), 52 deletions(-) diff --git a/mysql-test/include/ps_conv.inc b/mysql-test/include/ps_conv.inc index 0dd819f6e62..09290d760ce 100644 --- a/mysql-test/include/ps_conv.inc +++ b/mysql-test/include/ps_conv.inc @@ -1152,19 +1152,19 @@ select '-- select .. where date/time column = .. --' as test_sequence ; ######## SELECT .. WHERE column(date/time/..)=value(CHAR(n)/LONGTEXT) ######## set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; @@ -1177,7 +1177,7 @@ where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and c16= CAST('1991-01-01 01:01:01' as datetime) and c17= CAST('1991-01-01 01:01:01' as datetime) ; select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; prepare stmt1 from "select 'true' as found from t9 where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and @@ -1187,7 +1187,7 @@ where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and c17= CAST('1991-01-01 01:01:01' as datetime)" ; execute stmt1 ; prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 32f930ca6ba..a5af2217684 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -1207,6 +1207,23 @@ SET NAMES DEFAULT; select str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE NULL +create table t1 (field DATE); +insert into t1 values ('2006-11-06'); +select * from t1 where field < '2006-11-06 04:08:36.0'; +field +2006-11-06 +select * from t1 where field = '2006-11-06 04:08:36.0'; +field +select * from t1 where field = '2006-11-06'; +field +2006-11-06 +select * from t1 where CAST(field as DATETIME) < '2006-11-06 04:08:36.0'; +field +2006-11-06 +select * from t1 where CAST(field as DATE) < '2006-11-06 04:08:36.0'; +field +2006-11-06 +drop table t1; CREATE TABLE t1 (a int, t1 time, t2 time, d date, PRIMARY KEY (a)); INSERT INTO t1 VALUES (1, '10:00:00', NULL, NULL), (2, '11:00:00', '11:15:00', '1972-02-06'); diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index 2a7b0e959af..de6e2d62763 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -3046,25 +3046,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -3078,7 +3078,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -3092,7 +3092,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 88e8bf3ce04..1ebaafdd488 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -3029,25 +3029,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -3061,7 +3061,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -3075,7 +3075,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 0e4c6fc3077..74b9326dbc1 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -3030,25 +3030,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -3062,7 +3062,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -3076,7 +3076,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 1e337072ecb..bf80514906b 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -2966,25 +2966,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -2998,7 +2998,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -3012,7 +3012,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -5980,25 +5980,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -6012,7 +6012,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -6026,7 +6026,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index c84cced15f5..e8358098ee7 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -3029,25 +3029,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -3061,7 +3061,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -3075,7 +3075,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 1aa4b434a83..ab904b187a3 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -714,6 +714,19 @@ SET NAMES DEFAULT; select str_to_date('10:00 PM', '%h:%i %p') + INTERVAL 10 MINUTE; +# +# Bug #21103: DATE column not compared as DATE +# + +create table t1 (field DATE); +insert into t1 values ('2006-11-06'); +select * from t1 where field < '2006-11-06 04:08:36.0'; +select * from t1 where field = '2006-11-06 04:08:36.0'; +select * from t1 where field = '2006-11-06'; +select * from t1 where CAST(field as DATETIME) < '2006-11-06 04:08:36.0'; +select * from t1 where CAST(field as DATE) < '2006-11-06 04:08:36.0'; +drop table t1; + # # Bug #25643: SEC_TO_TIME function problem # diff --git a/sql/field.cc b/sql/field.cc index 74a5e742c06..54e5c362f0d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5338,27 +5338,30 @@ void Field_date::sql_type(String &res) const int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs) { TIME l_time; - long tmp; int error; THD *thd= table ? table->in_use : current_thd; - if (str_to_datetime(from, len, &l_time, - (TIME_FUZZY_DATE | - (thd->variables.sql_mode & - (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | - MODE_INVALID_DATES))), - &error) <= MYSQL_TIMESTAMP_ERROR) + enum enum_mysql_timestamp_type ret; + if ((ret= str_to_datetime(from, len, &l_time, + (TIME_FUZZY_DATE | + (thd->variables.sql_mode & + (MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | + MODE_INVALID_DATES))), + &error)) <= MYSQL_TIMESTAMP_ERROR) { - tmp= 0L; + int3store(ptr,0L); error= 2; } else - tmp= l_time.day + l_time.month*32 + l_time.year*16*32; + { + int3store(ptr, l_time.day + l_time.month*32 + l_time.year*16*32); + if(!error && (ret != MYSQL_TIMESTAMP_DATE)) + return 2; + } if (error) set_datetime_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, from, len, MYSQL_TIMESTAMP_DATE, 1); - int3store(ptr,tmp); return error; } From b73f17fb77dd9e698a23e5a2c16f286695956749 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 16:30:22 +0100 Subject: [PATCH 43/55] Another man page in the RPMs. support-files/mysql.spec.sh: Another man page. --- support-files/mysql.spec.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index f2d38718747..c005ecbf13a 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -455,6 +455,7 @@ fi %doc %attr(644, root, man) %{_mandir}/man1/mysqlhotcopy.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_install_db.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql.server.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysqltest.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql_zap.1* %doc %attr(644, root, man) %{_mandir}/man1/pack_isam.1* %doc %attr(644, root, man) %{_mandir}/man1/perror.1* From 56eae45c8fa9199a77fd881e8b772e5f95a998f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Mar 2007 16:32:27 +0100 Subject: [PATCH 44/55] More man pages for the RPMs. support-files/mysql.spec.sh: More man pages. --- support-files/mysql.spec.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index e0fe8d60aa6..fef0ed4780b 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -723,6 +723,8 @@ fi %attr(755, root, root) %{_bindir}/mysqlmanager %attr(755, root, root) %{_bindir}/mysqlmanagerc %attr(755, root, root) %{_bindir}/mysqlmanager-pwgen +%doc %attr(644, root, man) %{_mandir}/man1/mysql_client_test.1* +%doc %attr(644, root, man) %{_mandir}/man1/mysql-test-run.pl.1* %files Max %defattr(-, root, root, 0755) From 85c3f6df4516dd8799169db64fe6d4a2748d80c0 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 Mar 2007 14:02:29 +0100 Subject: [PATCH 45/55] Bug#21103: DATE column not compared as DATE When comparing a DATE field with a DATETIME constant, we now compare as DATETIMEs, not as DATEs. Fix BDB queries to still work. --- mysql-test/r/ps_6bdb.result | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 49e3f9d9bb7..e83a3944d4e 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -3029,25 +3029,25 @@ test_sequence -- select .. where date/time column = .. -- set @arg00= '1991-01-01 01:01:01' ; select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01' ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and +where c1= 20 and c13= CAST('1991-01-01 01:01:01' AS DATE) and c14= '1991-01-01 01:01:01' and c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and c17= '1991-01-01 01:01:01'" ; execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true @@ -3061,7 +3061,7 @@ c17= CAST('1991-01-01 01:01:01' as datetime) ; found true select 'true' as found from t9 -where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00 +where c1= 20 and c13= CAST(@arg00 AS DATE) and c14= @arg00 and c15= @arg00 and c16= @arg00 and c17= @arg00 ; found true @@ -3075,7 +3075,7 @@ execute stmt1 ; found true prepare stmt1 from "select 'true' as found from t9 -where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ; +where c1= 20 and c13= CAST(? AS DATE) and c14= ? and c15= ? and c16= ? and c17= ?" ; execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ; found true From 266a7fff520eb2253226158df236865f2ad16ffe Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 5 Mar 2007 19:42:07 -0700 Subject: [PATCH 46/55] Bug#8407 (Stored functions/triggers ignore exception handler) Bug 18914 (Calling certain SPs from triggers fail) Bug 20713 (Functions will not not continue for SQLSTATE VALUE '42S02') Bug 21825 (Incorrect message error deleting records in a table with a trigger for inserting) Bug 22580 (DROP TABLE in nested stored procedure causes strange dependency error) Bug 25345 (Cursors from Functions) This fix resolves a long standing issue originally reported with bug 8407, which affect the behavior of Stored Procedures, Stored Functions and Trigger in many different ways, causing symptoms reported by all the bugs listed. In all cases, the root cause of the problem traces back to 8407 and how the server locks tables involved with sub statements. Prior to this fix, the implementation of stored routines would: - compute the transitive closure of all the tables referenced by a top level statement - open and lock all the tables involved - execute the top level statement "transitive closure of tables" means collecting: - all the tables, - all the stored functions, - all the views, - all the table triggers - all the stored procedures involved, and recursively inspect these objects definition to find more references to more objects, until the list of every object referenced does not grow any more. This mechanism is known as "pre-locking" tables before execution. The motivation for locking all the tables (possibly) used at once is to prevent dead locks. One problem with this approach is that, if the execution path the code really takes during runtime does not use a given table, and if the table is missing, the server would not execute the statement. This in particular has a major impact on triggers, since a missing table referenced by an update/delete trigger would prevent an insert trigger to run. Another problem is that stored routines might define SQL exception handlers to deal with missing tables, but the server implementation would never give user code a chance to execute this logic, since the routine is never executed when a missing table cause the pre-locking code to fail. With this fix, the internal implementation of the pre-locking code has been relaxed of some constraints, so that failure to open a table does not necessarily prevent execution of a stored routine. In particular, the pre-locking mechanism is now behaving as follows: 1) the first step, to compute the transitive closure of all the tables possibly referenced by a statement, is unchanged. 2) the next step, which is to open all the tables involved, only attempts to open the tables added by the pre-locking code, but silently fails without reporting any error or invoking any exception handler is the table is not present. This is achieved by trapping internal errors with Prelock_error_handler 3) the locking step only locks tables that were successfully opened. 4) when executing sub statements, the list of tables used by each statements is evaluated as before. The tables needed by the sub statement are expected to be already opened and locked. Statement referencing tables that were not opened in step 2) will fail to find the table in the open list, and only at this point will execution of the user code fail. 5) when a runtime exception is raised at 4), the instruction continuation destination (the next instruction to execute in case of SQL continue handlers) is evaluated. This is achieved with sp_instr::exec_open_and_lock_tables() 6) if a user exception handler is present in the stored routine, that handler is invoked as usual, so that ER_NO_SUCH_TABLE exceptions can be trapped by stored routines. If no handler exists, then the runtime execution will fail as expected. With all these changes, a side effect is that view security is impacted, in two different ways. First, a view defined as "select stored_function()", where the stored function references a table that may not exist, is considered valid. The rationale is that, because the stored function might trap exceptions during execution and still return a valid result, there is no way to decide when the view is created if a missing table really cause the view to be invalid. Secondly, testing for existence of tables is now done later during execution. View security, which consist of trapping errors and return a generic ER_VIEW_INVALID (to prevent disclosing information) was only implemented at very specific phases covering *opening* tables, but not covering the runtime execution. Because of this existing limitation, errors that were previously trapped and converted into ER_VIEW_INVALID are not trapped, causing table names to be reported to the user. This change is exposing an existing problem, which is independent and will be resolved separately. mysql-test/r/information_schema_db.result: Revised the pre-locking code implementation, aligned the tests. mysql-test/r/sp-error.result: Revised the pre-locking code implementation, aligned the tests. mysql-test/r/sp.result: Revised the pre-locking code implementation, aligned the tests. mysql-test/r/trigger.result: Revised the pre-locking code implementation, aligned the tests. mysql-test/r/view.result: Revised the pre-locking code implementation, aligned the tests. mysql-test/t/sp-error.test: Revised the pre-locking code implementation, aligned the tests. mysql-test/t/sp.test: Revised the pre-locking code implementation, aligned the tests. mysql-test/t/trigger.test: Revised the pre-locking code implementation, aligned the tests. sql/lock.cc: table->placeholder now checks for schema_table sql/mysqld.cc: my_message_sql(): invoke internal exception handlers sql/sp_head.cc: exec_open_and_lock_tables(): open and lock tables, or return the continuation destination of this instruction sql/sp_head.h: exec_open_and_lock_tables(): open and lock tables, or return the continuation destination of this instruction sql/sql_base.cc: Prelock_error_handler: delay open table errors until execution sql/sql_class.cc: THD: add internal error handler, as an exception mechanism. sql/sql_class.h: THD: add internal error handler, as an exception mechanism. sql/sql_update.cc: table->placeholder now checks for schema_table sql/table.cc: st_table_list::hide_view_error(): masked more errors for view security sql/table.h: table->placeholder now checks for schema_table, and unopened tables --- mysql-test/r/information_schema_db.result | 6 +- mysql-test/r/sp-error.result | 143 +++++++++++++++- mysql-test/r/sp.result | 42 ++++- mysql-test/r/trigger.result | 37 +++++ mysql-test/r/view.result | 6 +- mysql-test/t/sp-error.test | 193 +++++++++++++++++++++- mysql-test/t/sp.test | 53 +++++- mysql-test/t/trigger.test | 74 +++++++++ sql/lock.cc | 2 +- sql/mysqld.cc | 8 + sql/sp_head.cc | 49 +++++- sql/sp_head.h | 24 +++ sql/sql_base.cc | 102 +++++++++++- sql/sql_class.cc | 32 ++++ sql/sql_class.h | 67 ++++++++ sql/sql_update.cc | 2 +- sql/table.cc | 4 +- sql/table.h | 2 +- 18 files changed, 801 insertions(+), 45 deletions(-) diff --git a/mysql-test/r/information_schema_db.result b/mysql-test/r/information_schema_db.result index 40773a7afc1..47efe1d17ad 100644 --- a/mysql-test/r/information_schema_db.result +++ b/mysql-test/r/information_schema_db.result @@ -87,13 +87,13 @@ where table_schema='test'; table_name table_type table_comment t1 BASE TABLE v1 VIEW VIEW -v2 VIEW View 'test.v2' references invalid table(s) or column(s) or function(s) or define +v2 VIEW VIEW drop table t1; select table_name, table_type, table_comment from information_schema.tables where table_schema='test'; table_name table_type table_comment -v1 VIEW View 'test.v1' references invalid table(s) or column(s) or function(s) or define -v2 VIEW View 'test.v2' references invalid table(s) or column(s) or function(s) or define +v1 VIEW VIEW +v2 VIEW VIEW drop function f1; drop function f2; drop view v1, v2; diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index e7e387f4348..332d4fa4519 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1128,9 +1128,9 @@ drop view if exists v1, v2, v3, v4; create function bug11555_1() returns int return (select max(i) from t1); create function bug11555_2() returns int return bug11555_1(); create view v1 as select bug11555_1(); -ERROR 42S02: Table 'test.t1' doesn't exist +drop view v1; create view v2 as select bug11555_2(); -ERROR 42S02: Table 'test.t1' doesn't exist +drop view v2; create table t1 (i int); create view v1 as select bug11555_1(); create view v2 as select bug11555_2(); @@ -1143,8 +1143,7 @@ ERROR HY000: View 'test.v2' references invalid table(s) or column(s) or function select * from v3; ERROR HY000: View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them create view v4 as select * from v1; -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them -drop view v1, v2, v3; +drop view v1, v2, v3, v4; drop function bug11555_1; drop function bug11555_2; create table t1 (i int); @@ -1153,12 +1152,12 @@ create trigger t1_ai after insert on t1 for each row insert into t2 values (new. create view v1 as select * from t1; drop table t2; insert into v1 values (1); -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +ERROR HY000: Table 't2' was not locked with LOCK TABLES drop trigger t1_ai; create function bug11555_1() returns int return (select max(i) from t2); create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1(); insert into v1 values (2); -ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +ERROR HY000: Table 't2' was not locked with LOCK TABLES drop function bug11555_1; drop table t1; drop view v1; @@ -1269,3 +1268,135 @@ call bug24491(); ERROR 42S22: Unknown column 'y.value' in 'field list' drop procedure bug24491; drop tables t1; +DROP FUNCTION IF EXISTS bug18914_f1; +DROP FUNCTION IF EXISTS bug18914_f2; +DROP PROCEDURE IF EXISTS bug18914_p1; +DROP PROCEDURE IF EXISTS bug18914_p2; +DROP TABLE IF EXISTS t1, t2; +CREATE TABLE t1 (i INT); +CREATE PROCEDURE bug18914_p1() CREATE TABLE t2 (i INT); +CREATE PROCEDURE bug18914_p2() DROP TABLE IF EXISTS no_such_table; +CREATE FUNCTION bug18914_f1() RETURNS INT +BEGIN +CALL bug18914_p1(); +RETURN 1; +END | +CREATE FUNCTION bug18914_f2() RETURNS INT +BEGIN +CALL bug18914_p2(); +RETURN 1; +END | +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +CALL bug18914_p1(); +INSERT INTO t1 VALUES (1); +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +SELECT bug18914_f1(); +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +SELECT bug18914_f2(); +ERROR HY000: Explicit or implicit commit is not allowed in stored function or trigger. +SELECT * FROM t2; +ERROR 42S02: Table 'test.t2' doesn't exist +DROP FUNCTION bug18914_f1; +DROP FUNCTION bug18914_f2; +DROP PROCEDURE bug18914_p1; +DROP PROCEDURE bug18914_p2; +DROP TABLE t1; +drop table if exists bogus_table_20713; +drop function if exists func_20713_a; +drop function if exists func_20713_b; +create table bogus_table_20713( id int(10) not null primary key); +insert into bogus_table_20713 values (1), (2), (3); +create function func_20713_a() returns int(11) +begin +declare id int; +declare continue handler for sqlexception set id=null; +set @in_func := 1; +set id = (select id from bogus_table_20713 where id = 3); +set @in_func := 2; +return id; +end// +create function func_20713_b() returns int(11) +begin +declare id int; +declare continue handler for sqlstate value '42S02' set id=null; +set @in_func := 1; +set id = (select id from bogus_table_20713 where id = 3); +set @in_func := 2; +return id; +end// +set @in_func := 0; +select func_20713_a(); +func_20713_a() +NULL +select @in_func; +@in_func +2 +set @in_func := 0; +select func_20713_b(); +func_20713_b() +NULL +select @in_func; +@in_func +2 +drop table bogus_table_20713; +set @in_func := 0; +select func_20713_a(); +func_20713_a() +NULL +select @in_func; +@in_func +2 +set @in_func := 0; +select func_20713_b(); +func_20713_b() +NULL +select @in_func; +@in_func +2 +drop function if exists func_20713_a; +drop function if exists func_20713_b; +drop table if exists table_25345_a; +drop table if exists table_25345_b; +drop procedure if exists proc_25345; +drop function if exists func_25345; +drop function if exists func_25345_b; +create table table_25345_a (a int); +create table table_25345_b (b int); +create procedure proc_25345() +begin +declare c1 cursor for select a from table_25345_a; +declare c2 cursor for select b from table_25345_b; +select 1 as result; +end || +create function func_25345() returns int(11) +begin +call proc_25345(); +return 1; +end || +create function func_25345_b() returns int(11) +begin +declare c1 cursor for select a from table_25345_a; +declare c2 cursor for select b from table_25345_b; +return 1; +end || +call proc_25345(); +result +1 +select func_25345(); +ERROR 0A000: Not allowed to return a result set from a function +select func_25345_b(); +func_25345_b() +1 +drop table table_25345_a; +call proc_25345(); +result +1 +select func_25345(); +ERROR 0A000: Not allowed to return a result set from a function +select func_25345_b(); +func_25345_b() +1 +drop table table_25345_b; +drop procedure proc_25345; +drop function func_25345; +drop function func_25345_b; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 8e3c057cc62..2f9f4fbdad2 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1155,9 +1155,13 @@ create function f12_2() returns int return (select count(*) from t3)| drop temporary table t3| select f12_1()| -ERROR 42S02: Table 'test.t3' doesn't exist +f12_1() +3 +Warnings: +Note 1051 Unknown table 't3' select f12_1() from t1 limit 1| -ERROR 42S02: Table 'test.t3' doesn't exist +f12_1() +3 drop function f0| drop function f1| drop function f2| @@ -5741,4 +5745,38 @@ END| CALL bug24117()| DROP PROCEDURE bug24117| DROP TABLE t3| +drop function if exists func_8407_a| +drop function if exists func_8407_b| +create function func_8407_a() returns int +begin +declare x int; +declare continue handler for sqlexception +begin +end; +select 1 from no_such_view limit 1 into x; +return x; +end| +create function func_8407_b() returns int +begin +declare x int default 0; +declare continue handler for sqlstate '42S02' + begin +set x:= x+1000; +end; +case (select 1 from no_such_view limit 1) +when 1 then set x:= x+1; +when 2 then set x:= x+2; +else set x:= x+100; +end case; +set x:=x + 500; +return x; +end| +select func_8407_a()| +func_8407_a() +NULL +select func_8407_b()| +func_8407_b() +1500 +drop function func_8407_a| +drop function func_8407_b| drop table t1,t2; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 9f34f60eb1a..b6a80810f33 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1278,4 +1278,41 @@ a b 2 b 3 c drop table t1; +DROP TABLE IF EXISTS bug21825_A; +DROP TABLE IF EXISTS bug21825_B; +CREATE TABLE bug21825_A (id int(10)); +CREATE TABLE bug21825_B (id int(10)); +CREATE TRIGGER trgA AFTER INSERT ON bug21825_A +FOR EACH ROW +BEGIN +INSERT INTO bug21825_B (id) values (1); +END// +INSERT INTO bug21825_A (id) VALUES (10); +INSERT INTO bug21825_A (id) VALUES (20); +DROP TABLE bug21825_B; +DELETE FROM bug21825_A WHERE id = 20; +DROP TABLE bug21825_A; +DROP TABLE IF EXISTS bug22580_t1; +DROP PROCEDURE IF EXISTS bug22580_proc_1; +DROP PROCEDURE IF EXISTS bug22580_proc_2; +CREATE TABLE bug22580_t1 (a INT, b INT); +CREATE PROCEDURE bug22580_proc_2() +BEGIN +DROP TABLE IF EXISTS bug22580_tmp; +CREATE TEMPORARY TABLE bug22580_tmp (a INT); +DROP TABLE bug22580_tmp; +END|| +CREATE PROCEDURE bug22580_proc_1() +BEGIN +CALL bug22580_proc_2(); +END|| +CREATE TRIGGER t1bu BEFORE UPDATE ON bug22580_t1 +FOR EACH ROW +BEGIN +CALL bug22580_proc_1(); +END|| +INSERT INTO bug22580_t1 VALUES (1,1); +DROP TABLE bug22580_t1; +DROP PROCEDURE bug22580_proc_1; +DROP PROCEDURE bug22580_proc_2; End of 5.0 tests diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index f8584275a5a..fcb9c151016 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1933,11 +1933,11 @@ create function f1 () returns int return (select max(col1) from t1); DROP TABLE t1; CHECK TABLE v1, v2, v3, v4, v5, v6; Table Op Msg_type Msg_text -test.v1 check error View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +test.v1 check status OK test.v2 check status OK -test.v3 check error View 'test.v3' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +test.v3 check status OK test.v4 check status OK -test.v5 check error View 'test.v5' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +test.v5 check status OK test.v6 check status OK drop function f1; drop function f2; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index e77e3df8301..396c1552e37 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1607,10 +1607,12 @@ create function bug11555_1() returns int return (select max(i) from t1); create function bug11555_2() returns int return bug11555_1(); # It is OK to report name of implicitly used table which is missing # when we create view. ---error ER_NO_SUCH_TABLE +# For stored functions however, because of exceptions handlers, there is +# no easy way to find out if a missing table makes the view invalid. create view v1 as select bug11555_1(); ---error ER_NO_SUCH_TABLE +drop view v1; create view v2 as select bug11555_2(); +drop view v2; # But we should hide name of missing implicitly used table when we use view create table t1 (i int); create view v1 as select bug11555_1(); @@ -1625,9 +1627,8 @@ select * from v2; select * from v3; # Note that creation of view which depends on broken view is yet # another form of view usage. ---error ER_VIEW_INVALID create view v4 as select * from v1; -drop view v1, v2, v3; +drop view v1, v2, v3, v4; # We also should hide details about broken triggers which are # invoked for view. drop function bug11555_1; @@ -1637,12 +1638,14 @@ create table t2 (i int); create trigger t1_ai after insert on t1 for each row insert into t2 values (new.i); create view v1 as select * from t1; drop table t2; ---error ER_VIEW_INVALID +# Limitation, the desired error is ER_VIEW_INVALID +--error ER_TABLE_NOT_LOCKED insert into v1 values (1); drop trigger t1_ai; create function bug11555_1() returns int return (select max(i) from t2); create trigger t1_ai after insert on t1 for each row set @a:=bug11555_1(); ---error ER_VIEW_INVALID +# Limitation, the desired error is ER_VIEW_INVALID +--error ER_TABLE_NOT_LOCKED insert into v1 values (2); drop function bug11555_1; drop table t1; @@ -1839,6 +1842,184 @@ call bug24491(); drop procedure bug24491; drop tables t1; +# +# BUG#18914: Calling certain SPs from triggers fail +# +# Failing to call a procedure that does implicit commit from a trigger +# is a correct behaviour, however the error message was misleading. +# +# DROP TABLE IF EXISTS is also fixed to give correct error instead of +# "Table doesn't exist". +# +--disable_warnings +DROP FUNCTION IF EXISTS bug18914_f1; +DROP FUNCTION IF EXISTS bug18914_f2; +DROP PROCEDURE IF EXISTS bug18914_p1; +DROP PROCEDURE IF EXISTS bug18914_p2; +DROP TABLE IF EXISTS t1, t2; +--enable_warnings + +CREATE TABLE t1 (i INT); + +CREATE PROCEDURE bug18914_p1() CREATE TABLE t2 (i INT); +CREATE PROCEDURE bug18914_p2() DROP TABLE IF EXISTS no_such_table; + +delimiter |; +CREATE FUNCTION bug18914_f1() RETURNS INT +BEGIN + CALL bug18914_p1(); + RETURN 1; +END | + +CREATE FUNCTION bug18914_f2() RETURNS INT +BEGIN + CALL bug18914_p2(); + RETURN 1; +END | +delimiter ;| + +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + CALL bug18914_p1(); + +--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +INSERT INTO t1 VALUES (1); + +--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +SELECT bug18914_f1(); + +--error ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG +SELECT bug18914_f2(); + +--error ER_NO_SUCH_TABLE +SELECT * FROM t2; + +DROP FUNCTION bug18914_f1; +DROP FUNCTION bug18914_f2; +DROP PROCEDURE bug18914_p1; +DROP PROCEDURE bug18914_p2; +DROP TABLE t1; + +# +# Bug#20713 (Functions will not not continue for SQLSTATE VALUE '42S02') +# + +--disable_warnings +drop table if exists bogus_table_20713; +drop function if exists func_20713_a; +drop function if exists func_20713_b; +--enable_warnings + +create table bogus_table_20713( id int(10) not null primary key); +insert into bogus_table_20713 values (1), (2), (3); + +delimiter //; + +create function func_20713_a() returns int(11) +begin + declare id int; + + declare continue handler for sqlexception set id=null; + + set @in_func := 1; + set id = (select id from bogus_table_20713 where id = 3); + set @in_func := 2; + + return id; +end// + +create function func_20713_b() returns int(11) +begin + declare id int; + + declare continue handler for sqlstate value '42S02' set id=null; + + set @in_func := 1; + set id = (select id from bogus_table_20713 where id = 3); + set @in_func := 2; + + return id; +end// + +delimiter ;// + +set @in_func := 0; +select func_20713_a(); +select @in_func; + +set @in_func := 0; +select func_20713_b(); +select @in_func; + +drop table bogus_table_20713; + +set @in_func := 0; +select func_20713_a(); +select @in_func; + +set @in_func := 0; +select func_20713_b(); +select @in_func; + +drop function if exists func_20713_a; +drop function if exists func_20713_b; + +# +# Bug#25345 (Cursors from Functions) +# + +--disable_warnings +drop table if exists table_25345_a; +drop table if exists table_25345_b; +drop procedure if exists proc_25345; +drop function if exists func_25345; +drop function if exists func_25345_b; +--enable_warnings + +create table table_25345_a (a int); +create table table_25345_b (b int); + +delimiter ||; + +create procedure proc_25345() +begin + declare c1 cursor for select a from table_25345_a; + declare c2 cursor for select b from table_25345_b; + + select 1 as result; +end || + +create function func_25345() returns int(11) +begin + call proc_25345(); + return 1; +end || + +create function func_25345_b() returns int(11) +begin + declare c1 cursor for select a from table_25345_a; + declare c2 cursor for select b from table_25345_b; + + return 1; +end || + +delimiter ;|| + +call proc_25345(); +--error ER_SP_NO_RETSET +select func_25345(); +select func_25345_b(); + +drop table table_25345_a; + +call proc_25345(); +--error ER_SP_NO_RETSET +select func_25345(); +select func_25345_b(); + +drop table table_25345_b; +drop procedure proc_25345; +drop function func_25345; +drop function func_25345_b; # # BUG#NNNN: New bug synopsis diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index cfa4937e050..157d0b7c118 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1368,7 +1368,7 @@ end| select f11()| --error ER_CANT_REOPEN_TABLE select f11() from t1| -# We don't handle temporary tables used by nested functions well +# Test that using a single table instance at a time works create function f12_1() returns int begin drop temporary table if exists t3; @@ -1378,11 +1378,9 @@ begin end| create function f12_2() returns int return (select count(*) from t3)| -# We need clean start to get error + drop temporary table t3| ---error ER_NO_SUCH_TABLE select f12_1()| ---error ER_NO_SUCH_TABLE select f12_1() from t1 limit 1| # Cleanup @@ -6714,6 +6712,53 @@ CALL bug24117()| DROP PROCEDURE bug24117| DROP TABLE t3| +# +# Bug#8407(Stored functions/triggers ignore exception handler) +# + +--disable_warnings +drop function if exists func_8407_a| +drop function if exists func_8407_b| +--enable_warnings + +create function func_8407_a() returns int +begin + declare x int; + + declare continue handler for sqlexception + begin + end; + + select 1 from no_such_view limit 1 into x; + + return x; +end| + +create function func_8407_b() returns int +begin + declare x int default 0; + + declare continue handler for sqlstate '42S02' + begin + set x:= x+1000; + end; + + case (select 1 from no_such_view limit 1) + when 1 then set x:= x+1; + when 2 then set x:= x+2; + else set x:= x+100; + end case; + set x:=x + 500; + + return x; +end| + +select func_8407_a()| +select func_8407_b()| + +drop function func_8407_a| +drop function func_8407_b| + # # NOTE: The delimiter is `|`, and not `;`. It is changed to `;` # at the end of the file! diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 63cef614b77..c27b9248d29 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1554,4 +1554,78 @@ select * from t1; drop table t1; +# +# Bug#21285 (Incorrect message error deleting records in a table with a +# trigger for inserting) +# + +--disable_warnings +DROP TABLE IF EXISTS bug21825_A; +DROP TABLE IF EXISTS bug21825_B; +--enable_warnings + +CREATE TABLE bug21825_A (id int(10)); +CREATE TABLE bug21825_B (id int(10)); + +delimiter //; + +CREATE TRIGGER trgA AFTER INSERT ON bug21825_A +FOR EACH ROW +BEGIN + INSERT INTO bug21825_B (id) values (1); +END// +delimiter ;// + +INSERT INTO bug21825_A (id) VALUES (10); +INSERT INTO bug21825_A (id) VALUES (20); + +DROP TABLE bug21825_B; + +# Must pass, the missing table in the insert trigger should not matter. +DELETE FROM bug21825_A WHERE id = 20; + +DROP TABLE bug21825_A; + +# +# Bug#22580 (DROP TABLE in nested stored procedure causes strange dependancy +# error) +# + +--disable_warnings +DROP TABLE IF EXISTS bug22580_t1; +DROP PROCEDURE IF EXISTS bug22580_proc_1; +DROP PROCEDURE IF EXISTS bug22580_proc_2; +--enable_warnings + +CREATE TABLE bug22580_t1 (a INT, b INT); + +DELIMITER ||; + +CREATE PROCEDURE bug22580_proc_2() +BEGIN + DROP TABLE IF EXISTS bug22580_tmp; + CREATE TEMPORARY TABLE bug22580_tmp (a INT); + DROP TABLE bug22580_tmp; +END|| + +CREATE PROCEDURE bug22580_proc_1() +BEGIN + CALL bug22580_proc_2(); +END|| + +CREATE TRIGGER t1bu BEFORE UPDATE ON bug22580_t1 +FOR EACH ROW +BEGIN + CALL bug22580_proc_1(); +END|| + +DELIMITER ;|| + +# Must pass, the actions of the update trigger should not matter +INSERT INTO bug22580_t1 VALUES (1,1); + +DROP TABLE bug22580_t1; +DROP PROCEDURE bug22580_proc_1; +DROP PROCEDURE bug22580_proc_2; + --echo End of 5.0 tests diff --git a/sql/lock.cc b/sql/lock.cc index 2afe1de59f5..bf1512b754c 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -566,7 +566,7 @@ TABLE_LIST *mysql_lock_have_duplicate(THD *thd, TABLE_LIST *needle, for (; haystack; haystack= haystack->next_global) { - if (haystack->placeholder() || haystack->schema_table) + if (haystack->placeholder()) continue; table2= haystack->table; if (table2->s->tmp_table == TMP_TABLE) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 4ee8c2e7e31..b6054cd30f4 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2411,6 +2411,14 @@ static int my_message_sql(uint error, const char *str, myf MyFlags) */ if ((thd= current_thd)) { + /* + TODO: There are two exceptions mechanism (THD and sp_rcontext), + this could be improved by having a common stack of handlers. + */ + if (thd->handle_error(error, + MYSQL_ERROR::WARN_LEVEL_ERROR)) + DBUG_RETURN(0); + if (thd->spcont && thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd)) { diff --git a/sql/sp_head.cc b/sql/sp_head.cc index de0edabda3e..32f7d0b7f8c 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2374,16 +2374,11 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, m_lex->mark_as_requiring_prelocking(lex_query_tables_own_last); } } - + reinit_stmt_before_use(thd, m_lex); - /* - If requested check whenever we have access to tables in LEX's table list - and open and lock them before executing instructtions core function. - */ - if (open_tables && - (check_table_access(thd, SELECT_ACL, m_lex->query_tables, 0) || - open_and_lock_tables(thd, m_lex->query_tables))) - res= -1; + + if (open_tables) + res= instr->exec_open_and_lock_tables(thd, m_lex->query_tables, nextp); if (!res) res= instr->exec_core(thd, nextp); @@ -2432,6 +2427,33 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, sp_instr class functions */ +int sp_instr::exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables, + uint *nextp) +{ + int result; + + /* + Check whenever we have access to tables for this statement + and open and lock them before executing instructions core function. + */ + if (check_table_access(thd, SELECT_ACL, tables, 0) + || open_and_lock_tables(thd, tables)) + { + get_cont_dest(nextp); + result= -1; + } + else + result= 0; + + return result; +} + +void sp_instr::get_cont_dest(uint *nextp) +{ + *nextp= m_ip+1; +} + + int sp_instr::exec_core(THD *thd, uint *nextp) { DBUG_ASSERT(0); @@ -2612,6 +2634,15 @@ sp_instr_set_trigger_field::print(String *str) value->print(str); } +/* + sp_instr_opt_meta +*/ + +void sp_instr_opt_meta::get_cont_dest(uint *nextp) +{ + *nextp= m_cont_dest; +} + /* sp_instr_jump class functions diff --git a/sql/sp_head.h b/sql/sp_head.h index 0139f879ce4..837d737f228 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -458,6 +458,28 @@ public: virtual int execute(THD *thd, uint *nextp) = 0; + /** + Execute open_and_lock_tables() for this statement. + Open and lock the tables used by this statement, as a pre-requisite + to execute the core logic of this instruction with + exec_core(). + If this statement fails, the next instruction to execute is also returned. + This is useful when a user defined SQL continue handler needs to be + executed. + @param thd the current thread + @param tables the list of tables to open and lock + @param nextp the continuation instruction, returned to the caller if this + method fails. + @return zero on success, non zero on failure. + */ + int exec_open_and_lock_tables(THD *thd, TABLE_LIST *tables, uint *nextp); + + /** + Get the continuation destination of this instruction. + @param nextp the continuation destination (output) + */ + virtual void get_cont_dest(uint *nextp); + /* Execute core function of instruction after all preparations (e.g. setting of proper LEX, saving part of the thread context have been @@ -722,6 +744,8 @@ public: virtual void set_destination(uint old_dest, uint new_dest) = 0; + virtual void get_cont_dest(uint *nextp); + protected: sp_instr *m_optdest; // Used during optimization diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a4318f7b4bf..52f08331069 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -28,6 +28,59 @@ #include #endif +/** + This internal handler is used to trap internally + errors that can occur when executing open table + during the prelocking phase. +*/ +class Prelock_error_handler : public Internal_error_handler +{ +public: + Prelock_error_handler() + : m_handled_errors(0), m_unhandled_errors(0) + {} + + virtual ~Prelock_error_handler() {} + + virtual bool handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level, + THD *thd); + + bool safely_trapped_errors(); + +private: + int m_handled_errors; + int m_unhandled_errors; +}; + + +bool +Prelock_error_handler::handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level /* level */, + THD * /* thd */) +{ + if (sql_errno == ER_NO_SUCH_TABLE) + { + m_handled_errors++; + return TRUE; // 'TRUE', as per coding style + } + + m_unhandled_errors++; + return FALSE; // 'FALSE', as per coding style +} + + +bool Prelock_error_handler::safely_trapped_errors() +{ + /* + If m_unhandled_errors != 0, something else, unanticipated, happened, + so the error is not trapped but returned to the caller. + Multiple ER_NO_SUCH_TABLE can be raised in case of views. + */ + return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); +} + + TABLE *unused_tables; /* Used by mysql_test */ HASH open_cache; /* Used by mysql_test */ @@ -1334,7 +1387,10 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, VOID(pthread_mutex_unlock(&LOCK_open)); } } - my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); + if ((thd->locked_tables) && (thd->locked_tables->lock_count > 0)) + my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); + else + my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias); DBUG_RETURN(0); } @@ -2092,6 +2148,8 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) MEM_ROOT new_frm_mem; /* Also used for indicating that prelocking is need */ TABLE_LIST **query_tables_last_own; + bool safe_to_ignore_table; + DBUG_ENTER("open_tables"); /* temporary mem_root for new .frm parsing. @@ -2147,6 +2205,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) for (tables= *start; tables ;tables= tables->next_global) { + safe_to_ignore_table= FALSE; // 'FALSE', as per coding style /* Ignore placeholders for derived tables. After derived tables processing, link to created temporary table will be put here. @@ -2166,9 +2225,28 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) DBUG_RETURN(-1); } (*counter)++; - - if (!tables->table && - !(tables->table= open_table(thd, tables, &new_frm_mem, &refresh, flags))) + + if (!tables->table) + { + if (tables->prelocking_placeholder) + { + /* + For the tables added by the pre-locking code, attempt to open + the table but fail silently if the table does not exist. + The real failure will occur when/if a statement attempts to use + that table. + */ + Prelock_error_handler prelock_handler; + thd->push_internal_handler(& prelock_handler); + tables->table= open_table(thd, tables, &new_frm_mem, &refresh, flags); + thd->pop_internal_handler(); + safe_to_ignore_table= prelock_handler.safely_trapped_errors(); + } + else + tables->table= open_table(thd, tables, &new_frm_mem, &refresh, flags); + } + + if (!tables->table) { free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); @@ -2219,6 +2297,14 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) close_tables_for_reopen(thd, start); goto restart; } + + if (safe_to_ignore_table) + { + DBUG_PRINT("info", ("open_table: ignoring table '%s'.'%s'", + tables->db, tables->alias)); + continue; + } + result= -1; // Fatal error break; } @@ -2522,7 +2608,7 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags) static void mark_real_tables_as_free_for_reuse(TABLE_LIST *table) { for (; table; table= table->next_global) - if (!table->placeholder() && !table->schema_table) + if (!table->placeholder()) table->table->query_id= 0; } @@ -2594,7 +2680,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) DBUG_RETURN(-1); for (table= tables; table; table= table->next_global) { - if (!table->placeholder() && !table->schema_table) + if (!table->placeholder()) *(ptr++)= table->table; } @@ -2636,7 +2722,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) for (table= tables; table != first_not_own; table= table->next_global) { - if (!table->placeholder() && !table->schema_table) + if (!table->placeholder()) { table->table->query_id= thd->query_id; if (check_lock_and_start_stmt(thd, table->table, table->lock_type)) @@ -2663,7 +2749,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) TABLE_LIST *first_not_own= thd->lex->first_not_own_table(); for (table= tables; table != first_not_own; table= table->next_global) { - if (!table->placeholder() && !table->schema_table && + if (!table->placeholder() && check_lock_and_start_stmt(thd, table->table, table->lock_type)) { ha_rollback_stmt(thd); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 3b612dadcd0..a662ae290fd 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -273,6 +273,38 @@ THD::THD() substitute_null_with_insert_id = FALSE; thr_lock_info_init(&lock_info); /* safety: will be reset after start */ thr_lock_owner_init(&main_lock_id, &lock_info); + + m_internal_handler= NULL; +} + + +void THD::push_internal_handler(Internal_error_handler *handler) +{ + /* + TODO: The current implementation is limited to 1 handler at a time only. + THD and sp_rcontext need to be modified to use a common handler stack. + */ + DBUG_ASSERT(m_internal_handler == NULL); + m_internal_handler= handler; +} + + +bool THD::handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level) +{ + if (m_internal_handler) + { + return m_internal_handler->handle_error(sql_errno, level, this); + } + + return FALSE; // 'FALSE', as per coding style +} + + +void THD::pop_internal_handler() +{ + DBUG_ASSERT(m_internal_handler != NULL); + m_internal_handler= NULL; } diff --git a/sql/sql_class.h b/sql/sql_class.h index 05034ebd573..d03845ae663 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1071,6 +1071,48 @@ public: SAVEPOINT *savepoints; }; +/** + This class represents the interface for internal error handlers. + Internal error handlers are exception handlers used by the server + implementation. +*/ +class Internal_error_handler +{ +protected: + Internal_error_handler() {} + virtual ~Internal_error_handler() {} + +public: + /** + Handle an error condition. + This method can be implemented by a subclass to achieve any of the + following: + - mask an error internally, prevent exposing it to the user, + - mask an error and throw another one instead. + When this method returns true, the error condition is considered + 'handled', and will not be propagated to upper layers. + It is the responsability of the code installing an internal handler + to then check for trapped conditions, and implement logic to recover + from the anticipated conditions trapped during runtime. + + This mechanism is similar to C++ try/throw/catch: + - 'try' correspond to THD::push_internal_handler(), + - 'throw' correspond to my_error(), + which invokes my_message_sql(), + - 'catch' correspond to checking how/if an internal handler was invoked, + before removing it from the exception stack with + THD::pop_internal_handler(). + + @param sql_errno the error number + @param level the error level + @param thd the calling thread + @return true if the error is handled + */ + virtual bool handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level, + THD *thd) = 0; +}; + /* For each client connection we create a separate thread with THD serving as @@ -1659,6 +1701,31 @@ public: *p_db_length= db_length; return FALSE; } + +public: + /** + Add an internal error handler to the thread execution context. + @param handler the exception handler to add + */ + void push_internal_handler(Internal_error_handler *handler); + + /** + Handle an error condition. + @param sql_errno the error number + @param level the error level + @return true if the error is handled + */ + virtual bool handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level); + + /** + Remove the error handler last pushed. + */ + void pop_internal_handler(); + +private: + /** The current internal error handler for this thread, or NULL. */ + Internal_error_handler *m_internal_handler; }; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 4043fe17a46..3b295b63c2b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -783,7 +783,7 @@ reopen_tables: tl->lock_type= using_update_log ? TL_READ_NO_INSERT : TL_READ; tl->updating= 0; /* Update TABLE::lock_type accordingly. */ - if (!tl->placeholder() && !tl->schema_table && !using_lock_tables) + if (!tl->placeholder() && !using_lock_tables) tl->table->reginfo.lock_type= tl->lock_type; } } diff --git a/sql/table.cc b/sql/table.cc index 5c72ac6ccbf..623560fbe83 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -2091,7 +2091,9 @@ void st_table_list::hide_view_error(THD *thd) thd->net.last_errno == ER_SP_DOES_NOT_EXIST || thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR || thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR || - thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR) + thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR || + thd->net.last_errno == ER_TABLE_NOT_LOCKED || + thd->net.last_errno == ER_NO_SUCH_TABLE) { TABLE_LIST *top= top_table(); thd->clear_error(); diff --git a/sql/table.h b/sql/table.h index 70e64439af5..d1b0510cea3 100644 --- a/sql/table.h +++ b/sql/table.h @@ -643,7 +643,7 @@ typedef struct st_table_list int view_check_option(THD *thd, bool ignore_failure); bool setup_underlying(THD *thd); void cleanup_items(); - bool placeholder() {return derived || view; } + bool placeholder() {return derived || view || schema_table || !table; } void print(THD *thd, String *str); bool check_single_table(st_table_list **table, table_map map, st_table_list *view); From f7414b28971e89bb7a8df03835b5ab250c8e24ee Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Mar 2007 14:30:28 -0700 Subject: [PATCH 47/55] Manual merge --- mysql-test/r/trigger.result | 37 +++++++++++++++++++ mysql-test/t/trigger.test | 74 +++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index fe0e444f87d..aa511ca27a7 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1335,4 +1335,41 @@ SELECT fubar_id FROM t2; fubar_id 1 DROP TABLE t1,t2; +DROP TABLE IF EXISTS bug21825_A; +DROP TABLE IF EXISTS bug21825_B; +CREATE TABLE bug21825_A (id int(10)); +CREATE TABLE bug21825_B (id int(10)); +CREATE TRIGGER trgA AFTER INSERT ON bug21825_A +FOR EACH ROW +BEGIN +INSERT INTO bug21825_B (id) values (1); +END// +INSERT INTO bug21825_A (id) VALUES (10); +INSERT INTO bug21825_A (id) VALUES (20); +DROP TABLE bug21825_B; +DELETE FROM bug21825_A WHERE id = 20; +DROP TABLE bug21825_A; +DROP TABLE IF EXISTS bug22580_t1; +DROP PROCEDURE IF EXISTS bug22580_proc_1; +DROP PROCEDURE IF EXISTS bug22580_proc_2; +CREATE TABLE bug22580_t1 (a INT, b INT); +CREATE PROCEDURE bug22580_proc_2() +BEGIN +DROP TABLE IF EXISTS bug22580_tmp; +CREATE TEMPORARY TABLE bug22580_tmp (a INT); +DROP TABLE bug22580_tmp; +END|| +CREATE PROCEDURE bug22580_proc_1() +BEGIN +CALL bug22580_proc_2(); +END|| +CREATE TRIGGER t1bu BEFORE UPDATE ON bug22580_t1 +FOR EACH ROW +BEGIN +CALL bug22580_proc_1(); +END|| +INSERT INTO bug22580_t1 VALUES (1,1); +DROP TABLE bug22580_t1; +DROP PROCEDURE bug22580_proc_1; +DROP PROCEDURE bug22580_proc_2; End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 825f1fec6b9..5c95004c901 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -1625,4 +1625,78 @@ SELECT fubar_id FROM t2; DROP TABLE t1,t2; +# +# Bug#21285 (Incorrect message error deleting records in a table with a +# trigger for inserting) +# + +--disable_warnings +DROP TABLE IF EXISTS bug21825_A; +DROP TABLE IF EXISTS bug21825_B; +--enable_warnings + +CREATE TABLE bug21825_A (id int(10)); +CREATE TABLE bug21825_B (id int(10)); + +delimiter //; + +CREATE TRIGGER trgA AFTER INSERT ON bug21825_A +FOR EACH ROW +BEGIN + INSERT INTO bug21825_B (id) values (1); +END// +delimiter ;// + +INSERT INTO bug21825_A (id) VALUES (10); +INSERT INTO bug21825_A (id) VALUES (20); + +DROP TABLE bug21825_B; + +# Must pass, the missing table in the insert trigger should not matter. +DELETE FROM bug21825_A WHERE id = 20; + +DROP TABLE bug21825_A; + +# +# Bug#22580 (DROP TABLE in nested stored procedure causes strange dependancy +# error) +# + +--disable_warnings +DROP TABLE IF EXISTS bug22580_t1; +DROP PROCEDURE IF EXISTS bug22580_proc_1; +DROP PROCEDURE IF EXISTS bug22580_proc_2; +--enable_warnings + +CREATE TABLE bug22580_t1 (a INT, b INT); + +DELIMITER ||; + +CREATE PROCEDURE bug22580_proc_2() +BEGIN + DROP TABLE IF EXISTS bug22580_tmp; + CREATE TEMPORARY TABLE bug22580_tmp (a INT); + DROP TABLE bug22580_tmp; +END|| + +CREATE PROCEDURE bug22580_proc_1() +BEGIN + CALL bug22580_proc_2(); +END|| + +CREATE TRIGGER t1bu BEFORE UPDATE ON bug22580_t1 +FOR EACH ROW +BEGIN + CALL bug22580_proc_1(); +END|| + +DELIMITER ;|| + +# Must pass, the actions of the update trigger should not matter +INSERT INTO bug22580_t1 VALUES (1,1); + +DROP TABLE bug22580_t1; +DROP PROCEDURE bug22580_proc_1; +DROP PROCEDURE bug22580_proc_2; + --echo End of 5.0 tests From 9a1ec4d37637d3f97942bd94b18b5424867d39df Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Mar 2007 14:47:26 -0700 Subject: [PATCH 48/55] Fix for bug #25595 "missing DBUG_RETURN in function "mysql_stat"" libmysql/libmysql.c: Fix for bug #25595 "missing DBUG_RETURN in function "mysql_stat"" Use DBUG_RETURN instead of return --- libmysql/libmysql.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 7e1ff92bce5..6d1ad868e93 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -1367,7 +1367,7 @@ mysql_stat(MYSQL *mysql) { DBUG_ENTER("mysql_stat"); if (simple_command(mysql,COM_STATISTICS,0,0,0)) - return mysql->net.last_error; + DBUG_RETURN(mysql->net.last_error); DBUG_RETURN((*mysql->methods->read_statistics)(mysql)); } From 5fdfea0023e9d6cda586568ab5ae216c4c81c31c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 6 Mar 2007 14:55:52 -0700 Subject: [PATCH 49/55] Bug #25075: sql_class.cc doesn't compile with --without-query-cache Wrap query_cache_init_query() call with #ifdef HAVE_QUERY_CACHE in THD::THD() --- sql/sql_class.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 714b1244be4..bd9caf6a487 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -224,7 +224,9 @@ THD::THD() #endif client_capabilities= 0; // minimalistic client net.last_error[0]=0; // If error on boot +#ifdef HAVE_QUERY_CACHE query_cache_init_query(&net); // If error on boot +#endif ull=0; system_thread= cleanup_done= abort_on_warning= no_warnings_for_error= 0; peer_port= 0; // For SHOW PROCESSLIST From cddc768751db467e2c047371642bb49052eaf1d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Mar 2007 08:11:16 +0700 Subject: [PATCH 50/55] ndb - fix printout crashes testSystemRestart -n SR_UNDO ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: fix printout crashes testSystemRestart -n SR_UNDO --- ndb/src/kernel/blocks/dbdih/DbdihMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp index 7810aa45d00..f24a8e2c7d5 100644 --- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp +++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp @@ -13639,7 +13639,7 @@ Dbdih::execDUMP_STATE_ORD(Signal* signal) } if(arg == DumpStateOrd::EnableUndoDelayDataWrite){ - g_eventLogger.info("Dbdih:: delay write of datapages for table = %s", + g_eventLogger.info("Dbdih:: delay write of datapages for table = %d", dumpState->args[1]); // Send this dump to ACC and TUP EXECUTE_DIRECT(DBACC, GSN_DUMP_STATE_ORD, signal, 2); From 053c6c01d62707fa6189d411fdaf1040b948f9e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Mar 2007 12:24:46 +0300 Subject: [PATCH 51/55] A fix for Bug#26750 "valgrind leak in sp_head" (and post-review fixes). The legend: on a replication slave, in case a trigger creation was filtered out because of application of replicate-do-table/ replicate-ignore-table rule, the parsed definition of a trigger was not cleaned up properly. LEX::sphead member was left around and leaked memory. Until the actual implementation of support of replicate-ignore-table rules for triggers by the patch for Bug 24478 it was never the case that "case SQLCOM_CREATE_TRIGGER" was not executed once a trigger was parsed, so the deletion of lex->sphead there worked and the memory did not leak. The fix: The real cause of the bug is that there is no 1 or 2 places where we can clean up the main LEX after parse. And the reason we can not have just one or two places where we clean up the LEX is asymmetric behaviour of MYSQLparse in case of success or error. One of the root causes of this behaviour is the code in Item::Item() constructor. There, a newly created item adds itself to THD::free_list - a single-linked list of Items used in a statement. Yuck. This code is unaware that we may have more than one statement active at a time, and always assumes that the free_list of the current statement is located in THD::free_list. One day we need to be able to explicitly allocate an item in a given Query_arena. Thus, when parsing a definition of a stored procedure, like CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END; we actually need to reset THD::mem_root, THD::free_list and THD::lex to parse the nested procedure statement (SELECT *). The actual reset and restore is implemented in semantic actions attached to sp_proc_stmt grammar rule. The problem is that in case of a parsing error inside a nested statement Bison generated parser would abort immediately, without executing the restore part of the semantic action. This would leave THD in an in-the-middle-of-parsing state. This is why we couldn't have had a single place where we clean up the LEX after MYSQLparse - in case of an error we needed to do a clean up immediately, in case of success a clean up could have been delayed. This left the door open for a memory leak. One of the following possibilities were considered when working on a fix: - patch the replication logic to do the clean up. Rejected as breaks module borders, replication code should not need to know the gory details of clean up procedure after CREATE TRIGGER. - wrap MYSQLparse with a function that would do a clean up. Rejected as ideally we should fix the problem when it happens, not adjust for it outside of the problematic code. - make sure MYSQLparse cleans up after itself by invoking the clean up functionality in the appropriate places before return. Implemented in this patch. - use %destructor rule for sp_proc_stmt to restore THD - cleaner than the prevoius approach, but rejected because needs a careful analysis of the side effects, and this patch is for 5.0, and long term we need to use the next alternative anyway - make sure that sp_proc_stmt doesn't juggle with THD - this is a large work that will affect many modules. Cleanup: move main_lex and main_mem_root from Statement to its only two descendants Prepared_statement and THD. This ensures that when a Statement instance was created for purposes of statement backup, we do not involve LEX constructor/destructor, which is fairly expensive. In order to track that the transformation produces equivalent functionality please check the respective constructors and destructors of Statement, Prepared_statement and THD - these members were used only there. This cleanup is unrelated to the patch. sql/log_event.cc: THD::main_lex is private and should not be used. sql/mysqld.cc: Move MYSQLerror to sql_yacc.yy as it depends on LEX headers now. sql/sql_class.cc: Cleanup: move main_lex and main_mem_root to THD and Prepared_statement sql/sql_class.h: Cleanup: move main_lex and main_mem_root to THD and Prepared_statement sql/sql_lex.cc: Implement st_lex::restore_lex() sql/sql_lex.h: Declare st_lex::restore_lex(). sql/sql_parse.cc: Consolidate the calls to unit.cleanup() and deletion of lex->sphead in mysql_parse (COM_QUERY handler) sql/sql_prepare.cc: No need to delete lex->sphead to restore memory roots now in case of a parse error - this is done automatically inside MYSQLparse sql/sql_trigger.cc: This code could lead to double deletion apparently, as in case of an error lex.sphead was never reset. sql/sql_yacc.yy: Trap all returns from the parser to ensure that MySQL-specific cleanup is invoked: we need to restore the global state of THD and LEX in case of a parsing error. In case of a parsing success this happens as part of normal grammar reduction process. --- sql/log_event.cc | 4 +- sql/mysqld.cc | 12 - sql/sql_class.cc | 32 +- sql/sql_class.h | 55 +++- sql/sql_lex.cc | 30 ++ sql/sql_lex.h | 4 + sql/sql_parse.cc | 34 +-- sql/sql_prepare.cc | 50 ++-- sql/sql_trigger.cc | 7 +- sql/sql_yacc.yy | 721 +++++++++++++++++++++++++-------------------- 10 files changed, 524 insertions(+), 425 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 227b6f0073e..dbf69acf70a 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3114,8 +3114,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, ex.skip_lines = skip_lines; List field_list; - thd->main_lex.select_lex.context.resolve_in_table_list_only(&tables); - set_fields(tables.db, field_list, &thd->main_lex.select_lex.context); + thd->lex->select_lex.context.resolve_in_table_list_only(&tables); + set_fields(tables.db, field_list, &thd->lex->select_lex.context); thd->variables.pseudo_thread_id= thread_id; if (net) { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f8fbbee5644..bcf02b67a24 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1598,18 +1598,6 @@ static void network_init(void) #endif /*!EMBEDDED_LIBRARY*/ -void MYSQLerror(const char *s) -{ - THD *thd=current_thd; - char *yytext= (char*) thd->lex->tok_start; - /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */ - if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0) - s=ER(ER_SYNTAX_ERROR); - my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s, - (yytext ? (char*) yytext : ""), - thd->lex->yylineno); -} - #ifndef EMBEDDED_LIBRARY /* diff --git a/sql/sql_class.cc b/sql/sql_class.cc index cef9257c235..e7ea86ac850 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -166,14 +166,10 @@ Open_tables_state::Open_tables_state(ulong version_arg) } -/* - Pass nominal parameters to Statement constructor only to ensure that - the destructor works OK in case of error. The main_mem_root will be - re-initialized in init(). -*/ THD::THD() - :Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0), + :Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION, + /* statement id */ 0), Open_tables_state(refresh_version), lock_id(&main_lock_id), user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0), @@ -184,6 +180,12 @@ THD::THD() { ulong tmp; + /* + Pass nominal parameters to init_alloc_root only to ensure that + the destructor works OK in case of an error. The main_mem_root + will be re-initialized in init_for_queries(). + */ + init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); stmt_arena= this; thread_stack= 0; db= 0; @@ -443,6 +445,7 @@ THD::~THD() #ifndef DBUG_OFF dbug_sentry= THD_SENTRY_GONE; #endif + free_root(&main_mem_root, MYF(0)); DBUG_VOID_RETURN; } @@ -1581,18 +1584,17 @@ void Query_arena::cleanup_stmt() Statement functions */ -Statement::Statement(enum enum_state state_arg, ulong id_arg, - ulong alloc_block_size, ulong prealloc_size) - :Query_arena(&main_mem_root, state_arg), +Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, + enum enum_state state_arg, ulong id_arg) + :Query_arena(mem_root_arg, state_arg), id(id_arg), set_query_id(1), - lex(&main_lex), + lex(lex_arg), query(0), query_length(0), cursor(0) { name.str= NULL; - init_sql_alloc(&main_mem_root, alloc_block_size, prealloc_size); } @@ -1634,7 +1636,7 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup) void THD::end_statement() { - /* Cleanup SQL processing state to resuse this statement in next query. */ + /* Cleanup SQL processing state to reuse this statement in next query. */ lex_end(lex); delete lex->result; lex->result= 0; @@ -1675,12 +1677,6 @@ void THD::restore_active_arena(Query_arena *set, Query_arena *backup) Statement::~Statement() { - /* - We must free `main_mem_root', not `mem_root' (pointer), to work - correctly if this statement is used as a backup statement, - for which `mem_root' may point to some other statement. - */ - free_root(&main_mem_root, MYF(0)); } C_MODE_START diff --git a/sql/sql_class.h b/sql/sql_class.h index 556b5f6e863..26e119d0a5a 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -753,8 +753,10 @@ public: class Server_side_cursor; -/* - State of a single command executed against this connection. +/** + @class Statement + @brief State of a single command executed against this connection. + One connection can contain a lot of simultaneously running statements, some of which could be: - prepared, that is, contain placeholders, @@ -772,10 +774,6 @@ class Statement: public ilink, public Query_arena Statement(const Statement &rhs); /* not implemented: */ Statement &operator=(const Statement &rhs); /* non-copyable */ public: - /* FIXME: these must be protected */ - MEM_ROOT main_mem_root; - LEX main_lex; - /* Uniquely identifies each statement object in thread scope; change during statement lifetime. FIXME: must be const @@ -819,10 +817,10 @@ public: public: /* This constructor is called for backup statements */ - Statement() { clear_alloc_root(&main_mem_root); } + Statement() {} - Statement(enum enum_state state_arg, ulong id_arg, - ulong alloc_block_size, ulong prealloc_size); + Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg, + enum enum_state state_arg, ulong id_arg); virtual ~Statement(); /* Assign execution context (note: not all members) of given stmt to self */ @@ -834,7 +832,7 @@ public: }; -/* +/** Container for all statements created/used in a connection. Statements in Statement_map have unique Statement::id (guaranteed by id assignment in Statement::Statement) @@ -914,6 +912,10 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state); bool xid_cache_insert(XID_STATE *xid_state); void xid_cache_delete(XID_STATE *xid_state); +/** + @class Security_context + @brief A set of THD members describing the current authenticated user. +*/ class Security_context { public: @@ -943,7 +945,7 @@ public: }; -/* +/** A registry for item tree transformations performed during query optimization. We register only those changes which require a rollback to re-execute a prepared statement or stored procedure @@ -954,7 +956,7 @@ struct Item_change_record; typedef I_List Item_change_list; -/* +/** Type of prelocked mode. See comment for THD::prelocked_mode for complete description. */ @@ -963,7 +965,7 @@ enum prelocked_mode_type {NON_PRELOCKED= 0, PRELOCKED= 1, PRELOCKED_UNDER_LOCK_TABLES= 2}; -/* +/** Class that holds information about tables which were opened and locked by the thread. It is also used to save/restore this information in push_open_tables_state()/pop_open_tables_state(). @@ -1048,14 +1050,17 @@ public: } }; - -/* class to save context when executing a function or trigger */ +/** + @class Sub_statement_state + @brief Used to save context when executing a function or trigger +*/ /* Defines used for Sub_statement_state::in_sub_stmt */ #define SUB_STMT_TRIGGER 1 #define SUB_STMT_FUNCTION 2 + class Sub_statement_state { public: @@ -1072,7 +1077,8 @@ public: }; -/* +/** + @class THD For each client connection we create a separate thread with THD serving as a thread/connection descriptor */ @@ -1659,6 +1665,23 @@ public: *p_db_length= db_length; return FALSE; } +private: + /** + The lex to hold the parsed tree of conventional (non-prepared) queries. + Whereas for prepared and stored procedure statements we use an own lex + instance for each new query, for conventional statements we reuse + the same lex. (@see mysql_parse for details). + */ + LEX main_lex; + /** + This memory root is used for two purposes: + - for conventional queries, to allocate structures stored in main_lex + during parsing, and allocate runtime data (execution plan, etc.) + during execution. + - for prepared queries, only to allocate runtime data. The parsed + tree itself is reused between executions and thus is stored elsewhere. + */ + MEM_ROOT main_mem_root; }; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9a9731459b3..d95d2733dcd 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1648,6 +1648,36 @@ void st_select_lex::print_limit(THD *thd, String *str) } } +/** + @brief Restore the LEX and THD in case of a parse error. + + This is a clean up call that is invoked by the Bison generated + parser before returning an error from MYSQLparse. If your + semantic actions manipulate with the global thread state (which + is a very bad practice and should not normally be employed) and + need a clean-up in case of error, and you can not use %destructor + rule in the grammar file itself, this function should be used + to implement the clean up. +*/ + +void st_lex::cleanup_lex_after_parse_error(THD *thd) +{ + /* + Delete sphead for the side effect of restoring of the original + LEX state, thd->lex, thd->mem_root and thd->free_list if they + were replaced when parsing stored procedure statements. We + will never use sphead object after a parse error, so it's okay + to delete it only for the sake of the side effect. + TODO: make this functionality explicit in sp_head class. + Sic: we must nullify the member of the main lex, not the + current one that will be thrown away + */ + if (thd->lex->sphead); + { + delete thd->lex->sphead; + thd->lex->sphead= NULL; + } +} /* Initialize (or reset) Query_tables_list object. diff --git a/sql/sql_lex.h b/sql/sql_lex.h index b963ada2004..b8be619c0c8 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1182,6 +1182,10 @@ typedef struct st_lex : public Query_tables_list { return context_stack.head(); } + /* + Restore the LEX and THD in case of a parse error. + */ + static void cleanup_lex_after_parse_error(THD *thd); void reset_n_backup_query_tables_list(Query_tables_list *backup); void restore_backup_query_tables_list(Query_tables_list *backup); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7f5fb416a94..d9e16ac8350 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4506,9 +4506,6 @@ end_with_restore_list: clean up the environment. */ create_sp_error: - lex->unit.cleanup(); - delete lex->sphead; - lex->sphead= 0; if (sp_result != SP_OK ) goto error; send_ok(thd); @@ -4879,9 +4876,6 @@ create_sp_error: /* Conditionally writes to binlog. */ res= mysql_create_or_drop_trigger(thd, all_tables, 1); - /* We don't care about trigger body after this point */ - delete lex->sphead; - lex->sphead= 0; break; } case SQLCOM_DROP_TRIGGER: @@ -5904,15 +5898,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length) else #endif { - if (thd->net.report_error) - { - if (thd->lex->sphead) - { - delete thd->lex->sphead; - thd->lex->sphead= NULL; - } - } - else + if (! thd->net.report_error) { /* Binlog logs a string starting from thd->query and having length @@ -5932,7 +5918,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length) query_cache_end_of_result(thd); } } - lex->unit.cleanup(); } else { @@ -5940,19 +5925,14 @@ void mysql_parse(THD *thd, char *inBuf, uint length) DBUG_PRINT("info",("Command aborted. Fatal_error: %d", thd->is_fatal_error)); - /* - The first thing we do after parse error is freeing sp_head to - ensure that we have restored original memroot. - */ - if (thd->lex->sphead) - { - /* Clean up after failed stored procedure/function */ - delete thd->lex->sphead; - thd->lex->sphead= NULL; - } query_cache_abort(&thd->net); - lex->unit.cleanup(); } + if (thd->lex->sphead) + { + delete thd->lex->sphead; + thd->lex->sphead= 0; + } + lex->unit.cleanup(); thd->proc_info="freeing items"; thd->end_statement(); thd->cleanup_after_query(); diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 0fdbd24e05c..33a57e8bea6 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -99,9 +99,12 @@ public: #endif }; -/****************************************************************************** - Prepared_statement: a statement that can contain placeholders -******************************************************************************/ +/****************************************************************************/ + +/** + @class Prepared_statement + @brief Prepared_statement: a statement that can contain placeholders +*/ class Prepared_statement: public Statement { @@ -141,6 +144,16 @@ public: bool execute(String *expanded_query, bool open_cursor); /* Destroy this statement */ bool deallocate(); +private: + /** + Store the parsed tree of a prepared statement here. + */ + LEX main_lex; + /** + The memory root to allocate parsed tree elements (instances of Item, + SELECT_LEX and other classes). + */ + MEM_ROOT main_mem_root; }; @@ -2034,6 +2047,7 @@ void mysql_sql_stmt_prepare(THD *thd) delete stmt; DBUG_VOID_RETURN; } + if (thd->stmt_map.insert(thd, stmt)) { /* The statement is deleted and an error is set if insert fails */ @@ -2629,17 +2643,18 @@ Select_fetch_protocol_prep::send_data(List &fields) ****************************************************************************/ Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg) - :Statement(INITIALIZED, ++thd_arg->statement_id_counter, - thd_arg->variables.query_alloc_block_size, - thd_arg->variables.query_prealloc_size), + :Statement(&main_lex, &main_mem_root, + INITIALIZED, ++thd_arg->statement_id_counter), thd(thd_arg), result(thd_arg), protocol(protocol_arg), param_array(0), param_count(0), last_errno(0), - flags((uint) IS_IN_USE) + flags((uint) IS_IN_USE) { + init_alloc_root(&main_mem_root, thd_arg->variables.query_alloc_block_size, + thd_arg->variables.query_prealloc_size); *last_error= '\0'; } @@ -2688,6 +2703,7 @@ Prepared_statement::~Prepared_statement() */ free_items(); delete lex->result; + free_root(&main_mem_root, MYF(0)); DBUG_VOID_RETURN; } @@ -2703,6 +2719,7 @@ void Prepared_statement::cleanup_stmt() DBUG_ENTER("Prepared_statement::cleanup_stmt"); DBUG_PRINT("enter",("stmt: %p", this)); + DBUG_ASSERT(lex->sphead == 0); /* The order is important */ lex->unit.cleanup(); cleanup_items(free_list); @@ -2789,15 +2806,6 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) error= MYSQLparse((void *)thd) || thd->is_fatal_error || thd->net.report_error || init_param_array(this); - /* - The first thing we do after parse error is freeing sp_head to - ensure that we have restored original memroot. - */ - if (error && lex->sphead) - { - delete lex->sphead; - lex->sphead= NULL; - } /* While doing context analysis of the query (in check_prepared_statement) we allocate a lot of additional memory: for open tables, JOINs, derived @@ -2823,12 +2831,18 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) if (error == 0) error= check_prepared_statement(this, name.str != 0); - /* Free sp_head if check_prepared_statement() failed. */ - if (error && lex->sphead) + /* + Currently CREATE PROCEDURE/TRIGGER/EVENT are prohibited in prepared + statements: ensure we have no memory leak here if by someone tries + to PREPARE stmt FROM "CREATE PROCEDURE ..." + */ + DBUG_ASSERT(lex->sphead == NULL || error != 0); + if (lex->sphead) { delete lex->sphead; lex->sphead= NULL; } + lex_end(lex); cleanup_stmt(); thd->restore_backup_statement(this, &stmt_backup); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 42a361cc464..55d51ad07b7 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -983,11 +983,8 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, thd->spcont= 0; if (MYSQLparse((void *)thd) || thd->is_fatal_error) { - /* - Free lex associated resources. - QQ: Do we really need all this stuff here ? - */ - delete lex.sphead; + /* Currently sphead is always deleted in case of a parse error */ + DBUG_ASSERT(lex.sphead == 0); goto err_with_lex_cleanup; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6b15ccfd729..d07234ff2bd 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -52,11 +52,18 @@ const LEX_STRING null_lex_str={0,0}; ER_WARN_DEPRECATED_SYNTAX, \ ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B)); -#define YYABORT_UNLESS(A) \ +#define MYSQL_YYABORT \ + do \ + { \ + LEX::cleanup_lex_after_parse_error(YYTHD);\ + YYABORT; \ + } while (0) + +#define MYSQL_YYABORT_UNLESS(A) \ if (!(A)) \ - { \ - yyerror(ER(ER_SYNTAX_ERROR)); \ - YYABORT; \ + { \ + my_parse_error(ER(ER_SYNTAX_ERROR));\ + MYSQL_YYABORT; \ } #ifndef DBUG_OFF @@ -65,6 +72,66 @@ const LEX_STRING null_lex_str={0,0}; #define YYDEBUG 0 #endif +/** + @brief Push an error message into MySQL error stack with line + and position information. + + This function provides semantic action implementers with a way + to push the famous "You have a syntax error near..." error + message into the error stack, which is normally produced only if + a parse error is discovered internally by the Bison generated + parser. +*/ + +void my_parse_error(const char *s) +{ + THD *thd= current_thd; + + char *yytext= (char*) thd->lex->tok_start; + /* Push an error into the error stack */ + my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s, + (yytext ? (char*) yytext : ""), + thd->lex->yylineno); +} + +/** + @brief Bison callback to report a syntax/OOM error + + This function is invoked by the bison-generated parser + when a syntax error, a parse error or an out-of-memory + condition occurs. This function is not invoked when the + parser is requested to abort by semantic action code + by means of YYABORT or YYACCEPT macros. This is why these + macros should not be used (use MYSQL_YYABORT/MYSQL_YYACCEPT + instead). + + The parser will abort immediately after invoking this callback. + + This function is not for use in semantic actions and is internal to + the parser, as it performs some pre-return cleanup. + In semantic actions, please use my_parse_error or my_error to + push an error into the error stack and MYSQL_YYABORT + to abort from the parser. +*/ + +void MYSQLerror(const char *s) +{ + THD *thd= current_thd; + + /* + Restore the original LEX if it was replaced when parsing + a stored procedure. We must ensure that a parsing error + does not leave any side effects in the THD. + */ + LEX::cleanup_lex_after_parse_error(thd); + + /* "parse error" changed into "syntax error" between bison 1.75 and 1.875 */ + if (strcmp(s,"parse error") == 0 || strcmp(s,"syntax error") == 0) + s= ER(ER_SYNTAX_ERROR); + my_parse_error(s); +} + + #ifndef DBUG_OFF void turn_parser_debug_on() { @@ -1138,7 +1205,7 @@ query: (!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT))) { my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0)); - YYABORT; + MYSQL_YYABORT; } else { @@ -1210,8 +1277,8 @@ deallocate: LEX *lex= thd->lex; if (lex->stmt_prepare_mode) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_DEALLOCATE_PREPARE; lex->prepared_stmt_name= $3; @@ -1230,8 +1297,8 @@ prepare: LEX *lex= thd->lex; if (lex->stmt_prepare_mode) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_PREPARE; lex->prepared_stmt_name= $2; @@ -1260,8 +1327,8 @@ execute: LEX *lex= thd->lex; if (lex->stmt_prepare_mode) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_EXECUTE; lex->prepared_stmt_name= $2; @@ -1285,7 +1352,7 @@ execute_var_ident: '@' ident_or_text LEX *lex=Lex; LEX_STRING *lexstr= (LEX_STRING*)sql_memdup(&$2, sizeof(LEX_STRING)); if (!lexstr || lex->prepared_stmt_params.push_back(lexstr)) - YYABORT; + MYSQL_YYABORT; } ; @@ -1297,7 +1364,7 @@ help: if (Lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "HELP"); - YYABORT; + MYSQL_YYABORT; } } ident_or_text @@ -1424,7 +1491,7 @@ create: (using_update_log ? TL_READ_NO_INSERT: TL_READ))) - YYABORT; + MYSQL_YYABORT; lex->alter_info.reset(); lex->col_list.empty(); lex->change=NullS; @@ -1442,7 +1509,7 @@ create: lex->sql_command= SQLCOM_CREATE_INDEX; if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL, TL_OPTION_UPDATING)) - YYABORT; + MYSQL_YYABORT; lex->alter_info.reset(); lex->alter_info.flags= ALTER_ADD_INDEX; lex->col_list.empty(); @@ -1503,12 +1570,12 @@ sp_name: if (!$1.str || check_db_name($1.str)) { my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } if (check_routine_name($3)) { my_error(ER_SP_WRONG_NAME, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } $$= new sp_name($1, $3); $$->init_qname(YYTHD); @@ -1520,10 +1587,10 @@ sp_name: if (check_routine_name($1)) { my_error(ER_SP_WRONG_NAME, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } if (thd->copy_db_to(&db.str, &db.length)) - YYABORT; + MYSQL_YYABORT; $$= new sp_name(db, $1); if ($$) $$->init_qname(YYTHD); @@ -1543,7 +1610,7 @@ create_function_tail: and is considered a parsing error. */ my_error(ER_WRONG_USAGE, MYF(0), "SONAME", "DEFINER"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_CREATE_FUNCTION; lex->udf.name = lex->spname->m_name; @@ -1562,13 +1629,13 @@ create_function_tail: if (lex->udf.type == UDFTYPE_AGGREGATE) { my_error(ER_SP_NO_AGGREGATE, MYF(0)); - YYABORT; + MYSQL_YYABORT; } if (lex->sphead) { my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION"); - YYABORT; + MYSQL_YYABORT; } /* Order is important here: new - reset - init */ sp= new sp_head(); @@ -1609,7 +1676,7 @@ create_function_tail: if (sp->fill_field_definition(YYTHD, lex, (enum enum_field_types) $8, &sp->m_return_field_def)) - YYABORT; + MYSQL_YYABORT; bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } @@ -1626,14 +1693,14 @@ create_function_tail: sp_head *sp= lex->sphead; if (sp->is_not_allowed_in_function("function")) - YYABORT; + MYSQL_YYABORT; lex->sql_command= SQLCOM_CREATE_SPFUNCTION; sp->init_strings(YYTHD, lex); if (!(sp->m_flags & sp_head::HAS_RETURN)) { my_error(ER_SP_NORETURN, MYF(0), sp->m_qname.str); - YYABORT; + MYSQL_YYABORT; } /* Restore flag if it was cleared above */ if (sp->m_old_cmq) @@ -1763,7 +1830,7 @@ sp_fdparam: if (spc->find_variable(&$1, TRUE)) { my_error(ER_SP_DUP_PARAM, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } sp_variable_t *spvar= spc->push_variable(&$1, (enum enum_field_types)$3, @@ -1773,7 +1840,7 @@ sp_fdparam: (enum enum_field_types) $3, &spvar->field_def)) { - YYABORT; + MYSQL_YYABORT; } spvar->field_def.field_name= spvar->name.str; spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL; @@ -1800,7 +1867,7 @@ sp_pdparam: if (spc->find_variable(&$3, TRUE)) { my_error(ER_SP_DUP_PARAM, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } sp_variable_t *spvar= spc->push_variable(&$3, (enum enum_field_types)$4, @@ -1810,7 +1877,7 @@ sp_pdparam: (enum enum_field_types) $4, &spvar->field_def)) { - YYABORT; + MYSQL_YYABORT; } spvar->field_def.field_name= spvar->name.str; spvar->field_def.pack_flag |= FIELDFLAG_MAYBE_NULL; @@ -1849,13 +1916,13 @@ sp_decls: { /* Variable or condition following cursor or handler */ my_message(ER_SP_VARCOND_AFTER_CURSHNDLR, ER(ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0)); - YYABORT; + MYSQL_YYABORT; } if ($2.curs && $1.hndlrs) { /* Cursor following handler */ my_message(ER_SP_CURSOR_AFTER_HANDLER, ER(ER_SP_CURSOR_AFTER_HANDLER), MYF(0)); - YYABORT; + MYSQL_YYABORT; } $$.vars= $1.vars + $2.vars; $$.conds= $1.conds + $2.conds; @@ -1893,7 +1960,7 @@ sp_decl: sp_variable_t *spvar= pctx->find_variable(var_idx); if (!spvar) - YYABORT; + MYSQL_YYABORT; spvar->type= var_type; spvar->dflt= dflt_value_item; @@ -1901,7 +1968,7 @@ sp_decl: if (lex->sphead->fill_field_definition(YYTHD, lex, var_type, &spvar->field_def)) { - YYABORT; + MYSQL_YYABORT; } spvar->field_def.field_name= spvar->name.str; @@ -1929,7 +1996,7 @@ sp_decl: if (spc->find_cond(&$2, TRUE)) { my_error(ER_SP_DUP_COND, MYF(0), $2.str); - YYABORT; + MYSQL_YYABORT; } YYTHD->lex->spcont->push_cond(&$2, $5); $$.vars= $$.hndlrs= $$.curs= 0; @@ -1987,7 +2054,7 @@ sp_decl: { my_error(ER_SP_DUP_CURS, MYF(0), $2.str); delete $5; - YYABORT; + MYSQL_YYABORT; } i= new sp_instr_cpush(sp->instructions(), ctx, $5, ctx->current_cursor_count()); @@ -2015,13 +2082,13 @@ sp_cursor_stmt: { my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY), MYF(0)); - YYABORT; + MYSQL_YYABORT; } if (lex->result) { my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT), MYF(0)); - YYABORT; + MYSQL_YYABORT; } lex->sp_lex_in_use= TRUE; $$= lex; @@ -2045,7 +2112,7 @@ sp_hcond_list: if (ctx->find_handler($1)) { my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0)); - YYABORT; + MYSQL_YYABORT; } else { @@ -2066,7 +2133,7 @@ sp_hcond_list: if (ctx->find_handler($3)) { my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0)); - YYABORT; + MYSQL_YYABORT; } else { @@ -2092,7 +2159,7 @@ sp_cond: if (!sp_cond_check(&$3)) { my_error(ER_SP_BAD_SQLSTATE, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } $$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t)); $$->type= sp_cond_type_t::state; @@ -2117,7 +2184,7 @@ sp_hcond: if ($$ == NULL) { my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } } | SQLWARNING_SYM /* SQLSTATEs 01??? */ @@ -2148,7 +2215,7 @@ sp_decl_idents: if (spc->find_variable(&$1, TRUE)) { my_error(ER_SP_DUP_VAR, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } spc->push_variable(&$1, (enum_field_types)0, sp_param_in); $$= 1; @@ -2163,7 +2230,7 @@ sp_decl_idents: if (spc->find_variable(&$3, TRUE)) { my_error(ER_SP_DUP_VAR, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } spc->push_variable(&$3, (enum_field_types)0, sp_param_in); $$= $1 + 1; @@ -2191,7 +2258,7 @@ sp_proc_stmt: if (lex->sql_command == SQLCOM_CHANGE_DB) { /* "USE db" doesn't work in a procedure */ my_error(ER_SP_BADSTATEMENT, MYF(0), "USE"); - YYABORT; + MYSQL_YYABORT; } /* Don't add an instruction for SET statements, since all @@ -2231,7 +2298,7 @@ sp_proc_stmt: if (sp->m_type != TYPE_ENUM_FUNCTION) { my_message(ER_SP_BADRETURN, ER(ER_SP_BADRETURN), MYF(0)); - YYABORT; + MYSQL_YYABORT; } else { @@ -2272,7 +2339,7 @@ sp_proc_stmt: if (! lab) { my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str); - YYABORT; + MYSQL_YYABORT; } else { @@ -2301,7 +2368,7 @@ sp_proc_stmt: if (! lab || lab->type != SP_LAB_ITER) { my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str); - YYABORT; + MYSQL_YYABORT; } else { @@ -2329,7 +2396,7 @@ sp_proc_stmt: if (! lex->spcont->find_cursor(&$2, &offset)) { my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str); - YYABORT; + MYSQL_YYABORT; } i= new sp_instr_copen(sp->instructions(), lex->spcont, offset); sp->add_instr(i); @@ -2344,7 +2411,7 @@ sp_proc_stmt: if (! lex->spcont->find_cursor(&$3, &offset)) { my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset); sp->add_instr(i); @@ -2361,7 +2428,7 @@ sp_proc_stmt: if (! lex->spcont->find_cursor(&$2, &offset)) { my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str); - YYABORT; + MYSQL_YYABORT; } i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset); sp->add_instr(i); @@ -2385,7 +2452,7 @@ sp_fetch_list: if (!spc || !(spv = spc->find_variable(&$1))) { my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } else { @@ -2406,7 +2473,7 @@ sp_fetch_list: if (!spc || !(spv = spc->find_variable(&$3))) { my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } else { @@ -2475,7 +2542,7 @@ simple_case_stmt: { LEX *lex= Lex; if (case_stmt_action_expr(lex, $3)) - YYABORT; + MYSQL_YYABORT; lex->sphead->restore_lex(YYTHD); /* For expr $3 */ } @@ -2578,7 +2645,7 @@ sp_labeled_control: if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } else { @@ -2599,7 +2666,7 @@ sp_labeled_control: my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) { my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); - YYABORT; + MYSQL_YYABORT; } } lex->sphead->backpatch(lex->spcont->pop_label()); @@ -2716,11 +2783,11 @@ create2: LEX *lex=Lex; THD *thd= lex->thd; if (!(lex->name= (char *)$2)) - YYABORT; + MYSQL_YYABORT; if ($2->db.str == NULL && thd->copy_db_to(&($2->db.str), &($2->db.length))) { - YYABORT; + MYSQL_YYABORT; } } | '(' LIKE table_ident ')' @@ -2728,11 +2795,11 @@ create2: LEX *lex=Lex; THD *thd= lex->thd; if (!(lex->name= (char *)$3)) - YYABORT; + MYSQL_YYABORT; if ($3->db.str == NULL && thd->copy_db_to(&($3->db.str), &($3->db.length))) { - YYABORT; + MYSQL_YYABORT; } } ; @@ -2844,8 +2911,8 @@ create_table_option: Lex->create_info.table_options|= HA_OPTION_PACK_KEYS; break; default: - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } Lex->create_info.used_fields|= HA_CREATE_USED_PACK_KEYS; } @@ -2861,17 +2928,17 @@ create_table_option: | RAID_TYPE opt_equal raid_types { my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_TYPE", "PARTITION"); - YYABORT; + MYSQL_YYABORT; } | RAID_CHUNKS opt_equal ulong_num { my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_CHUNKS", "PARTITION"); - YYABORT; + MYSQL_YYABORT; } | RAID_CHUNKSIZE opt_equal ulong_num { my_error(ER_WARN_DEPRECATED_SYNTAX, MYF(0), "RAID_CHUNKSIZE", "PARTITION"); - YYABORT; + MYSQL_YYABORT; } | UNION_SYM opt_equal '(' table_list ')' { @@ -2907,7 +2974,7 @@ default_charset: my_error(ER_CONFLICTING_DECLARATIONS, MYF(0), "CHARACTER SET ", cinfo->default_table_charset->csname, "CHARACTER SET ", $4->csname); - YYABORT; + MYSQL_YYABORT; } Lex->create_info.default_table_charset= $4; Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; @@ -2923,7 +2990,7 @@ default_collation: { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), $4->name, cinfo->default_table_charset->csname); - YYABORT; + MYSQL_YYABORT; } Lex->create_info.default_table_charset= $4; Lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; @@ -2935,7 +3002,7 @@ storage_engines: $$ = ha_resolve_by_name($1.str,$1.length); if ($$ == DB_TYPE_UNKNOWN) { my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } }; @@ -3070,7 +3137,7 @@ field_spec: &lex->comment, lex->change,&lex->interval_list,lex->charset, lex->uint_geom_type)) - YYABORT; + MYSQL_YYABORT; }; type: @@ -3139,7 +3206,7 @@ type: #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name, sym_group_geom.needed_define); - YYABORT; + MYSQL_YYABORT; #endif } | MEDIUMBLOB { Lex->charset=&my_charset_bin; @@ -3300,7 +3367,7 @@ attribute: { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), $2->name,Lex->charset->csname); - YYABORT; + MYSQL_YYABORT; } else { @@ -3325,7 +3392,7 @@ charset_name: if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0)))) { my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } } | BINARY { $$= &my_charset_bin; } @@ -3347,7 +3414,7 @@ old_or_new_charset_name: !($$=get_old_charset_by_name($1.str))) { my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } } | BINARY { $$= &my_charset_bin; } @@ -3363,7 +3430,7 @@ collation_name: if (!($$=get_charset_by_name($1.str,MYF(0)))) { my_error(ER_UNKNOWN_COLLATION, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } }; @@ -3390,7 +3457,7 @@ opt_binary: MY_CS_PRIMARY,MYF(0)))) { my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"); - YYABORT; + MYSQL_YYABORT; } } | charset charset_name opt_bin_mod { Lex->charset=$2; } @@ -3409,7 +3476,7 @@ opt_bin_charset: MY_CS_PRIMARY,MYF(0)))) { my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2"); - YYABORT; + MYSQL_YYABORT; } } | charset charset_name { Lex->charset=$2; } ; @@ -3472,7 +3539,7 @@ key_type: #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name, sym_group_geom.needed_define); - YYABORT; + MYSQL_YYABORT; #endif }; @@ -3505,7 +3572,7 @@ opt_unique_or_fulltext: #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name, sym_group_geom.needed_define); - YYABORT; + MYSQL_YYABORT; #endif } ; @@ -3565,7 +3632,7 @@ alter: lex->duplicates= DUP_ERROR; if (!lex->select_lex.add_table_to_list(thd, $4, NULL, TL_OPTION_UPDATING)) - YYABORT; + MYSQL_YYABORT; lex->col_list.empty(); lex->select_lex.init_order(); lex->select_lex.db= @@ -3591,7 +3658,7 @@ alter: lex->sql_command=SQLCOM_ALTER_DB; lex->name= $3; if (lex->name == NULL && thd->copy_db_to(&lex->name, NULL)) - YYABORT; + MYSQL_YYABORT; } | ALTER PROCEDURE sp_name { @@ -3600,7 +3667,7 @@ alter: if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"); - YYABORT; + MYSQL_YYABORT; } bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } @@ -3618,7 +3685,7 @@ alter: if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); - YYABORT; + MYSQL_YYABORT; } bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); } @@ -3697,7 +3764,7 @@ alter_list_item: &lex->comment, $3.str, &lex->interval_list, lex->charset, lex->uint_geom_type)) - YYABORT; + MYSQL_YYABORT; } opt_place | DROP opt_column field_ident opt_restrict @@ -3758,13 +3825,13 @@ alter_list_item: if (lex->select_lex.db == NULL && thd->copy_db_to(&lex->select_lex.db, NULL)) { - YYABORT; + MYSQL_YYABORT; } if (check_table_name($3->table.str,$3->table.length) || $3->db.str && check_db_name($3->db.str)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str); - YYABORT; + MYSQL_YYABORT; } lex->name= $3->table.str; lex->alter_info.flags|= ALTER_RENAME; @@ -3781,7 +3848,7 @@ alter_list_item: { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), $5->name, $4->csname); - YYABORT; + MYSQL_YYABORT; } LEX *lex= Lex; lex->create_info.table_charset= @@ -3919,7 +3986,7 @@ slave_until: { my_message(ER_BAD_SLAVE_UNTIL_COND, ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0)); - YYABORT; + MYSQL_YYABORT; } } @@ -4011,7 +4078,7 @@ check: if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "CHECK"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_CHECK; lex->check_opt.init(); @@ -4071,12 +4138,12 @@ rename_list: user TO_SYM user { if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3)) - YYABORT; + MYSQL_YYABORT; } | rename_list ',' user TO_SYM user { if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5)) - YYABORT; + MYSQL_YYABORT; } ; @@ -4093,7 +4160,7 @@ table_to_table: TL_IGNORE) || !sl->add_table_to_list(lex->thd, $3,NULL,TL_OPTION_UPDATING, TL_IGNORE)) - YYABORT; + MYSQL_YYABORT; }; keycache: @@ -4118,7 +4185,7 @@ assign_to_keycache: TL_READ, sel->get_use_index(), (List *)0)) - YYABORT; + MYSQL_YYABORT; } ; @@ -4150,7 +4217,7 @@ preload_keys: TL_READ, sel->get_use_index(), (List *)0)) - YYABORT; + MYSQL_YYABORT; } ; @@ -4205,16 +4272,16 @@ select_paren: SELECT_LEX * sel= lex->current_select; if (sel->set_braces(1)) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } if (sel->linkage == UNION_TYPE && !sel->master_unit()->first_select()->braces && sel->master_unit()->first_select()->linkage == UNION_TYPE) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } /* select in braces, can't contain global parameters */ if (sel->master_unit()->fake_select_lex) @@ -4230,14 +4297,14 @@ select_init2: SELECT_LEX * sel= lex->current_select; if (lex->current_select->set_braces(0)) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } if (sel->linkage == UNION_TYPE && sel->master_unit()->first_select()->braces) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } } union_clause @@ -4286,7 +4353,7 @@ select_options: if (test_all_bits(Select->options, SELECT_ALL | SELECT_DISTINCT)) { my_error(ER_WRONG_USAGE, MYF(0), "ALL", "DISTINCT"); - YYABORT; + MYSQL_YYABORT; } } ; @@ -4300,7 +4367,7 @@ select_option: | HIGH_PRIORITY { if (check_simple_select()) - YYABORT; + MYSQL_YYABORT; Lex->lock_option= TL_READ_HIGH_PRIORITY; } | DISTINCT { Select->options|= SELECT_DISTINCT; } @@ -4309,13 +4376,13 @@ select_option: | SQL_BUFFER_RESULT { if (check_simple_select()) - YYABORT; + MYSQL_YYABORT; Select->options|= OPTION_BUFFER_RESULT; } | SQL_CALC_FOUND_ROWS { if (check_simple_select()) - YYABORT; + MYSQL_YYABORT; Select->options|= OPTION_FOUND_ROWS; } | SQL_NO_CACHE_SYM @@ -4364,7 +4431,7 @@ select_item_list: new Item_field(&thd->lex->current_select-> context, NULL, NULL, "*"))) - YYABORT; + MYSQL_YYABORT; (thd->lex->current_select->with_wild)++; }; @@ -4373,7 +4440,7 @@ select_item: remember_name select_item2 remember_end select_alias { if (add_item_to_list(YYTHD, $2)) - YYABORT; + MYSQL_YYABORT; if ($4.str) { $2->is_autogenerated_name= FALSE; @@ -4653,7 +4720,7 @@ simple_expr: lex->dec ? atoi(lex->dec) : 0, lex->charset); if (!$$) - YYABORT; + MYSQL_YYABORT; } | CASE_SYM opt_expr when_list opt_else END { $$= new Item_func_case(* $3, $2, $4 ); } @@ -4664,7 +4731,7 @@ simple_expr: Lex->dec ? atoi(Lex->dec) : 0, Lex->charset); if (!$$) - YYABORT; + MYSQL_YYABORT; } | CONVERT_SYM '(' expr USING charset_name ')' { $$= new Item_func_conv_charset($3,$5); } @@ -4675,7 +4742,7 @@ simple_expr: Item_splocal *il= static_cast($3); my_error(ER_WRONG_COLUMN_NAME, MYF(0), il->my_name()->str); - YYABORT; + MYSQL_YYABORT; } $$= new Item_default_value(Lex->current_context(), $3); } @@ -4688,7 +4755,7 @@ simple_expr: my_error(ER_FEATURE_DISABLED, MYF(0), $1.symbol->group->name, $1.symbol->group->needed_define); - YYABORT; + MYSQL_YYABORT; } $$= ((Item*(*)(void))($1.symbol->create_func))(); } @@ -4699,7 +4766,7 @@ simple_expr: my_error(ER_FEATURE_DISABLED, MYF(0), $1.symbol->group->name, $1.symbol->group->needed_define); - YYABORT; + MYSQL_YYABORT; } $$= ((Item*(*)(Item*))($1.symbol->create_func))($3); } @@ -4710,7 +4777,7 @@ simple_expr: my_error(ER_FEATURE_DISABLED, MYF(0), $1.symbol->group->name, $1.symbol->group->needed_define); - YYABORT; + MYSQL_YYABORT; } $$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5); } @@ -4721,7 +4788,7 @@ simple_expr: my_error(ER_FEATURE_DISABLED, MYF(0), $1.symbol->group->name, $1.symbol->group->needed_define); - YYABORT; + MYSQL_YYABORT; } $$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7); } @@ -4752,7 +4819,7 @@ simple_expr: | CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')' { if (Lex->add_time_zone_tables_to_query_tables(YYTHD)) - YYABORT; + MYSQL_YYABORT; $$= new Item_func_convert_tz($3, $5, $7); } | CURDATE optional_braces @@ -4827,7 +4894,7 @@ simple_expr: #else my_error(ER_FEATURE_DISABLED, MYF(0), sym_group_geom.name, sym_group_geom.needed_define); - YYABORT; + MYSQL_YYABORT; #endif } | GET_FORMAT '(' date_time_type ',' expr ')' @@ -4845,8 +4912,8 @@ simple_expr: { if ($1->type() != Item::ROW_ITEM) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } $$= new Item_func_interval((Item_row *)$1); } @@ -5006,8 +5073,8 @@ simple_expr: { if (lex->current_select->inc_in_sum_expr()) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } } lex->current_select->udf_list.push_front(udf); @@ -5090,7 +5157,7 @@ simple_expr: } break; default: - YYABORT; + MYSQL_YYABORT; } } else @@ -5099,7 +5166,7 @@ simple_expr: THD *thd= lex->thd; LEX_STRING db; if (thd->copy_db_to(&db.str, &db.length)) - YYABORT; + MYSQL_YYABORT; sp_name *name= new sp_name(db, $1); if (name) name->init_qname(thd); @@ -5260,8 +5327,8 @@ udf_expr: Disallow using AS to specify explicit names for the arguments of stored routine calls */ - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } $2->is_autogenerated_name= FALSE; @@ -5340,7 +5407,7 @@ variable: if (! Lex->parsing_options.allows_variable) { my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); - YYABORT; + MYSQL_YYABORT; } } variable_aux @@ -5366,11 +5433,11 @@ variable_aux: { if ($3.str && $4.str && check_reserved_words(&$3)) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } if (!($$= get_system_var(YYTHD, $2, $3, $4))) - YYABORT; + MYSQL_YYABORT; } ; @@ -5404,8 +5471,8 @@ in_sum_expr: LEX *lex= Lex; if (lex->current_select->inc_in_sum_expr()) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } } expr @@ -5485,12 +5552,12 @@ table_ref: { LEX *lex= Lex; if (!($$= lex->current_select->nest_last_join(lex->thd))) - YYABORT; + MYSQL_YYABORT; } ; join_table_list: - derived_table_list { YYABORT_UNLESS($$=$1); } + derived_table_list { MYSQL_YYABORT_UNLESS($$=$1); } ; /* Warning - may return NULL in case of incomplete SELECT */ @@ -5498,7 +5565,7 @@ derived_table_list: table_ref { $$=$1; } | derived_table_list ',' table_ref { - YYABORT_UNLESS($1 && ($$=$3)); + MYSQL_YYABORT_UNLESS($1 && ($$=$3)); } ; @@ -5517,16 +5584,16 @@ join_table: left-associative joins. */ table_ref %prec TABLE_REF_PRIORITY normal_join table_ref - { YYABORT_UNLESS($1 && ($$=$3)); } + { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); } | table_ref STRAIGHT_JOIN table_factor - { YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; } + { MYSQL_YYABORT_UNLESS($1 && ($$=$3)); $3->straight=1; } | table_ref normal_join table_ref ON { - YYABORT_UNLESS($1 && $3); + MYSQL_YYABORT_UNLESS($1 && $3); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) - YYABORT; + MYSQL_YYABORT; Select->parsing_place= IN_ON; } expr @@ -5538,10 +5605,10 @@ join_table: | table_ref STRAIGHT_JOIN table_factor ON { - YYABORT_UNLESS($1 && $3); + MYSQL_YYABORT_UNLESS($1 && $3); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $3)) - YYABORT; + MYSQL_YYABORT; Select->parsing_place= IN_ON; } expr @@ -5554,13 +5621,13 @@ join_table: | table_ref normal_join table_ref USING { - YYABORT_UNLESS($1 && $3); + MYSQL_YYABORT_UNLESS($1 && $3); } '(' using_list ')' { add_join_natural($1,$3,$7,Select); $$=$3; } | table_ref NATURAL JOIN_SYM table_factor { - YYABORT_UNLESS($1 && ($$=$4)); + MYSQL_YYABORT_UNLESS($1 && ($$=$4)); add_join_natural($1,$4,NULL,Select); } @@ -5568,10 +5635,10 @@ join_table: | table_ref LEFT opt_outer JOIN_SYM table_ref ON { - YYABORT_UNLESS($1 && $5); + MYSQL_YYABORT_UNLESS($1 && $5); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) - YYABORT; + MYSQL_YYABORT; Select->parsing_place= IN_ON; } expr @@ -5584,7 +5651,7 @@ join_table: } | table_ref LEFT opt_outer JOIN_SYM table_factor { - YYABORT_UNLESS($1 && $5); + MYSQL_YYABORT_UNLESS($1 && $5); } USING '(' using_list ')' { @@ -5594,7 +5661,7 @@ join_table: } | table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor { - YYABORT_UNLESS($1 && $6); + MYSQL_YYABORT_UNLESS($1 && $6); add_join_natural($1,$6,NULL,Select); $6->outer_join|=JOIN_TYPE_LEFT; $$=$6; @@ -5604,39 +5671,39 @@ join_table: | table_ref RIGHT opt_outer JOIN_SYM table_ref ON { - YYABORT_UNLESS($1 && $5); + MYSQL_YYABORT_UNLESS($1 && $5); /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $1, $5)) - YYABORT; + MYSQL_YYABORT; Select->parsing_place= IN_ON; } expr { LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) - YYABORT; + MYSQL_YYABORT; add_join_on($$, $8); Lex->pop_context(); Select->parsing_place= NO_MATTER; } | table_ref RIGHT opt_outer JOIN_SYM table_factor { - YYABORT_UNLESS($1 && $5); + MYSQL_YYABORT_UNLESS($1 && $5); } USING '(' using_list ')' { LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) - YYABORT; + MYSQL_YYABORT; add_join_natural($$,$5,$9,Select); } | table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor { - YYABORT_UNLESS($1 && $6); + MYSQL_YYABORT_UNLESS($1 && $6); add_join_natural($6,$1,NULL,Select); LEX *lex= Lex; if (!($$= lex->current_select->convert_right_join())) - YYABORT; + MYSQL_YYABORT; }; normal_join: @@ -5661,7 +5728,7 @@ table_factor: lex->lock_option, sel->get_use_index(), sel->get_ignore_index()))) - YYABORT; + MYSQL_YYABORT; sel->add_joined_table($$); } | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref @@ -5669,19 +5736,19 @@ table_factor: { /* Change the current name resolution context to a local context. */ if (push_new_name_resolution_context(YYTHD, $3, $7)) - YYABORT; + MYSQL_YYABORT; } expr '}' { LEX *lex= Lex; - YYABORT_UNLESS($3 && $7); + MYSQL_YYABORT_UNLESS($3 && $7); add_join_on($7,$10); Lex->pop_context(); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; if (!($$= lex->current_select->nest_last_join(lex->thd))) - YYABORT; + MYSQL_YYABORT; } | select_derived_init get_select_lex select_derived2 { @@ -5691,8 +5758,8 @@ table_factor: { if (sel->set_braces(1)) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } /* select in braces, can't contain global parameters */ if (sel->master_unit()->fake_select_lex) @@ -5700,7 +5767,7 @@ table_factor: sel->master_unit()->fake_select_lex; } if ($2->init_nested_join(lex->thd)) - YYABORT; + MYSQL_YYABORT; $$= 0; /* incomplete derived tables return NULL, we must be nested in select_derived rule to be here. */ @@ -5734,7 +5801,7 @@ table_factor: TL_READ,(List *)0, (List *)0))) - YYABORT; + MYSQL_YYABORT; sel->add_joined_table($$); lex->pop_context(); } @@ -5742,8 +5809,8 @@ table_factor: if ($4 || $6) { /* simple nested joins cannot have aliases or unions */ - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } else $$= $3; @@ -5756,7 +5823,7 @@ select_derived: { LEX *lex= Lex; if ($1->init_nested_join(lex->thd)) - YYABORT; + MYSQL_YYABORT; } derived_table_list { @@ -5765,11 +5832,11 @@ select_derived: for derived tables, both must equal NULL */ if (!($$= $1->end_nested_join(lex->thd)) && $3) - YYABORT; + MYSQL_YYABORT; if (!$3 && $$) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } } ; @@ -5781,12 +5848,12 @@ select_derived2: if (lex->sql_command == (int)SQLCOM_HA_READ || lex->sql_command == (int)SQLCOM_KILL) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE || mysql_new_select(lex, 1)) - YYABORT; + MYSQL_YYABORT; mysql_init_select(lex); lex->current_select->linkage= DERIVED_TABLE_TYPE; lex->current_select->parsing_place= SELECT_LIST; @@ -5810,7 +5877,7 @@ select_derived_init: if (! lex->parsing_options.allows_derived) { my_error(ER_VIEW_SELECT_DERIVED, MYF(0)); - YYABORT; + MYSQL_YYABORT; } SELECT_LEX *sel= lex->current_select; @@ -5818,8 +5885,8 @@ select_derived_init: if (!sel->embedding || sel->end_nested_join(lex->thd)) { /* we are not in parentheses */ - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } embedding= Select->embedding; $$= embedding && @@ -5883,7 +5950,7 @@ using_list: ident { if (!($$= new List)) - YYABORT; + MYSQL_YYABORT; $$->push_back(new (YYTHD->mem_root) String((const char *) $1.str, $1.length, system_charset_info)); @@ -6003,9 +6070,9 @@ group_clause: group_list: group_list ',' order_ident order_dir - { if (add_group_to_list(YYTHD, $3,(bool) $4)) YYABORT; } + { if (add_group_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; } | order_ident order_dir - { if (add_group_to_list(YYTHD, $1,(bool) $2)) YYABORT; }; + { if (add_group_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; }; olap_opt: /* empty */ {} @@ -6016,11 +6083,11 @@ olap_opt: { my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE", "global union parameters"); - YYABORT; + MYSQL_YYABORT; } lex->current_select->olap= CUBE_TYPE; my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE"); - YYABORT; /* To be deleted in 5.1 */ + MYSQL_YYABORT; /* To be deleted in 5.1 */ } | WITH ROLLUP_SYM { @@ -6029,7 +6096,7 @@ olap_opt: { my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP", "global union parameters"); - YYABORT; + MYSQL_YYABORT; } lex->current_select->olap= ROLLUP_TYPE; } @@ -6054,7 +6121,7 @@ alter_order_item: THD *thd= YYTHD; bool ascending= ($2 == 1) ? true : false; if (add_order_to_list(thd, $1, ascending)) - YYABORT; + MYSQL_YYABORT; } ; @@ -6077,7 +6144,7 @@ order_clause: { my_error(ER_WRONG_USAGE, MYF(0), "CUBE/ROLLUP", "ORDER BY"); - YYABORT; + MYSQL_YYABORT; } if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex) { @@ -6094,15 +6161,15 @@ order_clause: (first_sl->order_list.elements || first_sl->select_limit) && unit->add_fake_select_lex(lex->thd)) - YYABORT; + MYSQL_YYABORT; } } order_list; order_list: order_list ',' order_ident order_dir - { if (add_order_to_list(YYTHD, $3,(bool) $4)) YYABORT; } + { if (add_order_to_list(YYTHD, $3,(bool) $4)) MYSQL_YYABORT; } | order_ident order_dir - { if (add_order_to_list(YYTHD, $1,(bool) $2)) YYABORT; }; + { if (add_order_to_list(YYTHD, $1,(bool) $2)) MYSQL_YYABORT; }; order_dir: /* empty */ { $$ = 1; } @@ -6199,13 +6266,13 @@ procedure_clause: if (! lex->parsing_options.allows_select_procedure) { my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "PROCEDURE"); - YYABORT; + MYSQL_YYABORT; } if (&lex->select_lex != lex->current_select) { my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery"); - YYABORT; + MYSQL_YYABORT; } lex->proc_list.elements=0; lex->proc_list.first=0; @@ -6214,7 +6281,7 @@ procedure_clause: current_select-> context, NULL,NULL,$2.str))) - YYABORT; + MYSQL_YYABORT; Lex->uncacheable(UNCACHEABLE_SIDEEFFECT); } '(' procedure_list ')'; @@ -6233,7 +6300,7 @@ procedure_item: { LEX *lex= Lex; if (add_proc_to_list(lex->thd, $2)) - YYABORT; + MYSQL_YYABORT; if (!$2->name) $2->set_name($1,(uint) ((char*) lex->tok_end - $1), YYTHD->charset()); @@ -6245,7 +6312,7 @@ select_var_list_init: { LEX *lex=Lex; if (!lex->describe && (!(lex->result= new select_dumpvar()))) - YYABORT; + MYSQL_YYABORT; } select_var_list {} @@ -6277,7 +6344,7 @@ select_var_ident: if (!lex->spcont || !(t=lex->spcont->find_variable(&$1))) { my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } if (lex->result) { @@ -6306,7 +6373,7 @@ into: if (! Lex->parsing_options.allows_select_into) { my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "INTO"); - YYABORT; + MYSQL_YYABORT; } } into_destination @@ -6319,7 +6386,7 @@ into_destination: lex->uncacheable(UNCACHEABLE_SIDEEFFECT); if (!(lex->exchange= new sql_exchange($2.str, 0)) || !(lex->result= new select_export(lex->exchange))) - YYABORT; + MYSQL_YYABORT; } opt_field_term opt_line_term | DUMPFILE TEXT_STRING_filesystem @@ -6329,9 +6396,9 @@ into_destination: { lex->uncacheable(UNCACHEABLE_SIDEEFFECT); if (!(lex->exchange= new sql_exchange($2.str,1))) - YYABORT; + MYSQL_YYABORT; if (!(lex->result= new select_dump(lex->exchange))) - YYABORT; + MYSQL_YYABORT; } } | select_var_list_init @@ -6378,7 +6445,7 @@ drop: $3.str)); if (!lex->current_select->add_table_to_list(lex->thd, $5, NULL, TL_OPTION_UPDATING)) - YYABORT; + MYSQL_YYABORT; } | DROP DATABASE if_exists ident { @@ -6393,7 +6460,7 @@ drop: if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_DROP_FUNCTION; lex->drop_if_exists= $3; @@ -6405,7 +6472,7 @@ drop: if (lex->sphead) { my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_DROP_PROCEDURE; lex->drop_if_exists= $3; @@ -6438,7 +6505,7 @@ table_name: table_ident { if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING)) - YYABORT; + MYSQL_YYABORT; } ; @@ -6536,7 +6603,7 @@ insert_field_spec: LEX *lex=Lex; if (!(lex->insert_list = new List_item) || lex->many_values.push_back(lex->insert_list)) - YYABORT; + MYSQL_YYABORT; } ident_eq_list; @@ -6566,7 +6633,7 @@ ident_eq_value: LEX *lex=Lex; if (lex->field_list.push_back($1) || lex->insert_list->push_back($3)) - YYABORT; + MYSQL_YYABORT; }; equal: EQ {} @@ -6582,13 +6649,13 @@ no_braces: '(' { if (!(Lex->insert_list = new List_item)) - YYABORT; + MYSQL_YYABORT; } opt_values ')' { LEX *lex=Lex; if (lex->many_values.push_back(lex->insert_list)) - YYABORT; + MYSQL_YYABORT; }; opt_values: @@ -6599,12 +6666,12 @@ values: values ',' expr_or_default { if (Lex->insert_list->push_back($3)) - YYABORT; + MYSQL_YYABORT; } | expr_or_default { if (Lex->insert_list->push_back($1)) - YYABORT; + MYSQL_YYABORT; } ; @@ -6641,7 +6708,7 @@ update: /* it is single table update and it is update of derived table */ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), lex->select_lex.get_table_list()->alias, "UPDATE"); - YYABORT; + MYSQL_YYABORT; } /* In case of multi-update setting write lock for all tables may @@ -6661,7 +6728,7 @@ update_elem: simple_ident_nospvar equal expr_or_default { if (add_item_to_list(YYTHD, $1) || add_value_to_list(YYTHD, $3)) - YYABORT; + MYSQL_YYABORT; }; insert_update_list: @@ -6674,7 +6741,7 @@ insert_update_elem: LEX *lex= Lex; if (lex->update_list.push_back($1) || lex->value_list.push_back($3)) - YYABORT; + MYSQL_YYABORT; }; opt_low_priority: @@ -6701,7 +6768,7 @@ single_multi: { if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING, Lex->lock_option)) - YYABORT; + MYSQL_YYABORT; } where_clause opt_order_clause delete_limit_clause {} @@ -6710,14 +6777,14 @@ single_multi: FROM join_table_list where_clause { if (multi_delete_set_locks_and_link_aux_tables(Lex)) - YYABORT; + MYSQL_YYABORT; } | FROM table_wild_list { mysql_init_multi_delete(Lex); } USING join_table_list where_clause { if (multi_delete_set_locks_and_link_aux_tables(Lex)) - YYABORT; + MYSQL_YYABORT; } ; @@ -6731,7 +6798,7 @@ table_wild_one: if (!Select->add_table_to_list(YYTHD, new Table_ident($1), $3, TL_OPTION_UPDATING | TL_OPTION_ALIAS, Lex->lock_option)) - YYABORT; + MYSQL_YYABORT; } | ident '.' ident opt_wild opt_table_alias { @@ -6741,7 +6808,7 @@ table_wild_one: TL_OPTION_UPDATING | TL_OPTION_ALIAS, Lex->lock_option)) - YYABORT; + MYSQL_YYABORT; } ; @@ -6796,7 +6863,7 @@ show_param: lex->sql_command= SQLCOM_SELECT; lex->orig_sql_command= SQLCOM_SHOW_DATABASES; if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA)) - YYABORT; + MYSQL_YYABORT; } | opt_full TABLES opt_db wild_and_where { @@ -6805,7 +6872,7 @@ show_param: lex->orig_sql_command= SQLCOM_SHOW_TABLES; lex->select_lex.db= $3; if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES)) - YYABORT; + MYSQL_YYABORT; } | opt_full TRIGGERS_SYM opt_db wild_and_where { @@ -6814,7 +6881,7 @@ show_param: lex->orig_sql_command= SQLCOM_SHOW_TRIGGERS; lex->select_lex.db= $3; if (prepare_schema_table(YYTHD, lex, 0, SCH_TRIGGERS)) - YYABORT; + MYSQL_YYABORT; } | TABLE_SYM STATUS_SYM opt_db wild_and_where { @@ -6823,7 +6890,7 @@ show_param: lex->orig_sql_command= SQLCOM_SHOW_TABLE_STATUS; lex->select_lex.db= $3; if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES)) - YYABORT; + MYSQL_YYABORT; } | OPEN_SYM TABLES opt_db wild_and_where { @@ -6832,7 +6899,7 @@ show_param: lex->orig_sql_command= SQLCOM_SHOW_OPEN_TABLES; lex->select_lex.db= $3; if (prepare_schema_table(YYTHD, lex, 0, SCH_OPEN_TABLES)) - YYABORT; + MYSQL_YYABORT; } | ENGINE_SYM storage_engines { Lex->create_info.db_type= $2; } @@ -6845,7 +6912,7 @@ show_param: if ($5) $4->change_db($5); if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS)) - YYABORT; + MYSQL_YYABORT; } | NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ TEXT_STRING_sys AND_SYM MASTER_LOG_POS_SYM EQ ulonglong_num @@ -6878,7 +6945,7 @@ show_param: if ($4) $3->change_db($4); if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS)) - YYABORT; + MYSQL_YYABORT; } | COLUMN_SYM TYPES_SYM { @@ -6916,7 +6983,7 @@ show_param: lex->orig_sql_command= SQLCOM_SHOW_STATUS; lex->option_type= $1; if (prepare_schema_table(YYTHD, lex, 0, SCH_STATUS)) - YYABORT; + MYSQL_YYABORT; } | INNOBASE_SYM STATUS_SYM { Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS; WARN_DEPRECATED("SHOW INNODB STATUS", "SHOW ENGINE INNODB STATUS"); } @@ -6931,7 +6998,7 @@ show_param: lex->orig_sql_command= SQLCOM_SHOW_VARIABLES; lex->option_type= $1; if (prepare_schema_table(YYTHD, lex, 0, SCH_VARIABLES)) - YYABORT; + MYSQL_YYABORT; } | charset wild_and_where { @@ -6939,7 +7006,7 @@ show_param: lex->sql_command= SQLCOM_SELECT; lex->orig_sql_command= SQLCOM_SHOW_CHARSETS; if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS)) - YYABORT; + MYSQL_YYABORT; } | COLLATION_SYM wild_and_where { @@ -6947,7 +7014,7 @@ show_param: lex->sql_command= SQLCOM_SELECT; lex->orig_sql_command= SQLCOM_SHOW_COLLATIONS; if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS)) - YYABORT; + MYSQL_YYABORT; } | BERKELEY_DB_SYM LOGS_SYM { Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS"); } @@ -6959,7 +7026,7 @@ show_param: lex->sql_command= SQLCOM_SHOW_GRANTS; LEX_USER *curr_user; if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user)))) - YYABORT; + MYSQL_YYABORT; bzero(curr_user, sizeof(st_lex_user)); lex->grant_user= curr_user; } @@ -6981,7 +7048,7 @@ show_param: LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL,0)) - YYABORT; + MYSQL_YYABORT; lex->only_view= 0; } | CREATE VIEW_SYM table_ident @@ -6989,7 +7056,7 @@ show_param: LEX *lex= Lex; lex->sql_command = SQLCOM_SHOW_CREATE; if (!lex->select_lex.add_table_to_list(YYTHD, $3, NULL, 0)) - YYABORT; + MYSQL_YYABORT; lex->only_view= 1; } | MASTER_SYM STATUS_SYM @@ -7020,9 +7087,9 @@ show_param: lex->sql_command= SQLCOM_SELECT; lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC; if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ)) - YYABORT; + MYSQL_YYABORT; if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) - YYABORT; + MYSQL_YYABORT; } | FUNCTION_SYM STATUS_SYM wild_and_where { @@ -7030,15 +7097,15 @@ show_param: lex->sql_command= SQLCOM_SELECT; lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC; if (!sp_add_to_query_tables(YYTHD, lex, "mysql", "proc", TL_READ)) - YYABORT; + MYSQL_YYABORT; if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES)) - YYABORT; + MYSQL_YYABORT; } | PROCEDURE CODE_SYM sp_name { #ifdef DBUG_OFF - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; #else Lex->sql_command= SQLCOM_SHOW_PROC_CODE; Lex->spname= $3; @@ -7047,8 +7114,8 @@ show_param: | FUNCTION_SYM CODE_SYM sp_name { #ifdef DBUG_OFF - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; #else Lex->sql_command= SQLCOM_SHOW_FUNC_CODE; Lex->spname= $3; @@ -7068,7 +7135,7 @@ show_engine_param: break; default: my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS"); - YYABORT; + MYSQL_YYABORT; } } | LOGS_SYM @@ -7079,7 +7146,7 @@ show_engine_param: break; default: my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LOGS"); - YYABORT; + MYSQL_YYABORT; } }; @@ -7138,7 +7205,7 @@ describe: lex->select_lex.db= 0; lex->verbose= 0; if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS)) - YYABORT; + MYSQL_YYABORT; } opt_describe_column {} | describe_command opt_extended_describe @@ -7280,7 +7347,7 @@ load: LOAD DATA_SYM if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA"); - YYABORT; + MYSQL_YYABORT; } lex->fname_start= lex->ptr; } @@ -7293,14 +7360,14 @@ load: LOAD DATA_SYM if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD TABLE"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_LOAD_MASTER_TABLE; WARN_DEPRECATED("LOAD TABLE FROM MASTER", "mysqldump or future " "BACKUP/RESTORE DATABASE facility"); if (!Select->add_table_to_list(YYTHD, $3, NULL, TL_OPTION_UPDATING)) - YYABORT; + MYSQL_YYABORT; }; load_data: @@ -7313,7 +7380,7 @@ load_data: lex->duplicates= DUP_ERROR; lex->ignore= 0; if (!(lex->exchange= new sql_exchange($4.str, 0))) - YYABORT; + MYSQL_YYABORT; } opt_duplicate INTO { @@ -7325,7 +7392,7 @@ load_data: LEX *lex=Lex; if (!Select->add_table_to_list(YYTHD, $10, NULL, TL_OPTION_UPDATING, lex->lock_option)) - YYABORT; + MYSQL_YYABORT; lex->field_list.empty(); lex->update_list.empty(); lex->value_list.empty(); @@ -7504,13 +7571,13 @@ param_marker: if (! lex->parsing_options.allows_variable) { my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); - YYABORT; + MYSQL_YYABORT; } item= new Item_param((uint) (lex->tok_start - (uchar *) thd->query)); if (!($$= item) || lex->param_list.push_back(item)) { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); - YYABORT; + MYSQL_YYABORT; } } ; @@ -7576,7 +7643,7 @@ NUM_literal: $$= new Item_decimal($1.str, $1.length, YYTHD->charset()); if (YYTHD->net.report_error) { - YYABORT; + MYSQL_YYABORT; } } | FLOAT_NUM @@ -7584,7 +7651,7 @@ NUM_literal: $$ = new Item_float($1.str, $1.length); if (YYTHD->net.report_error) { - YYABORT; + MYSQL_YYABORT; } } ; @@ -7629,7 +7696,7 @@ simple_ident: if (! lex->parsing_options.allows_variable) { my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); - YYABORT; + MYSQL_YYABORT; } Item_splocal *splocal; @@ -7689,14 +7756,14 @@ simple_ident_q: !new_row) { my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT"); - YYABORT; + MYSQL_YYABORT; } if (lex->trg_chistics.event == TRG_EVENT_DELETE && new_row) { my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"); - YYABORT; + MYSQL_YYABORT; } DBUG_ASSERT(!new_row || @@ -7711,7 +7778,7 @@ simple_ident_q: $3.str, SELECT_ACL, read_only))) - YYABORT; + MYSQL_YYABORT; /* Let us add this item to list of all Item_trigger_field objects @@ -7782,13 +7849,13 @@ field_ident: if (my_strcasecmp(table_alias_charset, $1.str, table->db)) { my_error(ER_WRONG_DB_NAME, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } if (my_strcasecmp(table_alias_charset, $3.str, table->table_name)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $3.str); - YYABORT; + MYSQL_YYABORT; } $$=$5; } @@ -7798,7 +7865,7 @@ field_ident: if (my_strcasecmp(table_alias_charset, $1.str, table->alias)) { my_error(ER_WRONG_TABLE_NAME, MYF(0), $1.str); - YYABORT; + MYSQL_YYABORT; } $$=$3; } @@ -7830,7 +7897,7 @@ IDENT_sys: { my_error(ER_INVALID_CHARACTER_STRING, MYF(0), cs->csname, $1.str + wlen); - YYABORT; + MYSQL_YYABORT; } $$= $1; } @@ -7907,32 +7974,32 @@ user: { THD *thd= YYTHD; if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) - YYABORT; + MYSQL_YYABORT; $$->user = $1; $$->host.str= (char *) "%"; $$->host.length= 1; if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH)) - YYABORT; + MYSQL_YYABORT; } | ident_or_text '@' ident_or_text { THD *thd= YYTHD; if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) - YYABORT; + MYSQL_YYABORT; $$->user = $1; $$->host=$3; if (check_string_length(&$$->user, ER(ER_USERNAME), USERNAME_LENGTH) || check_string_length(&$$->host, ER(ER_HOSTNAME), HOSTNAME_LENGTH)) - YYABORT; + MYSQL_YYABORT; } | CURRENT_USER optional_braces { if (!($$=(LEX_USER*) YYTHD->alloc(sizeof(st_lex_user)))) - YYABORT; + MYSQL_YYABORT; /* empty LEX_USER means current_user and will be handled in the get_current_user() function @@ -8275,7 +8342,7 @@ option_type_value: if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont, lex))) - YYABORT; + MYSQL_YYABORT; /* Extract the query statement from the tokenizer. The @@ -8288,7 +8355,7 @@ option_type_value: qbuff.length= lex->tok_end - sp->m_tmp_query; if (!(qbuff.str= alloc_root(YYTHD->mem_root, qbuff.length + 5))) - YYABORT; + MYSQL_YYABORT; strmake(strmake(qbuff.str, "SET ", 4), (char *)sp->m_tmp_query, qbuff.length); @@ -8344,8 +8411,8 @@ sys_option_value: LINT_INIT(sp_fld); if ($1) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } if ($4) it= $4; @@ -8367,7 +8434,7 @@ sys_option_value: lex->spcont, trg_fld, it, lex))) - YYABORT; + MYSQL_YYABORT; /* Let us add this item to list of all Item_trigger_field @@ -8394,8 +8461,8 @@ sys_option_value: Item *it; if ($1) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } spv= ctx->find_variable(&$2.base_name); @@ -8451,9 +8518,9 @@ option_value: if (spc && spc->find_variable(&names)) my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str); else - yyerror(ER(ER_SYNTAX_ERROR)); + my_parse_error(ER(ER_SYNTAX_ERROR)); - YYABORT; + MYSQL_YYABORT; } | NAMES_SYM charset_name_or_default opt_collate { @@ -8464,7 +8531,7 @@ option_value: { my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0), $3->name, $2->csname); - YYABORT; + MYSQL_YYABORT; } lex->var_list.push_back(new set_var_collation_client($3,$3,$3)); } @@ -8481,10 +8548,10 @@ option_value: if (spc && spc->find_variable(&pw)) { my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str); - YYABORT; + MYSQL_YYABORT; } if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER)))) - YYABORT; + MYSQL_YYABORT; user->host=null_lex_str; user->user.str=thd->security_ctx->priv_user; thd->lex->var_list.push_back(new set_var_password(user, $3)); @@ -8508,7 +8575,7 @@ internal_variable_name: /* Not an SP local variable */ sys_var *tmp=find_sys_var($1.str, $1.length); if (!tmp) - YYABORT; + MYSQL_YYABORT; $$.var= tmp; $$.base_name= null_lex_str; /* @@ -8517,7 +8584,7 @@ internal_variable_name: */ if (tmp == &sys_time_zone && lex->add_time_zone_tables_to_query_tables(YYTHD)) - YYABORT; + MYSQL_YYABORT; else if (spc && tmp == &sys_autocommit) { /* @@ -8539,8 +8606,8 @@ internal_variable_name: LEX *lex= Lex; if (check_reserved_words(&$1)) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_TRIGGER && (!my_strcasecmp(system_charset_info, $1.str, "NEW") || @@ -8549,18 +8616,18 @@ internal_variable_name: if ($1.str[0]=='O' || $1.str[0]=='o') { my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", ""); - YYABORT; + MYSQL_YYABORT; } if (lex->trg_chistics.event == TRG_EVENT_DELETE) { my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE"); - YYABORT; + MYSQL_YYABORT; } if (lex->trg_chistics.action_time == TRG_ACTION_AFTER) { my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after "); - YYABORT; + MYSQL_YYABORT; } /* This special combination will denote field of NEW row */ $$.var= &trg_new_row_fake_var; @@ -8570,7 +8637,7 @@ internal_variable_name: { sys_var *tmp=find_sys_var($3.str, $3.length); if (!tmp) - YYABORT; + MYSQL_YYABORT; if (!tmp->is_struct()) my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str); $$.var= tmp; @@ -8581,7 +8648,7 @@ internal_variable_name: { sys_var *tmp=find_sys_var($3.str, $3.length); if (!tmp) - YYABORT; + MYSQL_YYABORT; if (!tmp->is_struct()) my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str); $$.var= tmp; @@ -8633,7 +8700,7 @@ lock: if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "LOCK"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command= SQLCOM_LOCK_TABLES; } @@ -8653,7 +8720,7 @@ table_lock: table_ident opt_table_alias lock_option { if (!Select->add_table_to_list(YYTHD, $1, $2, 0, (thr_lock_type) $3)) - YYABORT; + MYSQL_YYABORT; } ; @@ -8672,7 +8739,7 @@ unlock: if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "UNLOCK"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command= SQLCOM_UNLOCK_TABLES; } @@ -8692,11 +8759,11 @@ handler: if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_HA_OPEN; if (!lex->current_select->add_table_to_list(lex->thd, $2, $4, 0)) - YYABORT; + MYSQL_YYABORT; } | HANDLER_SYM table_ident_nodb CLOSE_SYM { @@ -8704,11 +8771,11 @@ handler: if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_HA_CLOSE; if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) - YYABORT; + MYSQL_YYABORT; } | HANDLER_SYM table_ident_nodb READ_SYM { @@ -8716,14 +8783,14 @@ handler: if (lex->sphead) { my_error(ER_SP_BADSTATEMENT, MYF(0), "HANDLER"); - YYABORT; + MYSQL_YYABORT; } lex->sql_command = SQLCOM_HA_READ; lex->ha_rkey_mode= HA_READ_KEY_EXACT; /* Avoid purify warnings */ lex->current_select->select_limit= new Item_int((int32) 1); lex->current_select->offset_limit= 0; if (!lex->current_select->add_table_to_list(lex->thd, $2, 0, 0)) - YYABORT; + MYSQL_YYABORT; } handler_read_or_scan where_clause opt_limit_clause {} ; @@ -8749,7 +8816,7 @@ handler_rkey_function: lex->ha_read_mode = RKEY; lex->ha_rkey_mode=$1; if (!(lex->insert_list = new List_item)) - YYABORT; + MYSQL_YYABORT; } '(' values ')' { } ; @@ -8781,8 +8848,8 @@ revoke_command: LEX *lex= Lex; if (lex->columns.elements) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_REVOKE; lex->type= TYPE_ENUM_FUNCTION; @@ -8794,8 +8861,8 @@ revoke_command: LEX *lex= Lex; if (lex->columns.elements) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_REVOKE; lex->type= TYPE_ENUM_PROCEDURE; @@ -8827,8 +8894,8 @@ grant_command: LEX *lex= Lex; if (lex->columns.elements) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_GRANT; lex->type= TYPE_ENUM_FUNCTION; @@ -8840,8 +8907,8 @@ grant_command: LEX *lex= Lex; if (lex->columns.elements) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } lex->sql_command= SQLCOM_GRANT; lex->type= TYPE_ENUM_PROCEDURE; @@ -8918,7 +8985,7 @@ require_list_element: if (lex->x509_subject) { my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT"); - YYABORT; + MYSQL_YYABORT; } lex->x509_subject=$2.str; } @@ -8928,7 +8995,7 @@ require_list_element: if (lex->x509_issuer) { my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER"); - YYABORT; + MYSQL_YYABORT; } lex->x509_issuer=$2.str; } @@ -8938,7 +9005,7 @@ require_list_element: if (lex->ssl_cipher) { my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER"); - YYABORT; + MYSQL_YYABORT; } lex->ssl_cipher=$2.str; } @@ -8950,14 +9017,14 @@ grant_ident: LEX *lex= Lex; THD *thd= lex->thd; if (thd->copy_db_to(&lex->current_select->db, NULL)) - YYABORT; + MYSQL_YYABORT; if (lex->grant == GLOBAL_ACLS) lex->grant = DB_ACLS & ~GRANT_ACL; else if (lex->columns.elements) { my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0)); - YYABORT; + MYSQL_YYABORT; } } | ident '.' '*' @@ -8970,7 +9037,7 @@ grant_ident: { my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0)); - YYABORT; + MYSQL_YYABORT; } } | '*' '.' '*' @@ -8983,14 +9050,14 @@ grant_ident: { my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0)); - YYABORT; + MYSQL_YYABORT; } } | table_ident { LEX *lex=Lex; if (!lex->current_select->add_table_to_list(lex->thd, $1,NULL,0)) - YYABORT; + MYSQL_YYABORT; if (lex->grant == GLOBAL_ACLS) lex->grant = TABLE_ACLS & ~GRANT_ACL; } @@ -8998,21 +9065,21 @@ grant_ident: user_list: - user { if (Lex->users_list.push_back($1)) YYABORT;} + user { if (Lex->users_list.push_back($1)) MYSQL_YYABORT;} | user_list ',' user { if (Lex->users_list.push_back($3)) - YYABORT; + MYSQL_YYABORT; } ; grant_list: - grant_user { if (Lex->users_list.push_back($1)) YYABORT;} + grant_user { if (Lex->users_list.push_back($1)) MYSQL_YYABORT;} | grant_list ',' grant_user { if (Lex->users_list.push_back($3)) - YYABORT; + MYSQL_YYABORT; } ; @@ -9235,17 +9302,17 @@ union_list: { /* Only the last SELECT can have INTO...... */ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO"); - YYABORT; + MYSQL_YYABORT; } if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } /* This counter shouldn't be incremented for UNION parts */ Lex->nest_level--; if (mysql_new_select(lex, 0)) - YYABORT; + MYSQL_YYABORT; mysql_init_select(lex); lex->current_select->linkage=UNION_TYPE; if ($2) /* UNION DISTINCT - remember position */ @@ -9339,8 +9406,8 @@ subselect_start: if (lex->sql_command == (int)SQLCOM_HA_READ || lex->sql_command == (int)SQLCOM_KILL) { - yyerror(ER(ER_SYNTAX_ERROR)); - YYABORT; + my_parse_error(ER(ER_SYNTAX_ERROR)); + MYSQL_YYABORT; } /* we are making a "derived table" for the parenthesis @@ -9350,7 +9417,7 @@ subselect_start: SELECT * FROM ((SELECT ...) UNION ...) */ if (mysql_new_select(Lex, 1)) - YYABORT; + MYSQL_YYABORT; }; subselect_end: @@ -9468,7 +9535,7 @@ view_tail: lex->sql_command= SQLCOM_CREATE_VIEW; /* first table in list is target VIEW name */ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, TL_OPTION_UPDATING)) - YYABORT; + MYSQL_YYABORT; } view_list_opt AS view_select view_check_option {} @@ -9559,11 +9626,11 @@ trigger_tail: if (lex->sphead) { my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER"); - YYABORT; + MYSQL_YYABORT; } if (!(sp= new sp_head())) - YYABORT; + MYSQL_YYABORT; sp->reset_thd_mem_root(YYTHD); sp->init(lex); sp->init_sp_name(YYTHD, $3); @@ -9602,7 +9669,7 @@ trigger_tail: sp->restore_thd_mem_root(YYTHD); if (sp->is_not_allowed_in_function("trigger")) - YYABORT; + MYSQL_YYABORT; /* We have to do it after parsing trigger body, because some of @@ -9613,7 +9680,7 @@ trigger_tail: (LEX_STRING*) 0, TL_OPTION_UPDATING, TL_IGNORE)) - YYABORT; + MYSQL_YYABORT; } ; @@ -9641,7 +9708,7 @@ sp_tail: if (lex->sphead) { my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE"); - YYABORT; + MYSQL_YYABORT; } lex->stmt_definition_begin= $2; @@ -9727,23 +9794,23 @@ xa: XA_SYM begin_or_start xid opt_join_or_resume xid: text_string { - YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE); + MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE); if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID)))) - YYABORT; + MYSQL_YYABORT; Lex->xid->set(1L, $1->ptr(), $1->length(), 0, 0); } | text_string ',' text_string { - YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); + MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID)))) - YYABORT; + MYSQL_YYABORT; Lex->xid->set(1L, $1->ptr(), $1->length(), $3->ptr(), $3->length()); } | text_string ',' text_string ',' ulong_num { - YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); + MYSQL_YYABORT_UNLESS($1->length() <= MAXGTRIDSIZE && $3->length() <= MAXBQUALSIZE); if (!(Lex->xid=(XID *)YYTHD->alloc(sizeof(XID)))) - YYABORT; + MYSQL_YYABORT; Lex->xid->set($5, $1->ptr(), $1->length(), $3->ptr(), $3->length()); } ; From 4d6e16f284d9699307461b0081269bf4ce8be87e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Mar 2007 14:03:44 +0300 Subject: [PATCH 52/55] A fix for the windows build (harmless warning). sql/sql_lex.cc: A fix for the windows build. --- sql/sql_lex.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d95d2733dcd..4c0ab7a8e54 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1672,7 +1672,7 @@ void st_lex::cleanup_lex_after_parse_error(THD *thd) Sic: we must nullify the member of the main lex, not the current one that will be thrown away */ - if (thd->lex->sphead); + if (thd->lex->sphead) { delete thd->lex->sphead; thd->lex->sphead= NULL; From 83def161de98f4eaaccf6c83b71644ef44cc384d Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Mar 2007 10:46:38 -0500 Subject: [PATCH 53/55] Bug#25222 Win32 HANDLE leak in my_sopen() - When attempting to associate a Windows File handle to a C run-time file handle there is an upper bound. Once reached, the newly created handles will cause a memory leak since they are not properly associated with a handle that can later be cleaned up. mysys/my_open.c: Bug#25222 Win32 HANDLE leak in my_sopen() - Check for failure in _open_osfhandle and close allocated HANDLE on failure. --- mysys/my_open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mysys/my_open.c b/mysys/my_open.c index 2ba84f92ac2..9e1da1d3f07 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -345,7 +345,12 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode) return -1; /* return error to caller */ } - fh= _open_osfhandle((intptr_t)osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT)); + if ((fh= _open_osfhandle((intptr_t)osfh, + oflag & (_O_APPEND | _O_RDONLY | _O_TEXT))) == -1) + { + _dosmaperr(GetLastError()); /* map error */ + CloseHandle(osfh); + } return fh; /* return handle */ } From 5501a2915a8b8f3b4598dd187cbe1acdbbdf2fd2 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 7 Mar 2007 23:49:46 +0100 Subject: [PATCH 54/55] update test results for bdb_gis after merge of fix for b26038 --- mysql-test/r/bdb_gis.result | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/bdb_gis.result b/mysql-test/r/bdb_gis.result index c0e1682e485..512d681ff32 100644 --- a/mysql-test/r/bdb_gis.result +++ b/mysql-test/r/bdb_gis.result @@ -446,7 +446,7 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert IGNORE into t1 values ('Garbage'); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field drop table t1; -create table t1 (fl geometry); +create table t1 (fl geometry not null); insert into t1 values (1); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (1.11); @@ -454,5 +454,5 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values ("qwerty"); ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field insert into t1 values (pointfromtext('point(1,1)')); -ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field +ERROR 23000: Column 'fl' cannot be null drop table t1; From 0a5780bc03a8876851fbaa4a0cfb8caa680c0535 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 8 Mar 2007 08:15:30 +0100 Subject: [PATCH 55/55] comp_err.c: return ha_checksum from checksum_format_specifier() - more correct, avoid a compiler warning extra/comp_err.c: return ha_checksum from checksum_format_specifier() - more correct, avoid a compiler warning --- extra/comp_err.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/comp_err.c b/extra/comp_err.c index e5f7ed8d0ea..7cc4a0aa43f 100644 --- a/extra/comp_err.c +++ b/extra/comp_err.c @@ -637,9 +637,9 @@ static struct message *find_message(struct errors *err, const char *lang, either. */ -static char checksum_format_specifier(const char* msg) +static ha_checksum checksum_format_specifier(const char* msg) { - char chksum= 0; + ha_checksum chksum= 0; const char* p= msg; const char* start= 0; int num_format_specifiers= 0;