Commit 92b44016 authored by kostja@bodhi.local's avatar kostja@bodhi.local

Merge bodhi.local:/opt/local/work/mysql-5.0-runtime

into  bodhi.local:/opt/local/work/mysql-5.1-runtime-merge
parents 3d488d49 f49f21dc
......@@ -171,7 +171,7 @@ void set_extra_default(int id, const struct my_option *opt)
}
d= (extra_default_t *)my_malloc(sizeof(extra_default_t),
MYF(MY_FAE|MY_ZEROFILL));
MYF(MY_FAE | MY_ZEROFILL));
d->id= id;
d->name= opt->name;
d->n_len= strlen(opt->name);
......@@ -345,15 +345,17 @@ static int create_defaults_file(const char *path, const char *forced_path)
}
dynstr_set(&buf, NULL);
}
if (dynstr_append_mem(&buf, "\n", 1)
|| dynstr_append_mem(&buf, d->name, d->n_len)
|| (d->v_len && (dynstr_append_mem(&buf, "=", 1)
|| dynstr_append_mem(&buf, d->value, d->v_len))))
if (dynstr_append_mem(&buf, "\n", 1) ||
dynstr_append_mem(&buf, d->name, d->n_len) ||
(d->v_len && (dynstr_append_mem(&buf, "=", 1) ||
dynstr_append_mem(&buf, d->value, d->v_len))))
{
ret= 1;
goto error;
}
my_delete((gptr)d, MYF(0));
my_free((gptr) d, MYF(0));
list_pop(extra_defaults); /* pop off the head */
}
if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME)))
......@@ -451,10 +453,10 @@ int main(int argc, char **argv)
char *forced_extra_defaults;
char *local_defaults_group_suffix;
const char *script_line;
char *upgrade_defaults_path= 0;
char *upgrade_defaults_path= NULL;
char *defaults_to_use= NULL;
int upgrade_defaults_created= 0;
int no_defaults;
char path[FN_REFLEN];
DYNAMIC_STRING cmdline;
......@@ -464,6 +466,10 @@ int main(int argc, char **argv)
#endif
/* Check if we are forced to use specific defaults */
no_defaults= 0;
if (argc >= 2 && !strcmp(argv[1],"--no-defaults"))
no_defaults= 1;
get_defaults_options(argc, argv,
&forced_defaults_file, &forced_extra_defaults,
&local_defaults_group_suffix);
......@@ -578,7 +584,9 @@ int main(int argc, char **argv)
if (defaults_to_use)
{
dynstr_append(&cmdline, " ");
dynstr_append_os_quoted(&cmdline, "--defaults-extra-file=",
dynstr_append_os_quoted(&cmdline,
(no_defaults ? "--defaults-file=" :
"--defaults-extra-file="),
defaults_to_use, NullS);
}
......@@ -652,7 +660,9 @@ int main(int argc, char **argv)
if (defaults_to_use)
{
dynstr_append(&cmdline, " ");
dynstr_append_os_quoted(&cmdline, "--defaults-extra-file=",
dynstr_append_os_quoted(&cmdline,
(no_defaults ? "--defaults-file=" :
"--defaults-extra-file="),
defaults_to_use, NullS);
}
dynstr_append(&cmdline, " ");
......@@ -684,6 +694,7 @@ int main(int argc, char **argv)
if (upgrade_defaults_created)
my_delete(upgrade_defaults_path, MYF(0));
my_free(upgrade_defaults_path, MYF(MY_ALLOW_ZERO_PTR));
my_end(info_flag ? MY_CHECK_ERROR : 0);
return ret;
}
......
......@@ -2609,6 +2609,33 @@ CREATE TABLE t1 (s1 char(1));
INSERT INTO t1 VALUES ('a');
SELECT * FROM t1 WHERE _utf8'a' = ANY (SELECT s1 FROM t1);
DROP TABLE t1;
#
# 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 "(())")
......
......@@ -1850,6 +1850,13 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
key_length= (create_table_def_key(thd, key, table_list, 1) -
TMP_TABLE_KEY_EXTRA);
/*
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)
......@@ -1859,6 +1866,12 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
!memcmp(table->s->table_cache_key.str, 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)
{
......@@ -1878,6 +1891,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
......@@ -1949,7 +1969,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)
*/
......@@ -1981,8 +2001,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) &&
......@@ -1999,6 +2043,16 @@ 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 ;
......@@ -2008,6 +2062,21 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
/*
Here we flush tables marked for flush. However we never flush log
tables here. They are flushed only on FLUSH LOGS.
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 && !table->s->log_table)
{
......@@ -2023,16 +2092,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_conditionwill unlock LOCK_open for us */
wait_for_condition(thd, &LOCK_open, &COND_refresh);
}
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);
......@@ -2040,6 +2128,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
......@@ -2052,6 +2141,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
}
else
{
/* Insert a new TABLE instance into the open cache */
int error;
/* Free cache if too big */
while (open_cache.records > table_cache_size && unused_tables)
......@@ -2906,6 +2996,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)
{
/*
......@@ -2920,6 +3014,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))
......@@ -2928,6 +3028,10 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
}
(*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)))
{
......@@ -3034,7 +3138,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags)
{
/*
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;
......
......@@ -47,7 +47,7 @@ const LEX_STRING null_lex_str={0,0};
#define yyoverflow(A,B,C,D,E,F) {ulong val= *(F); if (my_yyoverflow((B), (D), &val)) { yyerror((char*) (A)); return 2; } else { *(F)= (YYSIZE_T)val; }}
#define YYERROR_UNLESS(A) \
#define YYABORT_UNLESS(A) \
if (!(A)) \
{ \
yyerror(ER(ER_SYNTAX_ERROR)); \
......@@ -421,6 +421,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
/*
Comments for TOKENS.
......@@ -7140,7 +7145,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 */
......@@ -7148,7 +7153,7 @@ derived_table_list:
table_ref { $$=$1; }
| derived_table_list ',' table_ref
{
YYERROR_UNLESS($1 && ($$=$3));
YYABORT_UNLESS($1 && ($$=$3));
}
;
......@@ -7167,13 +7172,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;
......@@ -7188,7 +7193,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;
......@@ -7204,13 +7209,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);
}
......@@ -7218,7 +7223,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;
......@@ -7234,7 +7239,7 @@ join_table:
}
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
YYERROR_UNLESS($1 && $5);
YYABORT_UNLESS($1 && $5);
}
USING '(' using_list ')'
{
......@@ -7244,7 +7249,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;
......@@ -7254,7 +7259,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;
......@@ -7271,7 +7276,7 @@ join_table:
}
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
YYERROR_UNLESS($1 && $5);
YYABORT_UNLESS($1 && $5);
}
USING '(' using_list ')'
{
......@@ -7282,7 +7287,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()))
......@@ -7325,7 +7330,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;
......@@ -11511,21 +11516,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());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment