summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <dlenev@brandersnatch.localdomain>2004-12-17 15:34:48 +0300
committerunknown <dlenev@brandersnatch.localdomain>2004-12-17 15:34:48 +0300
commitbc152db57932ffec118a11ad9607fb99d9d2bdd4 (patch)
tree577624a5e1b07aa6fa2e71cc63e8ca25649164a8
parent9a3de9447460e33a9f318c9b33bc96558eabe5d1 (diff)
downloadmariadb-git-bc152db57932ffec118a11ad9607fb99d9d2bdd4.tar.gz
Fix for bug #6849 "Crash while preparing query containing const expr with
IN and CONVERT_TZ()" (with after review changes). Now we add implicitly used time zone tables to global table list right at the parsing stage instead of doing it later in mysql_execute_command() or in check_prepared_statement(). No special test-case needed since this bug also manifests itself as timezone2.test failure if one runs it with --ps-protocol option. sql/sql_base.cc: relink_tables_for_multidelete(): presence of implicitly used time zone tables is no longer condition for propagation of TABLE pointers from global table list to local table lists (since now global list is always created...) sql/sql_lex.cc: - Added LEX::add_time_zone_tables_to_query_tables() function which adds implicitly used time zone tables to global table list. - Definition of fake_time_zone_tables_list moved to tztime.cc, since it is no longer used in parser. sql/sql_lex.h: - Since now we add implicitly used time zone tables right at parsing stage, LEX::time_zone_tables_used is either zero or points to valid time zone tables list. Updated its description to reflect that. - Added LEX::add_time_zone_tables_to_query_tables() function which adds implicitly used time zone tables to global table list. - Declaration of fake_time_zone_tables_list moved to tztime.h, since it is no longer used in parser. sql/sql_parse.cc: mysql_execute_command(): Removed adding list of implicitly used time zone tables to global table list, since now we do this right at the parsing stage. sql/sql_yacc.yy: Let us add implicitly used time zone tables to global table list right at the parsing stage instead of doing it later in mysql_execute_command() or in check_prepared_statement(). sql/tztime.cc: Moved fake_time_zone_tables_list definition from sql_lex.cc to tztime.cc since now it is used only for error reporting from my_tz_get_table_list() function. sql/tztime.h: Moved fake_time_zone_tables_list declaration from sql_lex.h to tztime.h since now it is used only for error reporting from my_tz_get_table_list() function.
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_lex.cc34
-rw-r--r--sql/sql_lex.h7
-rw-r--r--sql/sql_parse.cc13
-rw-r--r--sql/sql_yacc.yy8
-rw-r--r--sql/tztime.cc6
-rw-r--r--sql/tztime.h1
7 files changed, 41 insertions, 31 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b4a2f368bc2..6d2aa3a6fba 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1864,8 +1864,7 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables)
static void relink_tables_for_multidelete(THD *thd)
{
- if (thd->lex->all_selects_list->next_select_in_list() ||
- thd->lex->time_zone_tables_used)
+ if (thd->lex->all_selects_list->next_select_in_list())
{
for (SELECT_LEX *sl= thd->lex->all_selects_list;
sl;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 12e4d912f15..8f5114b290a 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -30,15 +30,6 @@
*/
sys_var_long_ptr trg_new_row_fake_var(0, 0);
-/*
- Fake table list object, pointer to which is used as special value for
- st_lex::time_zone_tables_used indicating that we implicitly use time
- zone tables in this statement but real table list was not yet created.
- Pointer to it is also returned by my_tz_get_tables_list() as indication
- of transient error;
-*/
-TABLE_LIST fake_time_zone_tables_list;
-
/* Macros to look like lex */
#define yyGet() *(lex->ptr++)
@@ -1881,6 +1872,31 @@ void st_lex::first_lists_tables_same()
/*
+ Add implicitly used time zone description tables to global table list
+ (if needed).
+
+ SYNOPSYS
+ st_lex::add_time_zone_tables_to_query_tables()
+ thd - pointer to current thread context
+
+ RETURN VALUE
+ TRUE - error
+ FALSE - success
+*/
+
+bool st_lex::add_time_zone_tables_to_query_tables(THD *thd)
+{
+ /* We should not add these tables twice */
+ if (!time_zone_tables_used)
+ {
+ time_zone_tables_used= my_tz_get_table_list(thd, &query_tables_last);
+ if (time_zone_tables_used == &fake_time_zone_tables_list)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/*
Link table back that was unlinked with unlink_first_table()
SYNOPSIS
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 1c0e3e2e02e..e0e9d2503fe 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -735,9 +735,8 @@ typedef struct st_lex
/* Names of user variables holding parameters (in EXECUTE) */
List<LEX_STRING> prepared_stmt_params;
/*
- If points to fake_time_zone_tables_list indicates that time zone
- tables are implicitly used by statement, also is used for holding
- list of those tables after they are opened.
+ Points to part of global table list which contains time zone tables
+ implicitly used by the statement.
*/
TABLE_LIST *time_zone_tables_used;
sp_head *sphead;
@@ -802,6 +801,7 @@ typedef struct st_lex
*(table->prev_global= query_tables_last)= table;
query_tables_last= &table->next_global;
}
+ bool add_time_zone_tables_to_query_tables(THD *thd);
bool can_be_merged();
bool can_use_merged();
@@ -810,7 +810,6 @@ typedef struct st_lex
bool need_correct_ident();
} LEX;
-extern TABLE_LIST fake_time_zone_tables_list;
struct st_lex_local: public st_lex
{
static void *operator new(size_t size)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3d4252a2b17..3094bd76b4e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2114,19 +2114,6 @@ mysql_execute_command(THD *thd)
}
#endif /* !HAVE_REPLICATION */
- if (lex->time_zone_tables_used)
- {
- TABLE_LIST *tmp;
- if ((tmp= my_tz_get_table_list(thd, &lex->query_tables_last)) ==
- &fake_time_zone_tables_list)
- {
- DBUG_RETURN(-1);
- }
- lex->time_zone_tables_used= tmp;
- if (!all_tables)
- all_tables= tmp;
- }
-
/*
When option readonly is set deny operations which change tables.
Except for the replication thread and the 'super' users.
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 3511777dd27..673f340722b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4266,7 +4266,8 @@ simple_expr:
{ $$= create_func_contains($3, $5); }
| CONVERT_TZ_SYM '(' expr ',' expr ',' expr ')'
{
- Lex->time_zone_tables_used= &fake_time_zone_tables_list;
+ if (Lex->add_time_zone_tables_to_query_tables(YYTHD))
+ YYABORT;
$$= new Item_func_convert_tz($3, $5, $7);
}
| CURDATE optional_braces
@@ -7276,8 +7277,9 @@ internal_variable_name:
If this is time_zone variable we should open time zone
describing tables
*/
- if (tmp == &sys_time_zone)
- Lex->time_zone_tables_used= &fake_time_zone_tables_list;
+ if (tmp == &sys_time_zone &&
+ lex->add_time_zone_tables_to_query_tables(YYTHD))
+ YYABORT;
}
else
{
diff --git a/sql/tztime.cc b/sql/tztime.cc
index 50c496577e0..2c25c647a19 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -1440,6 +1440,12 @@ tz_init_table_list(TABLE_LIST *tz_tabs, TABLE_LIST ***global_next_ptr)
/*
+ Fake table list object, pointer to which is returned by
+ my_tz_get_tables_list() as indication of error.
+*/
+TABLE_LIST fake_time_zone_tables_list;
+
+/*
Create table list with time zone related tables and add it to the end
of global table list.
diff --git a/sql/tztime.h b/sql/tztime.h
index 6d2388bb160..07e9146c6e9 100644
--- a/sql/tztime.h
+++ b/sql/tztime.h
@@ -64,6 +64,7 @@ extern Time_zone * my_tz_find(const String *name, TABLE_LIST *tz_tables);
extern my_bool my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap);
extern void my_tz_free();
+extern TABLE_LIST fake_time_zone_tables_list;
/*
Check if we have pointer to the beggining of list of implictly used