Fixed following problems:
--Bug#52157 various crashes and assertions with multi-table update, stored function --Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb --Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846 --Bug#57352 valgrind warnings when creating view --Recently discovered problem when a nested materialized derived table is used before being populated and it leads to incorrect result We have several modes when we should disable subquery evaluation. The reasons for disabling are different. It could be uselessness of the evaluation as in case of 'CREATE VIEW' or 'PREPARE stmt', or we should disable subquery evaluation if tables are not locked yet as it happens in bug#54475, or too early evaluation of subqueries can lead to wrong result as it happened in Bug#19077. Main problem is that if subquery items are treated as const they are evaluated in ::fix_fields(), ::fix_length_and_dec() of the parental items as a lot of these methods have Item::val_...() calls inside. We have to make subqueries non-const to prevent unnecessary subquery evaluation. At the moment we have different methods for this. Here is a list of these modes: 1. PREPARE stmt; We use UNCACHEABLE_PREPARE flag. It is set during parsing in sql_parse.cc, mysql_new_select() for each SELECT_LEX object and cleared at the end of PREPARE in sql_prepare.cc, init_stmt_after_parse(). If this flag is set subquery becomes non-const and evaluation does not happen. 2. CREATE|ALTER VIEW, SHOW CREATE VIEW, I_S tables which process FRM files We use LEX::view_prepare_mode field. We set it before view preparation and check this flag in ::fix_fields(), ::fix_length_and_dec(). Some bugs are fixed using this approach, some are not(Bug#57352, Bug#57703). The problem here is that we have a lot of ::fix_fields(), ::fix_length_and_dec() where we use Item::val_...() calls for const items. 3. Derived tables with subquery = wrong result(Bug19077) The reason of this bug is too early subquery evaluation. It was fixed by adding Item::with_subselect field The check of this field in appropriate places prevents const item evaluation if the item have subquery. The fix for Bug19077 fixes only the problem with convert_constant_item() function and does not cover other places(::fix_fields(), ::fix_length_and_dec() again) where subqueries could be evaluated. Example: CREATE TABLE t1 (i INT, j BIGINT); INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2); SELECT * FROM (SELECT MIN(i) FROM t1 WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3; DROP TABLE t1; 4. Derived tables with subquery where subquery is evaluated before table locking(Bug#54475, Bug#52157) Suggested solution is following: -Introduce new field LEX::context_analysis_only with the following possible flags: #define CONTEXT_ANALYSIS_ONLY_PREPARE 1 #define CONTEXT_ANALYSIS_ONLY_VIEW 2 #define CONTEXT_ANALYSIS_ONLY_DERIVED 4 -Set/clean these flags when we perform context analysis operation -Item_subselect::const_item() returns result depending on LEX::context_analysis_only. If context_analysis_only is set then we return FALSE that means that subquery is non-const. As all subquery types are wrapped by Item_subselect it allow as to make subquery non-const when it's necessary. mysql-test/r/derived.result: test case mysql-test/r/multi_update.result: test case mysql-test/r/view.result: test case mysql-test/suite/innodb/r/innodb_multi_update.result: test case mysql-test/suite/innodb/t/innodb_multi_update.test: test case mysql-test/suite/innodb_plugin/r/innodb_multi_update.result: test case mysql-test/suite/innodb_plugin/t/innodb_multi_update.test: test case mysql-test/t/derived.test: test case mysql-test/t/multi_update.test: test case mysql-test/t/view.test: test case sql/item.cc: --removed unnecessary code sql/item_cmpfunc.cc: --removed unnecessary checks --THD::is_context_analysis_only() is replaced with LEX::is_ps_or_view_context_analysis() sql/item_func.cc: --refactored context analysis checks sql/item_row.cc: --removed unnecessary checks sql/item_subselect.cc: --removed unnecessary code --added DBUG_ASSERT into Item_subselect::exec() which asserts that subquery execution can not happen if LEX::context_analysis_only is set, i.e. at context analysis stage. --Item_subselect::const_item() Return FALSE if LEX::context_analysis_only is set. It prevents subquery evaluation in ::fix_fields & ::fix_length_and_dec at context analysis stage. sql/item_subselect.h: --removed unnecessary code sql/mysql_priv.h: --Added new set of flags. sql/sql_class.h: --removed unnecessary code sql/sql_derived.cc: --added LEX::context_analysis_only analysis intialization/cleanup sql/sql_lex.cc: --init LEX::context_analysis_only field sql/sql_lex.h: --New LEX::context_analysis_only field sql/sql_parse.cc: --removed unnecessary code sql/sql_prepare.cc: --removed unnecessary code --added LEX::context_analysis_only analysis intialization/cleanup sql/sql_select.cc: --refactored context analysis checks sql/sql_show.cc: --added LEX::context_analysis_only analysis intialization/cleanup sql/sql_view.cc: --added LEX::context_analysis_only analysis intialization/cleanup
This commit is contained in:
parent
fda6290041
commit
fcb83cbf15
@ -400,4 +400,15 @@ SELECT 0 FROM
|
||||
(SELECT 0) t61;
|
||||
0
|
||||
0
|
||||
#
|
||||
# A nested materialized derived table is used before being populated.
|
||||
# (addon for bug#19077)
|
||||
#
|
||||
CREATE TABLE t1 (i INT, j BIGINT);
|
||||
INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
|
||||
SELECT * FROM (SELECT MIN(i) FROM t1
|
||||
WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3;
|
||||
MIN(i)
|
||||
1
|
||||
DROP TABLE t1;
|
||||
# End of 5.0 tests
|
||||
|
@ -659,4 +659,15 @@ Error 1242 Subquery returns more than 1 row
|
||||
Error 1242 Subquery returns more than 1 row
|
||||
DROP TABLE t1, t2, t3;
|
||||
SET SESSION sql_safe_updates = DEFAULT;
|
||||
#
|
||||
# Bug#52157 various crashes and assertions with multi-table update, stored function
|
||||
#
|
||||
CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
|
||||
CREATE TABLE t1 (f1 DATE);
|
||||
INSERT INTO t1 VALUES('2001-01-01');
|
||||
UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect datetime value: '1'
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE t1;
|
||||
end of tests
|
||||
|
@ -3884,6 +3884,19 @@ CREATE VIEW v1 AS SELECT 1 from t1
|
||||
WHERE t1.b <=> (SELECT a FROM t1 WHERE a < SOME(SELECT '1'));
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846
|
||||
#
|
||||
CREATE TABLE t1(a int);
|
||||
CREATE VIEW v1 AS SELECT 1 FROM t1 GROUP BY
|
||||
SUBSTRING(1 FROM (SELECT 3 FROM t1 WHERE a >= ANY(SELECT 1)));
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#57352 valgrind warnings when creating view
|
||||
#
|
||||
CREATE VIEW v1 AS SELECT 1 IN (1 LIKE 2,0) AS f;
|
||||
DROP VIEW v1;
|
||||
# -----------------------------------------------------------------
|
||||
# -- End of 5.1 tests.
|
||||
# -----------------------------------------------------------------
|
||||
|
@ -74,3 +74,11 @@ a b
|
||||
4 14
|
||||
5 15
|
||||
drop table bug38999_1,bug38999_2;
|
||||
#
|
||||
# Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
|
||||
#
|
||||
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
DROP TABLE t1;
|
||||
|
@ -27,3 +27,14 @@ select * from bug38999_1;
|
||||
select * from bug38999_2;
|
||||
|
||||
drop table bug38999_1,bug38999_2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
|
||||
--echo #
|
||||
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
--error ER_OPERAND_COLUMNS
|
||||
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -74,3 +74,11 @@ a b
|
||||
4 14
|
||||
5 15
|
||||
drop table bug38999_1,bug38999_2;
|
||||
#
|
||||
# Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
|
||||
#
|
||||
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
|
||||
ERROR 21000: Operand should contain 1 column(s)
|
||||
DROP TABLE t1;
|
||||
|
@ -27,3 +27,14 @@ select * from bug38999_1;
|
||||
select * from bug38999_2;
|
||||
|
||||
drop table bug38999_1,bug38999_2;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
|
||||
--echo #
|
||||
CREATE TABLE t1(f1 INT) ENGINE=INNODB;
|
||||
INSERT INTO t1 VALUES(1);
|
||||
--error ER_OPERAND_COLUMNS
|
||||
UPDATE (SELECT ((SELECT 1 FROM t1), 1) FROM t1 WHERE (SELECT 1 FROM t1)) x, (SELECT 1) AS d SET d.f1 = 1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
@ -301,4 +301,15 @@ SELECT 0 FROM
|
||||
(SELECT 0) t56, (SELECT 0) t57, (SELECT 0) t58, (SELECT 0) t59, (SELECT 0) t60,
|
||||
(SELECT 0) t61; # 61 == MAX_TABLES
|
||||
|
||||
--echo #
|
||||
--echo # A nested materialized derived table is used before being populated.
|
||||
--echo # (addon for bug#19077)
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (i INT, j BIGINT);
|
||||
INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
|
||||
SELECT * FROM (SELECT MIN(i) FROM t1
|
||||
WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo # End of 5.0 tests
|
||||
|
@ -673,4 +673,15 @@ SET t3.a = 0;
|
||||
DROP TABLE t1, t2, t3;
|
||||
SET SESSION sql_safe_updates = DEFAULT;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#52157 various crashes and assertions with multi-table update, stored function
|
||||
--echo #
|
||||
|
||||
CREATE FUNCTION f1 () RETURNS BLOB RETURN 1;
|
||||
CREATE TABLE t1 (f1 DATE);
|
||||
INSERT INTO t1 VALUES('2001-01-01');
|
||||
UPDATE (SELECT 1 FROM t1 WHERE f1 = (SELECT f1() FROM t1)) x, t1 SET f1 = 1;
|
||||
DROP FUNCTION f1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo end of tests
|
||||
|
@ -3925,6 +3925,22 @@ WHERE t1.b <=> (SELECT a FROM t1 WHERE a < SOME(SELECT '1'));
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1(a int);
|
||||
CREATE VIEW v1 AS SELECT 1 FROM t1 GROUP BY
|
||||
SUBSTRING(1 FROM (SELECT 3 FROM t1 WHERE a >= ANY(SELECT 1)));
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#57352 valgrind warnings when creating view
|
||||
--echo #
|
||||
CREATE VIEW v1 AS SELECT 1 IN (1 LIKE 2,0) AS f;
|
||||
DROP VIEW v1;
|
||||
|
||||
--echo # -----------------------------------------------------------------
|
||||
--echo # -- End of 5.1 tests.
|
||||
--echo # -----------------------------------------------------------------
|
||||
|
11
sql/item.cc
11
sql/item.cc
@ -1712,16 +1712,7 @@ bool agg_item_set_converter(DTCollation &coll, const char *fname,
|
||||
|
||||
if (!(conv= (*arg)->safe_charset_converter(coll.collation)) &&
|
||||
((*arg)->collation.repertoire == MY_REPERTOIRE_ASCII))
|
||||
{
|
||||
/*
|
||||
We should disable const subselect item evaluation because
|
||||
subselect transformation does not happen in view_prepare_mode
|
||||
and thus val_...() methods can not be called for const items.
|
||||
*/
|
||||
bool resolve_const= ((*arg)->type() == Item::SUBSELECT_ITEM &&
|
||||
thd->lex->view_prepare_mode) ? FALSE : TRUE;
|
||||
conv= new Item_func_conv_charset(*arg, coll.collation, resolve_const);
|
||||
}
|
||||
conv= new Item_func_conv_charset(*arg, coll.collation, 1);
|
||||
|
||||
if (!conv)
|
||||
{
|
||||
|
@ -401,7 +401,7 @@ static bool convert_constant_item(THD *thd, Item_field *field_item,
|
||||
Field *field= field_item->field;
|
||||
int result= 0;
|
||||
|
||||
if (!(*item)->with_subselect && (*item)->const_item())
|
||||
if ((*item)->const_item())
|
||||
{
|
||||
TABLE *table= field->table;
|
||||
ulong orig_sql_mode= thd->variables.sql_mode;
|
||||
@ -497,7 +497,7 @@ void Item_bool_func2::fix_length_and_dec()
|
||||
}
|
||||
|
||||
thd= current_thd;
|
||||
if (!thd->is_context_analysis_only())
|
||||
if (!thd->lex->is_ps_or_view_context_analysis())
|
||||
{
|
||||
if (args[0]->real_item()->type() == FIELD_ITEM)
|
||||
{
|
||||
@ -801,7 +801,7 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
|
||||
confuse storage engines since in context analysis mode tables
|
||||
aren't locked.
|
||||
*/
|
||||
if (!thd->is_context_analysis_only() &&
|
||||
if (!thd->lex->is_ps_or_view_context_analysis() &&
|
||||
cmp_type != CMP_DATE_WITH_DATE && str_arg->const_item() &&
|
||||
(str_arg->type() != Item::FUNC_ITEM ||
|
||||
((Item_func*)str_arg)->functype() != Item_func::GUSERVAR_FUNC))
|
||||
@ -1027,7 +1027,7 @@ Item** Arg_comparator::cache_converted_constant(THD *thd_arg, Item **value,
|
||||
Item_result type)
|
||||
{
|
||||
/* Don't need cache if doing context analysis only. */
|
||||
if (!thd_arg->is_context_analysis_only() &&
|
||||
if (!thd->lex->is_ps_or_view_context_analysis() &&
|
||||
(*value)->const_item() && type != (*value)->result_type())
|
||||
{
|
||||
Item_cache *cache= Item_cache::get_cache(*value, type);
|
||||
@ -4686,7 +4686,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (escape_item->const_item() && !thd->lex->view_prepare_mode)
|
||||
if (escape_item->const_item())
|
||||
{
|
||||
/* If we are on execution stage */
|
||||
String *escape_str= escape_item->val_str(&cmp.value1);
|
||||
|
@ -6066,7 +6066,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
||||
if (res)
|
||||
DBUG_RETURN(res);
|
||||
|
||||
if (thd->lex->view_prepare_mode)
|
||||
if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
|
||||
{
|
||||
/*
|
||||
Here we check privileges of the stored routine only during view
|
||||
|
@ -73,12 +73,8 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
|
||||
used_tables_cache |= item->used_tables();
|
||||
const_item_cache&= item->const_item() && !with_null;
|
||||
not_null_tables_cache|= item->not_null_tables();
|
||||
/*
|
||||
Some subqueries transformations aren't done in the view_prepare_mode thus
|
||||
is_null() will fail. So we skip is_null() calculation for CREATE VIEW as
|
||||
not necessary.
|
||||
*/
|
||||
if (const_item_cache && !thd->lex->view_prepare_mode)
|
||||
|
||||
if (const_item_cache)
|
||||
{
|
||||
if (item->cols() > 1)
|
||||
with_null|= item->null_inside();
|
||||
|
@ -123,20 +123,6 @@ void Item_subselect::cleanup()
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
We cannot use generic Item::safe_charset_converter() because
|
||||
Subselect transformation does not happen in view_prepare_mode
|
||||
and thus we can not evaluate val_...() for const items.
|
||||
*/
|
||||
|
||||
Item *Item_subselect::safe_charset_converter(CHARSET_INFO *tocs)
|
||||
{
|
||||
Item_func_conv_charset *conv=
|
||||
new Item_func_conv_charset(this, tocs, thd->lex->view_prepare_mode ? 0 : 1);
|
||||
return conv->safe ? conv : NULL;
|
||||
}
|
||||
|
||||
|
||||
void Item_singlerow_subselect::cleanup()
|
||||
{
|
||||
DBUG_ENTER("Item_singlerow_subselect::cleanup");
|
||||
@ -271,6 +257,7 @@ bool Item_subselect::exec()
|
||||
if (thd->is_error() || thd->killed)
|
||||
return 1;
|
||||
|
||||
DBUG_ASSERT(!thd->lex->context_analysis_only);
|
||||
/*
|
||||
Simulate a failure in sub-query execution. Used to test e.g.
|
||||
out of memory or query being killed conditions.
|
||||
@ -307,7 +294,7 @@ table_map Item_subselect::used_tables() const
|
||||
|
||||
bool Item_subselect::const_item() const
|
||||
{
|
||||
return const_item_cache;
|
||||
return thd->lex->context_analysis_only ? FALSE : const_item_cache;
|
||||
}
|
||||
|
||||
Item *Item_subselect::get_tmp_table_item(THD *thd_arg)
|
||||
@ -1638,7 +1625,8 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
|
||||
{
|
||||
bool result = 0;
|
||||
|
||||
if (thd_arg->lex->view_prepare_mode && left_expr && !left_expr->fixed)
|
||||
if ((thd_arg->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) &&
|
||||
left_expr && !left_expr->fixed)
|
||||
result = left_expr->fix_fields(thd_arg, &left_expr);
|
||||
|
||||
return result || Item_subselect::fix_fields(thd_arg, ref);
|
||||
|
@ -126,7 +126,6 @@ public:
|
||||
virtual void reset_value_registration() {}
|
||||
enum_parsing_place place() { return parsing_place; }
|
||||
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
|
||||
Item *safe_charset_converter(CHARSET_INFO *tocs);
|
||||
|
||||
/**
|
||||
Get the SELECT_LEX structure associated with this Item.
|
||||
|
@ -566,17 +566,42 @@ protected:
|
||||
|
||||
#define MY_CHARSET_BIN_MB_MAXLEN 1
|
||||
|
||||
/*
|
||||
Flags below are set when we perform
|
||||
context analysis of the statement and make
|
||||
subqueries non-const. It prevents subquery
|
||||
evaluation at context analysis stage.
|
||||
*/
|
||||
|
||||
/*
|
||||
Don't evaluate this subquery during statement prepare even if
|
||||
it's a constant one. The flag is switched off in the end of
|
||||
mysqld_stmt_prepare.
|
||||
*/
|
||||
#define CONTEXT_ANALYSIS_ONLY_PREPARE 1
|
||||
/*
|
||||
Special JOIN::prepare mode: changing of query is prohibited.
|
||||
When creating a view, we need to just check its syntax omitting
|
||||
any optimizations: afterwards definition of the view will be
|
||||
reconstructed by means of ::print() methods and written to
|
||||
to an .frm file. We need this definition to stay untouched.
|
||||
*/
|
||||
#define CONTEXT_ANALYSIS_ONLY_VIEW 2
|
||||
/*
|
||||
Don't evaluate this subquery during derived table prepare even if
|
||||
it's a constant one.
|
||||
*/
|
||||
#define CONTEXT_ANALYSIS_ONLY_DERIVED 4
|
||||
|
||||
// uncachable cause
|
||||
#define UNCACHEABLE_DEPENDENT 1
|
||||
#define UNCACHEABLE_RAND 2
|
||||
#define UNCACHEABLE_SIDEEFFECT 4
|
||||
/// forcing to save JOIN for explain
|
||||
#define UNCACHEABLE_EXPLAIN 8
|
||||
/** Don't evaluate subqueries in prepare even if they're not correlated */
|
||||
#define UNCACHEABLE_PREPARE 16
|
||||
/* For uncorrelated SELECT in an UNION with some correlated SELECTs */
|
||||
#define UNCACHEABLE_UNITED 32
|
||||
#define UNCACHEABLE_CHECKOPTION 64
|
||||
#define UNCACHEABLE_UNITED 16
|
||||
#define UNCACHEABLE_CHECKOPTION 32
|
||||
|
||||
/* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */
|
||||
#define UNDEF_POS (-1)
|
||||
|
@ -2180,8 +2180,6 @@ public:
|
||||
(variables.sql_mode & MODE_STRICT_ALL_TABLES)));
|
||||
}
|
||||
void set_status_var_init();
|
||||
bool is_context_analysis_only()
|
||||
{ return stmt_arena->is_stmt_prepare() || lex->view_prepare_mode; }
|
||||
void reset_n_backup_open_tables_state(Open_tables_state *backup);
|
||||
void restore_backup_open_tables_state(Open_tables_state *backup);
|
||||
void reset_sub_statement_state(Sub_statement_state *backup, uint new_state);
|
||||
|
@ -147,10 +147,11 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
|
||||
if (!(derived_result= new select_union))
|
||||
DBUG_RETURN(TRUE); // out of memory
|
||||
|
||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
|
||||
// st_select_lex_unit::prepare correctly work for single select
|
||||
if ((res= unit->prepare(thd, derived_result, 0)))
|
||||
goto exit;
|
||||
|
||||
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
|
||||
if ((res= check_duplicate_names(unit->types, 0)))
|
||||
goto exit;
|
||||
|
||||
|
@ -305,7 +305,7 @@ void lex_start(THD *thd)
|
||||
lex->select_lex.group_list.empty();
|
||||
lex->describe= 0;
|
||||
lex->subqueries= FALSE;
|
||||
lex->view_prepare_mode= FALSE;
|
||||
lex->context_analysis_only= 0;
|
||||
lex->derived_tables= 0;
|
||||
lex->lock_option= TL_READ;
|
||||
lex->safe_to_cache_query= 1;
|
||||
|
@ -1715,14 +1715,8 @@ typedef struct st_lex : public Query_tables_list
|
||||
bool verbose, no_write_to_binlog;
|
||||
|
||||
bool tx_chain, tx_release;
|
||||
/*
|
||||
Special JOIN::prepare mode: changing of query is prohibited.
|
||||
When creating a view, we need to just check its syntax omitting
|
||||
any optimizations: afterwards definition of the view will be
|
||||
reconstructed by means of ::print() methods and written to
|
||||
to an .frm file. We need this definition to stay untouched.
|
||||
*/
|
||||
bool view_prepare_mode;
|
||||
|
||||
uint8 context_analysis_only;
|
||||
bool safe_to_cache_query;
|
||||
bool subqueries, ignore;
|
||||
st_parsing_options parsing_options;
|
||||
@ -1843,6 +1837,13 @@ typedef struct st_lex : public Query_tables_list
|
||||
delete_dynamic(&plugins);
|
||||
}
|
||||
|
||||
inline bool is_ps_or_view_context_analysis()
|
||||
{
|
||||
return (context_analysis_only &
|
||||
(CONTEXT_ANALYSIS_ONLY_PREPARE |
|
||||
CONTEXT_ANALYSIS_ONLY_VIEW));
|
||||
}
|
||||
|
||||
inline void uncacheable(uint8 cause)
|
||||
{
|
||||
safe_to_cache_query= 0;
|
||||
|
@ -5865,13 +5865,6 @@ mysql_new_select(LEX *lex, bool move_down)
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
select_lex->nest_level= lex->nest_level;
|
||||
/*
|
||||
Don't evaluate this subquery during statement prepare even if
|
||||
it's a constant one. The flag is switched off in the end of
|
||||
mysqld_stmt_prepare.
|
||||
*/
|
||||
if (thd->stmt_arena->is_stmt_prepare())
|
||||
select_lex->uncacheable|= UNCACHEABLE_PREPARE;
|
||||
if (move_down)
|
||||
{
|
||||
SELECT_LEX_UNIT *unit;
|
||||
|
@ -1688,7 +1688,7 @@ static bool mysql_test_create_view(Prepared_statement *stmt)
|
||||
if (open_normal_and_derived_tables(thd, tables, 0))
|
||||
goto err;
|
||||
|
||||
lex->view_prepare_mode= 1;
|
||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
|
||||
res= select_like_stmt_test(stmt, 0, 0);
|
||||
|
||||
err:
|
||||
@ -2234,19 +2234,6 @@ end:
|
||||
}
|
||||
|
||||
|
||||
/** Init PS/SP specific parse tree members. */
|
||||
|
||||
static void init_stmt_after_parse(LEX *lex)
|
||||
{
|
||||
SELECT_LEX *sl= lex->all_selects_list;
|
||||
/*
|
||||
Switch off a temporary flag that prevents evaluation of
|
||||
subqueries in statement prepare.
|
||||
*/
|
||||
for (; sl; sl= sl->next_select_in_list())
|
||||
sl->uncacheable&= ~UNCACHEABLE_PREPARE;
|
||||
}
|
||||
|
||||
/**
|
||||
SQLCOM_PREPARE implementation.
|
||||
|
||||
@ -3080,6 +3067,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||
|
||||
parser_state.m_lip.stmt_prepare_mode= TRUE;
|
||||
lex_start(thd);
|
||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_PREPARE;
|
||||
|
||||
error= parse_sql(thd, & parser_state, NULL) ||
|
||||
thd->is_error() ||
|
||||
@ -3132,7 +3120,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
||||
if (error == 0)
|
||||
{
|
||||
setup_set_params();
|
||||
init_stmt_after_parse(lex);
|
||||
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
|
||||
state= Query_arena::PREPARED;
|
||||
flags&= ~ (uint) IS_IN_USE;
|
||||
/*
|
||||
|
@ -538,7 +538,8 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
thd->lex->allow_sum_func= save_allow_sum_func;
|
||||
}
|
||||
|
||||
if (!thd->lex->view_prepare_mode && !(select_options & SELECT_DESCRIBE))
|
||||
if (!(thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW) &&
|
||||
!(select_options & SELECT_DESCRIBE))
|
||||
{
|
||||
Item_subselect *subselect;
|
||||
/* Is it subselect? */
|
||||
|
@ -718,7 +718,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
||||
table_list->table_name));
|
||||
|
||||
/* We want to preserve the tree for views. */
|
||||
thd->lex->view_prepare_mode= TRUE;
|
||||
thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
|
||||
|
||||
{
|
||||
Show_create_error_handler view_error_suppressor(thd, table_list);
|
||||
@ -3315,7 +3315,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
uint derived_tables= lex->derived_tables;
|
||||
int error= 1;
|
||||
Open_tables_state open_tables_state_backup;
|
||||
bool save_view_prepare_mode= lex->view_prepare_mode;
|
||||
uint8 save_context_analysis_only= lex->context_analysis_only;
|
||||
Query_tables_list query_tables_list_backup;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
Security_context *sctx= thd->security_ctx;
|
||||
@ -3323,7 +3323,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
|
||||
uint table_open_method;
|
||||
DBUG_ENTER("get_all_tables");
|
||||
|
||||
lex->view_prepare_mode= TRUE;
|
||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
|
||||
lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
|
||||
|
||||
/*
|
||||
@ -3540,7 +3540,7 @@ err:
|
||||
lex->restore_backup_query_tables_list(&query_tables_list_backup);
|
||||
lex->derived_tables= derived_tables;
|
||||
lex->all_selects_list= old_all_select_lex;
|
||||
lex->view_prepare_mode= save_view_prepare_mode;
|
||||
lex->context_analysis_only= save_context_analysis_only;
|
||||
lex->sql_command= save_sql_command;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
@ -545,7 +545,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
||||
}
|
||||
|
||||
/* prepare select to resolve all fields */
|
||||
lex->view_prepare_mode= 1;
|
||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
|
||||
if (unit->prepare(thd, 0, 0))
|
||||
{
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user