2004-10-06 18:14:33 +02:00
|
|
|
/* Copyright (C) 2000-2004 MySQL AB
|
2001-04-07 00:18:33 +02:00
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2001-04-07 00:18:33 +02:00
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
|
|
|
|
|
|
|
|
/* HANDLER ... commands - direct access to ISAM */
|
|
|
|
|
2001-04-13 16:18:44 +02:00
|
|
|
/* TODO:
|
|
|
|
HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2001-04-13 16:18:44 +02:00
|
|
|
the most natural (easiest, fastest) way to do it is to
|
|
|
|
compute List<Item> field_list not in mysql_ha_read
|
|
|
|
but in mysql_ha_open, and then store it in TABLE structure.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2001-04-13 16:18:44 +02:00
|
|
|
The problem here is that mysql_parse calls free_item to free all the
|
|
|
|
items allocated at the end of every query. The workaround would to
|
|
|
|
keep two item lists per THD - normal free_list and handler_items.
|
|
|
|
The second is to be freeed only on thread end. mysql_ha_open should
|
|
|
|
then do { handler_items=concat(handler_items, free_list); free_list=0; }
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2003-09-09 19:23:01 +02:00
|
|
|
But !!! do_command calls free_root at the end of every query and frees up
|
2001-04-13 16:18:44 +02:00
|
|
|
all the sql_alloc'ed memory. It's harder to work around...
|
2004-03-10 12:46:11 +01:00
|
|
|
*/
|
2001-04-13 16:18:44 +02:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
/*
|
|
|
|
There are two containers holding information about open handler tables.
|
|
|
|
The first is 'thd->handler_tables'. It is a linked list of TABLE objects.
|
|
|
|
It is used like 'thd->open_tables' in the table cache. The trick is to
|
|
|
|
exchange these two lists during open and lock of tables. Thus the normal
|
|
|
|
table cache code can be used.
|
|
|
|
The second container is a HASH. It holds objects of the type TABLE_LIST.
|
|
|
|
Despite its name, no lists of tables but only single structs are hashed
|
|
|
|
(the 'next' pointer is always NULL). The reason for theis second container
|
|
|
|
is, that we want handler tables to survive FLUSH TABLE commands. A table
|
|
|
|
affected by FLUSH TABLE must be closed so that other threads are not
|
|
|
|
blocked by handler tables still in use. Since we use the normal table cache
|
|
|
|
functions with 'thd->handler_tables', the closed tables are removed from
|
|
|
|
this list. Hence we need the original open information for the handler
|
|
|
|
table in the case that it is used again. This information is handed over
|
|
|
|
to mysql_ha_open() as a TABLE_LIST. So we store this information in the
|
|
|
|
second container, where it is not affected by FLUSH TABLE. The second
|
|
|
|
container is implemented as a hash for performance reasons. Consequently,
|
|
|
|
we use it not only for re-opening a handler table, but also for the
|
|
|
|
HANDLER ... READ commands. For this purpose, we store a pointer to the
|
|
|
|
TABLE structure (in the first container) in the TBALE_LIST object in the
|
|
|
|
second container. When the table is flushed, the pointer is cleared.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "mysql_priv.h"
|
|
|
|
#include "sql_select.h"
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#define HANDLER_TABLES_HASH_SIZE 120
|
|
|
|
|
|
|
|
static enum enum_ha_read_modes rkey_to_rnext[]=
|
2004-10-29 18:26:52 +02:00
|
|
|
{ RNEXT_SAME, RNEXT, RPREV, RNEXT, RPREV, RNEXT, RPREV, RPREV };
|
2004-09-24 18:39:25 +02:00
|
|
|
|
2004-10-06 16:20:39 +02:00
|
|
|
static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags);
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Get hash key and hash key length.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
mysql_ha_hash_get_key()
|
|
|
|
tables Pointer to the hash object.
|
|
|
|
key_len_p (out) Pointer to the result for key length.
|
|
|
|
first Unused.
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
The hash object is an TABLE_LIST struct.
|
|
|
|
The hash key is the alias name.
|
|
|
|
The hash key length is the alias name length plus one for the
|
|
|
|
terminateing NUL character.
|
2001-04-07 00:18:33 +02:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
RETURN
|
|
|
|
Pointer to the TABLE_LIST struct.
|
|
|
|
*/
|
2001-04-07 00:18:33 +02:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
static char *mysql_ha_hash_get_key(TABLE_LIST *tables, uint *key_len_p,
|
|
|
|
my_bool first __attribute__((unused)))
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
*key_len_p= strlen(tables->alias) + 1 ; /* include '\0' in comparisons */
|
|
|
|
return tables->alias;
|
|
|
|
}
|
2004-09-07 09:42:23 +02:00
|
|
|
|
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
/*
|
|
|
|
Free an hash object.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
SYNOPSIS
|
|
|
|
mysql_ha_hash_free()
|
|
|
|
tables Pointer to the hash object.
|
2001-12-21 14:28:51 +01:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
DESCRIPTION
|
|
|
|
The hash object is an TABLE_LIST struct.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
Nothing
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void mysql_ha_hash_free(TABLE_LIST *tables)
|
|
|
|
{
|
|
|
|
my_free((char*) tables, MYF(0));
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
|
|
|
|
2007-08-15 17:13:34 +02:00
|
|
|
/**
|
2007-08-15 22:12:09 +02:00
|
|
|
Close a HANDLER table.
|
|
|
|
|
|
|
|
@param thd Thread identifier.
|
|
|
|
@param tables A list of tables with the first entry to close.
|
|
|
|
|
|
|
|
@note Though this function takes a list of tables, only the first list entry
|
|
|
|
will be closed.
|
|
|
|
@note Broadcasts refresh if it closed the table.
|
|
|
|
*/
|
2007-08-15 17:13:34 +02:00
|
|
|
|
|
|
|
static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
|
|
|
|
{
|
|
|
|
TABLE **table_ptr;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Though we could take the table pointer from hash_tables->table,
|
|
|
|
we must follow the thd->handler_tables chain anyway, as we need the
|
|
|
|
address of the 'next' pointer referencing this table
|
|
|
|
for close_thread_table().
|
|
|
|
*/
|
|
|
|
for (table_ptr= &(thd->handler_tables);
|
|
|
|
*table_ptr && (*table_ptr != tables->table);
|
|
|
|
table_ptr= &(*table_ptr)->next)
|
|
|
|
;
|
|
|
|
|
|
|
|
if (*table_ptr)
|
|
|
|
{
|
|
|
|
(*table_ptr)->file->ha_index_or_rnd_end();
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_open));
|
|
|
|
if (close_thread_table(thd, table_ptr))
|
|
|
|
{
|
|
|
|
/* Tell threads waiting for refresh that something has happened */
|
|
|
|
broadcast_refresh();
|
|
|
|
}
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
|
|
|
}
|
|
|
|
}
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
/*
|
2004-09-24 18:39:25 +02:00
|
|
|
Open a HANDLER table.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
SYNOPSIS
|
2004-09-24 18:39:25 +02:00
|
|
|
mysql_ha_open()
|
2004-06-24 15:06:56 +02:00
|
|
|
thd Thread identifier.
|
2004-09-24 18:39:25 +02:00
|
|
|
tables A list of tables with the first entry to open.
|
|
|
|
reopen Re-open a previously opened handler table.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
Though this function takes a list of tables, only the first list entry
|
2004-09-24 18:39:25 +02:00
|
|
|
will be opened.
|
|
|
|
'reopen' is set when a handler table is to be re-opened. In this case,
|
|
|
|
'tables' is the pointer to the hashed TABLE_LIST object which has been
|
|
|
|
saved on the original open.
|
|
|
|
'reopen' is also used to suppress the sending of an 'ok' message or
|
|
|
|
error messages.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
RETURN
|
2004-10-20 03:04:37 +02:00
|
|
|
FALSE OK
|
|
|
|
TRUE Error
|
2004-06-24 15:06:56 +02:00
|
|
|
*/
|
|
|
|
|
2004-11-12 14:36:31 +01:00
|
|
|
bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2007-08-15 17:13:34 +02:00
|
|
|
TABLE_LIST *hash_tables = NULL;
|
2004-10-06 18:14:33 +02:00
|
|
|
char *db, *name, *alias;
|
|
|
|
uint dblen, namelen, aliaslen, counter;
|
2004-10-29 18:26:52 +02:00
|
|
|
int error;
|
2007-10-09 17:02:59 +02:00
|
|
|
TABLE *backup_open_tables;
|
2004-09-24 18:39:25 +02:00
|
|
|
DBUG_ENTER("mysql_ha_open");
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("enter",("'%s'.'%s' as '%s' reopen: %d",
|
2005-01-06 12:00:13 +01:00
|
|
|
tables->db, tables->table_name, tables->alias,
|
2004-10-06 16:20:39 +02:00
|
|
|
(int) reopen));
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
if (! hash_inited(&thd->handler_tables_hash))
|
2001-11-29 20:46:51 +01:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
/*
|
|
|
|
HASH entries are of type TABLE_LIST.
|
|
|
|
*/
|
2004-10-07 09:50:13 +02:00
|
|
|
if (hash_init(&thd->handler_tables_hash, &my_charset_latin1,
|
|
|
|
HANDLER_TABLES_HASH_SIZE, 0, 0,
|
2004-09-24 18:39:25 +02:00
|
|
|
(hash_get_key) mysql_ha_hash_get_key,
|
|
|
|
(hash_free_key) mysql_ha_hash_free, 0))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
else if (! reopen) /* Otherwise we have 'tables' already. */
|
2001-11-29 20:46:51 +01:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
if (hash_search(&thd->handler_tables_hash, (byte*) tables->alias,
|
|
|
|
strlen(tables->alias) + 1))
|
2003-09-09 19:23:01 +02:00
|
|
|
{
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
|
2004-09-24 18:39:25 +02:00
|
|
|
if (! reopen)
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
|
2004-09-24 18:39:25 +02:00
|
|
|
goto err;
|
2003-09-09 19:23:01 +02:00
|
|
|
}
|
2001-11-29 20:46:51 +01:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
|
2007-10-09 17:02:59 +02:00
|
|
|
/*
|
|
|
|
Save and reset the open_tables list so that open_tables() won't
|
|
|
|
be able to access (or know about) the previous list. And on return
|
|
|
|
from open_tables(), thd->open_tables will contain only the opened
|
|
|
|
table.
|
|
|
|
|
|
|
|
The thd->handler_tables list is kept as-is to avoid deadlocks if
|
|
|
|
open_table(), called by open_tables(), needs to back-off because
|
|
|
|
of a pending name-lock on the table being opened.
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
|
2007-10-09 17:02:59 +02:00
|
|
|
See open_table() back-off comments for more details.
|
|
|
|
*/
|
|
|
|
backup_open_tables= thd->open_tables;
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
thd->open_tables= NULL;
|
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
/*
|
|
|
|
open_tables() will set 'tables->table' if successful.
|
|
|
|
It must be NULL for a real open when calling open_tables().
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(! tables->table);
|
2004-10-29 18:26:52 +02:00
|
|
|
|
|
|
|
/* for now HANDLER can be used only for real TABLES */
|
|
|
|
tables->required_type= FRMTYPE_TABLE;
|
2005-08-08 15:46:06 +02:00
|
|
|
error= open_tables(thd, &tables, &counter, 0);
|
2004-10-29 18:26:52 +02:00
|
|
|
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
/* restore the state and merge the opened table into handler_tables list */
|
2007-10-09 17:02:59 +02:00
|
|
|
if (thd->open_tables)
|
|
|
|
{
|
|
|
|
thd->open_tables->next= thd->handler_tables;
|
|
|
|
thd->handler_tables= thd->open_tables;
|
|
|
|
}
|
|
|
|
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
thd->open_tables= backup_open_tables;
|
|
|
|
|
2004-10-29 18:26:52 +02:00
|
|
|
if (error)
|
2004-09-24 18:39:25 +02:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* There can be only one table in '*tables'. */
|
|
|
|
if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
|
2001-12-22 19:40:26 +01:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
if (! reopen)
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
|
2004-09-24 18:39:25 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! reopen)
|
2001-12-22 19:40:26 +01:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
/* copy the TABLE_LIST struct */
|
|
|
|
dblen= strlen(tables->db) + 1;
|
2005-01-06 12:00:13 +01:00
|
|
|
namelen= strlen(tables->table_name) + 1;
|
2004-09-24 18:39:25 +02:00
|
|
|
aliaslen= strlen(tables->alias) + 1;
|
|
|
|
if (!(my_multi_malloc(MYF(MY_WME),
|
|
|
|
&hash_tables, sizeof(*hash_tables),
|
|
|
|
&db, dblen,
|
|
|
|
&name, namelen,
|
|
|
|
&alias, aliaslen,
|
|
|
|
NullS)))
|
|
|
|
goto err;
|
|
|
|
/* structure copy */
|
|
|
|
*hash_tables= *tables;
|
|
|
|
hash_tables->db= db;
|
2005-01-06 12:00:13 +01:00
|
|
|
hash_tables->table_name= name;
|
2004-09-24 18:39:25 +02:00
|
|
|
hash_tables->alias= alias;
|
|
|
|
memcpy(hash_tables->db, tables->db, dblen);
|
2005-01-06 12:00:13 +01:00
|
|
|
memcpy(hash_tables->table_name, tables->table_name, namelen);
|
2004-09-24 18:39:25 +02:00
|
|
|
memcpy(hash_tables->alias, tables->alias, aliaslen);
|
|
|
|
|
|
|
|
/* add to hash */
|
2004-10-07 09:50:13 +02:00
|
|
|
if (my_hash_insert(&thd->handler_tables_hash, (byte*) hash_tables))
|
2004-09-24 18:39:25 +02:00
|
|
|
goto err;
|
2001-12-22 19:40:26 +01:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
if (! reopen)
|
2002-10-02 12:33:08 +02:00
|
|
|
send_ok(thd);
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit",("OK"));
|
2004-11-12 14:36:31 +01:00
|
|
|
DBUG_RETURN(FALSE);
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
err:
|
2007-08-15 17:13:34 +02:00
|
|
|
if (hash_tables)
|
|
|
|
my_free((char*) hash_tables, MYF(0));
|
|
|
|
if (tables->table)
|
|
|
|
mysql_ha_close_table(thd, tables);
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit",("ERROR"));
|
2004-11-12 14:36:31 +01:00
|
|
|
DBUG_RETURN(TRUE);
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
|
|
|
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
/*
|
2007-08-15 17:13:34 +02:00
|
|
|
Close a HANDLER table by alias or table name
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
SYNOPSIS
|
2004-09-24 18:39:25 +02:00
|
|
|
mysql_ha_close()
|
2004-06-24 15:06:56 +02:00
|
|
|
thd Thread identifier.
|
2004-09-24 18:39:25 +02:00
|
|
|
tables A list of tables with the first entry to close.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
DESCRIPTION
|
2007-08-15 17:13:34 +02:00
|
|
|
Closes the table that is associated (on the handler tables hash) with the
|
|
|
|
name (table->alias) of the specified table.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
RETURN
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
FALSE ok
|
|
|
|
TRUE error
|
2004-06-24 15:06:56 +02:00
|
|
|
*/
|
|
|
|
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
|
2003-01-28 14:36:22 +01:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
TABLE_LIST *hash_tables;
|
|
|
|
DBUG_ENTER("mysql_ha_close");
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
|
2005-01-06 12:00:13 +01:00
|
|
|
tables->db, tables->table_name, tables->alias));
|
2004-06-24 15:06:56 +02:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
|
|
|
(byte*) tables->alias,
|
|
|
|
strlen(tables->alias) + 1)))
|
2003-09-09 19:23:01 +02:00
|
|
|
{
|
2007-08-15 17:13:34 +02:00
|
|
|
mysql_ha_close_table(thd, hash_tables);
|
2004-10-29 18:26:52 +02:00
|
|
|
hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
|
2004-06-24 15:06:56 +02:00
|
|
|
}
|
|
|
|
else
|
2003-09-09 19:23:01 +02:00
|
|
|
{
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit",("ERROR"));
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
DBUG_RETURN(TRUE);
|
2003-09-09 19:23:01 +02:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
|
2004-10-06 18:14:33 +02:00
|
|
|
send_ok(thd);
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit", ("OK"));
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
DBUG_RETURN(FALSE);
|
2003-01-28 14:36:22 +01:00
|
|
|
}
|
|
|
|
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
/*
|
|
|
|
Read from a HANDLER table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
mysql_ha_read()
|
|
|
|
thd Thread identifier.
|
|
|
|
tables A list of tables with the first entry to read.
|
|
|
|
mode
|
|
|
|
keyname
|
|
|
|
key_expr
|
|
|
|
ha_rkey_mode
|
|
|
|
cond
|
Patch two (the final one) for Bug#7306 "the server side preparedStatement
error for LIMIT placeholder".
The patch adds grammar support for LIMIT ?, ? and changes the
type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*,
so that it can point to Item_param.
mysql-test/include/ps_modify.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/include/ps_query.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/r/ps.result:
Add basic test coverage for LIMIT ?, ? and fix test results.
mysql-test/r/ps_2myisam.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_3innodb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_4heap.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_5merge.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_6bdb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_7ndb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/t/ps.test:
Add basic test coverage for LIMIT ?, ?.
sql/item.h:
Add a short-cut for (ulonglong) val_int() to Item.
Add a constructor to Item_int() that accepts ulonglong.
Simplify Item_uint constructor by using the c-tor above.
sql/item_subselect.cc:
Now select_limit has type Item *.
We can safely create an Item in Item_exists_subselect::fix_length_and_dec():
it will be allocated in runtime memory root and freed in the end of
execution.
sql/sp_head.cc:
Add a special initalization state for stored procedures to
be able to easily distinguish the first execution of a stored procedure
from prepared statement prepare.
sql/sql_class.h:
Introduce new state 'INITIALIZED_FOR_SP' to be able to easily distinguish
the first execution of a stored procedure from prepared statement prepare.
sql/sql_derived.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace. Add a warning about use of set_limit in
mysql_derived_filling.
sql/sql_error.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace.
- this change is also aware of bug#11095 "show warnings limit 0 returns
all rows instead of zero rows", so the one who merges the bugfix from
4.1 can use local version of sql_error.cc.
sql/sql_handler.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
sql/sql_lex.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_lex.h:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_parse.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
- we can create an Item_int to set global limit of a statement:
it will be created in the runtime mem root and freed in the end of
execution.
sql/sql_repl.cc:
Use unit->set_limit to initialize limits.
sql/sql_select.cc:
- select_limit is now Item* so the proper way to check for default value
is to compare it with NULL.
sql/sql_union.cc:
Evaluate offset_limit_cnt using the new type of ST_SELECT_LEX::offset_limit
sql/sql_view.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_yacc.yy:
Add grammar support for LIMIT ?, ? clause.
2005-06-07 12:11:36 +02:00
|
|
|
select_limit_cnt
|
|
|
|
offset_limit_cnt
|
2002-01-29 17:32:16 +01:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
RETURN
|
2004-11-12 14:36:31 +01:00
|
|
|
FALSE ok
|
|
|
|
TRUE error
|
2004-09-24 18:39:25 +02:00
|
|
|
*/
|
|
|
|
|
2004-10-20 03:04:37 +02:00
|
|
|
bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
|
|
|
enum enum_ha_read_modes mode, char *keyname,
|
|
|
|
List<Item> *key_expr,
|
|
|
|
enum ha_rkey_function ha_rkey_mode, Item *cond,
|
Patch two (the final one) for Bug#7306 "the server side preparedStatement
error for LIMIT placeholder".
The patch adds grammar support for LIMIT ?, ? and changes the
type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*,
so that it can point to Item_param.
mysql-test/include/ps_modify.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/include/ps_query.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/r/ps.result:
Add basic test coverage for LIMIT ?, ? and fix test results.
mysql-test/r/ps_2myisam.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_3innodb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_4heap.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_5merge.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_6bdb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_7ndb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/t/ps.test:
Add basic test coverage for LIMIT ?, ?.
sql/item.h:
Add a short-cut for (ulonglong) val_int() to Item.
Add a constructor to Item_int() that accepts ulonglong.
Simplify Item_uint constructor by using the c-tor above.
sql/item_subselect.cc:
Now select_limit has type Item *.
We can safely create an Item in Item_exists_subselect::fix_length_and_dec():
it will be allocated in runtime memory root and freed in the end of
execution.
sql/sp_head.cc:
Add a special initalization state for stored procedures to
be able to easily distinguish the first execution of a stored procedure
from prepared statement prepare.
sql/sql_class.h:
Introduce new state 'INITIALIZED_FOR_SP' to be able to easily distinguish
the first execution of a stored procedure from prepared statement prepare.
sql/sql_derived.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace. Add a warning about use of set_limit in
mysql_derived_filling.
sql/sql_error.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace.
- this change is also aware of bug#11095 "show warnings limit 0 returns
all rows instead of zero rows", so the one who merges the bugfix from
4.1 can use local version of sql_error.cc.
sql/sql_handler.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
sql/sql_lex.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_lex.h:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_parse.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
- we can create an Item_int to set global limit of a statement:
it will be created in the runtime mem root and freed in the end of
execution.
sql/sql_repl.cc:
Use unit->set_limit to initialize limits.
sql/sql_select.cc:
- select_limit is now Item* so the proper way to check for default value
is to compare it with NULL.
sql/sql_union.cc:
Evaluate offset_limit_cnt using the new type of ST_SELECT_LEX::offset_limit
sql/sql_view.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_yacc.yy:
Add grammar support for LIMIT ?, ? clause.
2005-06-07 12:11:36 +02:00
|
|
|
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
TABLE_LIST *hash_tables;
|
2007-10-09 17:02:59 +02:00
|
|
|
TABLE *table, *backup_open_tables;
|
2004-10-06 18:14:33 +02:00
|
|
|
MYSQL_LOCK *lock;
|
|
|
|
List<Item> list;
|
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
char buff[MAX_FIELD_WIDTH];
|
|
|
|
String buffer(buff, sizeof(buff), system_charset_info);
|
2004-10-29 18:26:52 +02:00
|
|
|
int error, keyno= -1;
|
2004-09-24 18:39:25 +02:00
|
|
|
uint num_rows;
|
2004-10-06 18:14:33 +02:00
|
|
|
byte *key;
|
|
|
|
uint key_len;
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
bool need_reopen;
|
2004-09-24 18:39:25 +02:00
|
|
|
DBUG_ENTER("mysql_ha_read");
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
|
2005-01-06 12:00:13 +01:00
|
|
|
tables->db, tables->table_name, tables->alias));
|
2004-09-24 18:39:25 +02:00
|
|
|
|
2004-10-06 18:14:33 +02:00
|
|
|
LINT_INIT(key);
|
|
|
|
LINT_INIT(key_len);
|
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
thd->lex->select_lex.context.resolve_in_table_list_only(tables);
|
|
|
|
list.push_front(new Item_field(&thd->lex->select_lex.context,
|
|
|
|
NULL, NULL, "*"));
|
2004-09-24 18:39:25 +02:00
|
|
|
List_iterator<Item> it(list);
|
|
|
|
it++;
|
|
|
|
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
retry:
|
2004-09-24 18:39:25 +02:00
|
|
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
|
|
|
(byte*) tables->alias,
|
|
|
|
strlen(tables->alias) + 1)))
|
|
|
|
{
|
|
|
|
table= hash_tables->table;
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p",
|
2005-01-06 12:00:13 +01:00
|
|
|
hash_tables->db, hash_tables->table_name,
|
2004-10-06 16:20:39 +02:00
|
|
|
hash_tables->alias, table));
|
2004-09-24 18:39:25 +02:00
|
|
|
if (!table)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
The handler table has been closed. Re-open it.
|
|
|
|
*/
|
|
|
|
if (mysql_ha_open(thd, hash_tables, 1))
|
|
|
|
{
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit",("reopen failed"));
|
2004-09-24 18:39:25 +02:00
|
|
|
goto err0;
|
|
|
|
}
|
|
|
|
|
|
|
|
table= hash_tables->table;
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("info",("re-opened '%s'.'%s' as '%s' tab %p",
|
2005-01-06 12:00:13 +01:00
|
|
|
hash_tables->db, hash_tables->table_name,
|
2004-09-24 18:39:25 +02:00
|
|
|
hash_tables->alias, table));
|
|
|
|
}
|
|
|
|
|
|
|
|
#if MYSQL_VERSION_ID < 40100
|
|
|
|
if (*tables->db && strcmp(table->table_cache_key, tables->db))
|
|
|
|
{
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("info",("wrong db"));
|
2004-09-24 18:39:25 +02:00
|
|
|
table= NULL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
table= NULL;
|
|
|
|
|
2001-04-07 00:18:33 +02:00
|
|
|
if (!table)
|
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
#if MYSQL_VERSION_ID < 40100
|
|
|
|
char buff[MAX_DBKEY_LENGTH];
|
|
|
|
if (*tables->db)
|
2005-01-06 12:00:13 +01:00
|
|
|
strxnmov(buff, sizeof(buff), tables->db, ".", tables->table_name, NullS);
|
2004-09-24 18:39:25 +02:00
|
|
|
else
|
|
|
|
strncpy(buff, tables->alias, sizeof(buff));
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_UNKNOWN_TABLE, MYF(0), buff, "HANDLER");
|
2004-09-24 18:39:25 +02:00
|
|
|
#else
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
|
2004-09-24 18:39:25 +02:00
|
|
|
#endif
|
|
|
|
goto err0;
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
|
|
|
tables->table=table;
|
2001-04-13 16:18:44 +02:00
|
|
|
|
2007-10-09 17:02:59 +02:00
|
|
|
/* save open_tables state */
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
backup_open_tables= thd->open_tables;
|
2007-10-09 17:02:59 +02:00
|
|
|
/*
|
|
|
|
mysql_lock_tables() needs thd->open_tables to be set correctly to
|
|
|
|
be able to handle aborts properly. When the abort happens, it's
|
|
|
|
safe to not protect thd->handler_tables because it won't close any
|
|
|
|
tables.
|
|
|
|
*/
|
|
|
|
thd->open_tables= thd->handler_tables;
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
|
|
|
|
lock= mysql_lock_tables(thd, &tables->table, 1,
|
|
|
|
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &need_reopen);
|
|
|
|
|
|
|
|
/* restore previous context */
|
|
|
|
thd->open_tables= backup_open_tables;
|
|
|
|
|
|
|
|
if (need_reopen)
|
|
|
|
{
|
|
|
|
mysql_ha_close_table(thd, tables);
|
|
|
|
hash_tables->table= NULL;
|
2007-10-12 15:55:46 +02:00
|
|
|
/*
|
|
|
|
The lock might have been aborted, we need to manually reset
|
|
|
|
thd->some_tables_deleted because handler's tables are closed
|
|
|
|
in a non-standard way. Otherwise we might loop indefinitely.
|
|
|
|
*/
|
|
|
|
thd->some_tables_deleted= 0;
|
Bug#21587 FLUSH TABLES causes server crash when used with HANDLER statements
This bug is a symptom of the way handler's tables are managed. The
most different aspect, compared to the conventional behavior, is that
the handler's tables are long lived, meaning that their lifetimes are
not bounded by the duration of the command that opened them. For this
effect the handler code uses its own list (handler_tables instead of
open_tables) to hold open handler tables so that the tables won't be
closed at the end of the command/statement. Besides the handler_tables
list, there is a hash (handler_tables_hash) which is used to associate
handler aliases to tables and to refresh the tables upon demand (flush
tables).
The current implementation doesn't work properly with refreshed tables
-- more precisely when flush commands are issued by other initiators.
This happens because when a handler open or read statement is being
processed, the associated table has to be opened or locked and, for this
matter, the open_tables and handler_tables lists are swapped so that the
new table being opened is inserted into the handler_tables list. But when
opening or locking the table, if the refresh version is different from the
thread refresh version then all used tables in the open_tables list (now
handler_tables) are refreshed. In the "refreshing" process the handler
tables are flushed (closed) without being properly unlinked from the
handler hash.
The current implementation also fails to properly discard handlers of
dropped tables, but this and other problems are going to be addressed
in the fixes for bugs 31397 and 31409.
The chosen approach tries to properly save and restore the table state
so that no table is flushed during the table open and lock operations.
The logic is almost the same as before with the list swapping, but with
a working glue code.
The test case for this bug is going to be committed into 5.1 because it
requires a test feature only avaiable in 5.1 (wait_condition).
sql/sql_handler.cc:
Backup and reset the open_tables and handler_table lists when opening
a new handler table and merge the opened table into the handler_tables
list afterwards. When locking, do the same but possibly close the table
if a refresh is pending.
2007-10-04 22:34:41 +02:00
|
|
|
goto retry;
|
|
|
|
}
|
2006-01-06 11:48:14 +01:00
|
|
|
|
|
|
|
if (!lock)
|
|
|
|
goto err0; // mysql_lock_tables() printed error message already
|
|
|
|
|
2006-01-16 22:15:00 +01:00
|
|
|
if (cond)
|
2006-01-10 18:13:12 +01:00
|
|
|
{
|
|
|
|
if (table->query_id != thd->query_id)
|
|
|
|
cond->cleanup(); // File was reopened
|
2006-01-16 22:15:00 +01:00
|
|
|
if ((!cond->fixed &&
|
|
|
|
cond->fix_fields(thd, &cond)) || cond->check_cols(1))
|
2007-08-27 15:37:12 +02:00
|
|
|
goto err;
|
2006-01-10 18:13:12 +01:00
|
|
|
}
|
2003-01-13 17:20:59 +01:00
|
|
|
|
2001-04-13 16:18:44 +02:00
|
|
|
if (keyname)
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
if ((keyno=find_type(keyname, &table->s->keynames, 1+2)-1)<0)
|
2001-04-13 16:18:44 +02:00
|
|
|
{
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias);
|
2007-08-27 15:37:12 +02:00
|
|
|
goto err;
|
2001-04-13 16:18:44 +02:00
|
|
|
}
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
|
|
|
|
2006-01-05 23:47:49 +01:00
|
|
|
if (insert_fields(thd, &thd->lex->select_lex.context,
|
|
|
|
tables->db, tables->alias, &it, 0))
|
2007-08-27 15:37:12 +02:00
|
|
|
goto err;
|
2006-01-05 23:47:49 +01:00
|
|
|
|
|
|
|
protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
|
|
|
|
|
2003-02-07 14:47:24 +01:00
|
|
|
/*
|
|
|
|
In ::external_lock InnoDB resets the fields which tell it that
|
|
|
|
the handle is used in the HANDLER interface. Tell it again that
|
|
|
|
we are using it for HANDLER.
|
|
|
|
*/
|
2003-01-13 17:20:59 +01:00
|
|
|
|
|
|
|
table->file->init_table_handle_for_HANDLER();
|
|
|
|
|
Patch two (the final one) for Bug#7306 "the server side preparedStatement
error for LIMIT placeholder".
The patch adds grammar support for LIMIT ?, ? and changes the
type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*,
so that it can point to Item_param.
mysql-test/include/ps_modify.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/include/ps_query.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/r/ps.result:
Add basic test coverage for LIMIT ?, ? and fix test results.
mysql-test/r/ps_2myisam.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_3innodb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_4heap.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_5merge.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_6bdb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_7ndb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/t/ps.test:
Add basic test coverage for LIMIT ?, ?.
sql/item.h:
Add a short-cut for (ulonglong) val_int() to Item.
Add a constructor to Item_int() that accepts ulonglong.
Simplify Item_uint constructor by using the c-tor above.
sql/item_subselect.cc:
Now select_limit has type Item *.
We can safely create an Item in Item_exists_subselect::fix_length_and_dec():
it will be allocated in runtime memory root and freed in the end of
execution.
sql/sp_head.cc:
Add a special initalization state for stored procedures to
be able to easily distinguish the first execution of a stored procedure
from prepared statement prepare.
sql/sql_class.h:
Introduce new state 'INITIALIZED_FOR_SP' to be able to easily distinguish
the first execution of a stored procedure from prepared statement prepare.
sql/sql_derived.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace. Add a warning about use of set_limit in
mysql_derived_filling.
sql/sql_error.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace.
- this change is also aware of bug#11095 "show warnings limit 0 returns
all rows instead of zero rows", so the one who merges the bugfix from
4.1 can use local version of sql_error.cc.
sql/sql_handler.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
sql/sql_lex.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_lex.h:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_parse.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
- we can create an Item_int to set global limit of a statement:
it will be created in the runtime mem root and freed in the end of
execution.
sql/sql_repl.cc:
Use unit->set_limit to initialize limits.
sql/sql_select.cc:
- select_limit is now Item* so the proper way to check for default value
is to compare it with NULL.
sql/sql_union.cc:
Evaluate offset_limit_cnt using the new type of ST_SELECT_LEX::offset_limit
sql/sql_view.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_yacc.yy:
Add grammar support for LIMIT ?, ? clause.
2005-06-07 12:11:36 +02:00
|
|
|
for (num_rows=0; num_rows < select_limit_cnt; )
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
switch (mode) {
|
2005-06-07 22:43:25 +02:00
|
|
|
case RNEXT:
|
|
|
|
if (table->file->inited != handler::NONE)
|
|
|
|
{
|
2005-06-09 18:15:06 +02:00
|
|
|
error=keyname ?
|
2005-06-07 22:43:25 +02:00
|
|
|
table->file->index_next(table->record[0]) :
|
|
|
|
table->file->rnd_next(table->record[0]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* else fall through */
|
2002-01-29 17:32:16 +01:00
|
|
|
case RFIRST:
|
2003-02-22 18:00:34 +01:00
|
|
|
if (keyname)
|
2005-06-07 22:43:25 +02:00
|
|
|
{
|
|
|
|
table->file->ha_index_or_rnd_end();
|
|
|
|
table->file->ha_index_init(keyno);
|
2004-10-29 18:26:52 +02:00
|
|
|
error= table->file->index_first(table->record[0]);
|
2005-06-07 22:43:25 +02:00
|
|
|
}
|
2003-02-22 18:00:34 +01:00
|
|
|
else
|
|
|
|
{
|
2004-06-23 12:29:05 +02:00
|
|
|
table->file->ha_index_or_rnd_end();
|
2004-10-29 18:26:52 +02:00
|
|
|
if (!(error= table->file->ha_rnd_init(1)))
|
|
|
|
error= table->file->rnd_next(table->record[0]);
|
2003-02-22 18:00:34 +01:00
|
|
|
}
|
2002-01-29 17:32:16 +01:00
|
|
|
mode=RNEXT;
|
|
|
|
break;
|
2005-06-07 22:43:25 +02:00
|
|
|
case RPREV:
|
|
|
|
DBUG_ASSERT(keyname != 0);
|
|
|
|
if (table->file->inited != handler::NONE)
|
|
|
|
{
|
2005-06-09 18:15:06 +02:00
|
|
|
error=table->file->index_prev(table->record[0]);
|
2005-06-07 22:43:25 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* else fall through */
|
2002-01-29 17:32:16 +01:00
|
|
|
case RLAST:
|
|
|
|
DBUG_ASSERT(keyname != 0);
|
2005-06-07 22:43:25 +02:00
|
|
|
table->file->ha_index_or_rnd_end();
|
|
|
|
table->file->ha_index_init(keyno);
|
2004-10-29 18:26:52 +02:00
|
|
|
error= table->file->index_last(table->record[0]);
|
2002-01-29 17:32:16 +01:00
|
|
|
mode=RPREV;
|
|
|
|
break;
|
2004-05-19 00:18:54 +02:00
|
|
|
case RNEXT_SAME:
|
|
|
|
/* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...) */
|
|
|
|
DBUG_ASSERT(keyname != 0);
|
2004-10-29 18:26:52 +02:00
|
|
|
error= table->file->index_next_same(table->record[0], key, key_len);
|
2004-05-19 00:18:54 +02:00
|
|
|
break;
|
2002-01-29 17:32:16 +01:00
|
|
|
case RKEY:
|
2001-04-09 15:37:19 +02:00
|
|
|
{
|
2002-01-29 17:32:16 +01:00
|
|
|
DBUG_ASSERT(keyname != 0);
|
|
|
|
KEY *keyinfo=table->key_info+keyno;
|
|
|
|
KEY_PART_INFO *key_part=keyinfo->key_part;
|
|
|
|
if (key_expr->elements > keyinfo->key_parts)
|
|
|
|
{
|
now my_printf_error is not better then my_error, but my_error call is shorter
used only one implementation of format parser of (printf)
fixed multistatement
include/mysqld_error.h:
newerror messages
mysql-test/t/key.test:
unknown error replaced with real error
mysys/my_error.c:
my_error & my_printf_error use my_vsprintf
sql/field_conv.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/ha_innodb.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_cmpfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_func.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/item_strfunc.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/lock.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/log.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/parse_file.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/procedure.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/protocol.cc:
no need reset thd->lex->found_colon to break multiline sequance now, send_error called too late
sql/repl_failsafe.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/set_var.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/share/czech/errmsg.txt:
new errors converted from unknown error
sql/share/danish/errmsg.txt:
new errors converted from unknown error
sql/share/dutch/errmsg.txt:
new errors converted from unknown error
sql/share/english/errmsg.txt:
new errors converted from unknown error
sql/share/estonian/errmsg.txt:
new errors converted from unknown error
sql/share/french/errmsg.txt:
new errors converted from unknown error
sql/share/german/errmsg.txt:
new errors converted from unknown error
sql/share/greek/errmsg.txt:
new errors converted from unknown error
sql/share/hungarian/errmsg.txt:
new errors converted from unknown error
sql/share/italian/errmsg.txt:
new errors converted from unknown error
sql/share/japanese/errmsg.txt:
new errors converted from unknown error
sql/share/korean/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian-ny/errmsg.txt:
new errors converted from unknown error
sql/share/norwegian/errmsg.txt:
new errors converted from unknown error
sql/share/polish/errmsg.txt:
new errors converted from unknown error
sql/share/portuguese/errmsg.txt:
new errors converted from unknown error
sql/share/romanian/errmsg.txt:
new errors converted from unknown error
sql/share/russian/errmsg.txt:
new errors converted from unknown error
sql/share/serbian/errmsg.txt:
new errors converted from unknown error
sql/share/slovak/errmsg.txt:
new errors converted from unknown error
sql/share/spanish/errmsg.txt:
new errors converted from unknown error
sql/share/swedish/errmsg.txt:
new errors converted from unknown error
sql/share/ukrainian/errmsg.txt:
new errors converted from unknown error
sql/slave.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sp_head.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_acl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_analyse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_base.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_class.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_db.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_delete.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_handler.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_insert.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_load.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_map.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_parse.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
multi-row command fixed
sql/sql_prepare.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
remover send_error ingected from 4.1
sql/sql_rename.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_repl.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_select.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_show.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_trigger.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_udf.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_update.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_view.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/sql_yacc.yy:
now my_printf_error is not better then my_error, but my_error call is shorter
sql/table.cc:
now my_printf_error is not better then my_error, but my_error call is shorter
strings/my_vsnprintf.c:
* format support added to my_vsprint
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), keyinfo->key_parts);
|
2002-01-29 17:32:16 +01:00
|
|
|
goto err;
|
|
|
|
}
|
2004-02-18 00:08:52 +01:00
|
|
|
List_iterator<Item> it_ke(*key_expr);
|
2002-01-29 17:32:16 +01:00
|
|
|
Item *item;
|
|
|
|
for (key_len=0 ; (item=it_ke++) ; key_part++)
|
|
|
|
{
|
2004-02-18 00:08:52 +01:00
|
|
|
// 'item' can be changed by fix_fields() call
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((!item->fixed &&
|
2005-07-01 06:05:42 +02:00
|
|
|
item->fix_fields(thd, it_ke.ref())) ||
|
2004-02-18 00:08:52 +01:00
|
|
|
(item= *it_ke.ref())->check_cols(1))
|
2003-07-04 12:55:25 +02:00
|
|
|
goto err;
|
|
|
|
if (item->used_tables() & ~RAND_TABLE_BIT)
|
|
|
|
{
|
|
|
|
my_error(ER_WRONG_ARGUMENTS,MYF(0),"HANDLER ... READ");
|
|
|
|
goto err;
|
|
|
|
}
|
2002-12-05 18:38:42 +01:00
|
|
|
(void) item->save_in_field(key_part->field, 1);
|
2002-01-29 17:32:16 +01:00
|
|
|
key_len+=key_part->store_length;
|
|
|
|
}
|
2002-12-03 12:08:25 +01:00
|
|
|
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
|
2002-01-29 17:32:16 +01:00
|
|
|
goto err;
|
2005-06-07 22:43:25 +02:00
|
|
|
table->file->ha_index_or_rnd_end();
|
|
|
|
table->file->ha_index_init(keyno);
|
2004-08-27 15:37:13 +02:00
|
|
|
key_copy(key, table->record[0], table->key_info + keyno, key_len);
|
2004-10-29 18:26:52 +02:00
|
|
|
error= table->file->index_read(table->record[0],
|
2002-01-29 17:32:16 +01:00
|
|
|
key,key_len,ha_rkey_mode);
|
|
|
|
mode=rkey_to_rnext[(int)ha_rkey_mode];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), MYF(0));
|
2002-01-29 17:32:16 +01:00
|
|
|
goto err;
|
2001-04-09 15:37:19 +02:00
|
|
|
}
|
|
|
|
|
2004-10-29 18:26:52 +02:00
|
|
|
if (error)
|
2001-04-09 15:37:19 +02:00
|
|
|
{
|
2004-10-29 18:26:52 +02:00
|
|
|
if (error == HA_ERR_RECORD_DELETED)
|
|
|
|
continue;
|
2004-11-03 11:39:38 +01:00
|
|
|
if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
2001-04-13 16:18:44 +02:00
|
|
|
{
|
2003-11-12 22:33:28 +01:00
|
|
|
sql_print_error("mysql_ha_read: Got error %d when reading table '%s'",
|
2005-01-06 12:00:13 +01:00
|
|
|
error, tables->table_name);
|
2004-11-03 11:39:38 +01:00
|
|
|
table->file->print_error(error,MYF(0));
|
2001-04-13 16:18:44 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
goto ok;
|
|
|
|
}
|
2003-07-04 11:41:01 +02:00
|
|
|
if (cond && !cond->val_int())
|
|
|
|
continue;
|
Patch two (the final one) for Bug#7306 "the server side preparedStatement
error for LIMIT placeholder".
The patch adds grammar support for LIMIT ?, ? and changes the
type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*,
so that it can point to Item_param.
mysql-test/include/ps_modify.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/include/ps_query.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/r/ps.result:
Add basic test coverage for LIMIT ?, ? and fix test results.
mysql-test/r/ps_2myisam.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_3innodb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_4heap.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_5merge.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_6bdb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_7ndb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/t/ps.test:
Add basic test coverage for LIMIT ?, ?.
sql/item.h:
Add a short-cut for (ulonglong) val_int() to Item.
Add a constructor to Item_int() that accepts ulonglong.
Simplify Item_uint constructor by using the c-tor above.
sql/item_subselect.cc:
Now select_limit has type Item *.
We can safely create an Item in Item_exists_subselect::fix_length_and_dec():
it will be allocated in runtime memory root and freed in the end of
execution.
sql/sp_head.cc:
Add a special initalization state for stored procedures to
be able to easily distinguish the first execution of a stored procedure
from prepared statement prepare.
sql/sql_class.h:
Introduce new state 'INITIALIZED_FOR_SP' to be able to easily distinguish
the first execution of a stored procedure from prepared statement prepare.
sql/sql_derived.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace. Add a warning about use of set_limit in
mysql_derived_filling.
sql/sql_error.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace.
- this change is also aware of bug#11095 "show warnings limit 0 returns
all rows instead of zero rows", so the one who merges the bugfix from
4.1 can use local version of sql_error.cc.
sql/sql_handler.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
sql/sql_lex.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_lex.h:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_parse.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
- we can create an Item_int to set global limit of a statement:
it will be created in the runtime mem root and freed in the end of
execution.
sql/sql_repl.cc:
Use unit->set_limit to initialize limits.
sql/sql_select.cc:
- select_limit is now Item* so the proper way to check for default value
is to compare it with NULL.
sql/sql_union.cc:
Evaluate offset_limit_cnt using the new type of ST_SELECT_LEX::offset_limit
sql/sql_view.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_yacc.yy:
Add grammar support for LIMIT ?, ? clause.
2005-06-07 12:11:36 +02:00
|
|
|
if (num_rows >= offset_limit_cnt)
|
2001-12-21 14:28:51 +01:00
|
|
|
{
|
2003-07-04 11:41:01 +02:00
|
|
|
Item *item;
|
|
|
|
protocol->prepare_for_resend();
|
|
|
|
it.rewind();
|
|
|
|
while ((item=it++))
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2003-07-04 11:41:01 +02:00
|
|
|
if (item->send(thd->protocol, &buffer))
|
|
|
|
{
|
|
|
|
protocol->free(); // Free used
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
2003-07-04 11:41:01 +02:00
|
|
|
goto err;
|
|
|
|
}
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
2003-07-04 11:41:01 +02:00
|
|
|
protocol->write();
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
2001-04-13 16:18:44 +02:00
|
|
|
num_rows++;
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
2001-04-13 16:18:44 +02:00
|
|
|
ok:
|
|
|
|
mysql_unlock_tables(thd,lock);
|
2002-10-02 12:33:08 +02:00
|
|
|
send_eof(thd);
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit",("OK"));
|
2004-11-12 14:36:31 +01:00
|
|
|
DBUG_RETURN(FALSE);
|
2004-10-06 16:20:39 +02:00
|
|
|
|
2001-04-13 16:18:44 +02:00
|
|
|
err:
|
|
|
|
mysql_unlock_tables(thd,lock);
|
2002-01-03 15:31:54 +01:00
|
|
|
err0:
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("exit",("ERROR"));
|
2004-11-12 14:36:31 +01:00
|
|
|
DBUG_RETURN(TRUE);
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
|
2004-06-24 15:06:56 +02:00
|
|
|
/*
|
2004-09-24 18:39:25 +02:00
|
|
|
Flush (close) a list of HANDLER tables.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
SYNOPSIS
|
2004-09-24 18:39:25 +02:00
|
|
|
mysql_ha_flush()
|
2004-06-24 15:06:56 +02:00
|
|
|
thd Thread identifier.
|
2004-09-24 18:39:25 +02:00
|
|
|
tables The list of tables to close. If NULL,
|
|
|
|
close all HANDLER tables [marked as flushed].
|
|
|
|
mode_flags MYSQL_HA_CLOSE_FINAL finally close the table.
|
|
|
|
MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
|
|
|
|
MYSQL_HA_FLUSH_ALL flush all tables, not only
|
|
|
|
those marked for flush.
|
2005-11-15 21:57:02 +01:00
|
|
|
is_locked If LOCK_open is locked.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
DESCRIPTION
|
2004-09-24 18:39:25 +02:00
|
|
|
The list of HANDLER tables may be NULL, in which case all HANDLER
|
|
|
|
tables are closed (if MYSQL_HA_FLUSH_ALL) is set.
|
|
|
|
If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set,
|
|
|
|
all HANDLER tables marked for flush are closed.
|
2006-06-26 19:14:35 +02:00
|
|
|
Broadcasts refresh for every table closed.
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
NOTE
|
|
|
|
Since mysql_ha_flush() is called when the base table has to be closed,
|
|
|
|
we compare real table names, not aliases. Hence, database names matter.
|
2004-06-24 15:06:56 +02:00
|
|
|
|
|
|
|
RETURN
|
2004-09-24 18:39:25 +02:00
|
|
|
0 ok
|
2004-06-24 15:06:56 +02:00
|
|
|
*/
|
|
|
|
|
2005-11-15 21:57:02 +01:00
|
|
|
int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
|
|
|
|
bool is_locked)
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
TABLE_LIST *tmp_tables;
|
|
|
|
TABLE **table_ptr;
|
2005-11-15 21:57:02 +01:00
|
|
|
bool did_lock= FALSE;
|
2004-09-24 18:39:25 +02:00
|
|
|
DBUG_ENTER("mysql_ha_flush");
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags));
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
if (tables)
|
2001-04-07 00:18:33 +02:00
|
|
|
{
|
2004-09-24 18:39:25 +02:00
|
|
|
/* Close all tables in the list. */
|
2004-10-29 18:26:52 +02:00
|
|
|
for (tmp_tables= tables ; tmp_tables; tmp_tables= tmp_tables->next_local)
|
2003-11-18 22:06:47 +01:00
|
|
|
{
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("info-in-tables-list",("'%s'.'%s' as '%s'",
|
2005-01-06 12:00:13 +01:00
|
|
|
tmp_tables->db, tmp_tables->table_name,
|
2004-10-06 16:20:39 +02:00
|
|
|
tmp_tables->alias));
|
2004-09-24 18:39:25 +02:00
|
|
|
/* Close all currently open handler tables with the same base table. */
|
|
|
|
table_ptr= &(thd->handler_tables);
|
|
|
|
while (*table_ptr)
|
2003-11-18 22:06:47 +01:00
|
|
|
{
|
2005-01-06 12:00:13 +01:00
|
|
|
if ((!*tmp_tables->db ||
|
|
|
|
!my_strcasecmp(&my_charset_latin1, (*table_ptr)->s->db,
|
2004-10-07 09:50:13 +02:00
|
|
|
tmp_tables->db)) &&
|
2005-01-06 12:00:13 +01:00
|
|
|
! my_strcasecmp(&my_charset_latin1, (*table_ptr)->s->table_name,
|
|
|
|
tmp_tables->table_name))
|
2003-11-18 22:06:47 +01:00
|
|
|
{
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("info",("*table_ptr '%s'.'%s' as '%s'",
|
2005-01-06 12:00:13 +01:00
|
|
|
(*table_ptr)->s->db,
|
|
|
|
(*table_ptr)->s->table_name,
|
|
|
|
(*table_ptr)->alias));
|
2005-11-15 21:57:02 +01:00
|
|
|
/* The first time it is required, lock for close_thread_table(). */
|
|
|
|
if (! did_lock && ! is_locked)
|
|
|
|
{
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_open));
|
|
|
|
did_lock= TRUE;
|
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
mysql_ha_flush_table(thd, table_ptr, mode_flags);
|
|
|
|
continue;
|
2003-11-18 22:06:47 +01:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
table_ptr= &(*table_ptr)->next;
|
|
|
|
}
|
|
|
|
/* end of handler_tables list */
|
|
|
|
}
|
|
|
|
/* end of flush tables list */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Close all currently open tables [which are marked for flush]. */
|
|
|
|
table_ptr= &(thd->handler_tables);
|
|
|
|
while (*table_ptr)
|
|
|
|
{
|
|
|
|
if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
|
Fix for:
Bug #20662 "Infinite loop in CREATE TABLE IF NOT EXISTS ... SELECT
with locked tables"
Bug #20903 "Crash when using CREATE TABLE .. SELECT and triggers"
Bug #24738 "CREATE TABLE ... SELECT is not isolated properly"
Bug #24508 "Inconsistent results of CREATE TABLE ... SELECT when
temporary table exists"
Deadlock occured when one tried to execute CREATE TABLE IF NOT
EXISTS ... SELECT statement under LOCK TABLES which held
read lock on target table.
Attempt to execute the same statement for already existing
target table with triggers caused server crashes.
Also concurrent execution of CREATE TABLE ... SELECT statement
and other statements involving target table suffered from
various races (some of which might've led to deadlocks).
Finally, attempt to execute CREATE TABLE ... SELECT in case
when a temporary table with same name was already present
led to the insertion of data into this temporary table and
creation of empty non-temporary table.
All above problems stemmed from the old implementation of CREATE
TABLE ... SELECT in which we created, opened and locked target
table without any special protection in a separate step and not
with the rest of tables used by this statement.
This underminded deadlock-avoidance approach used in server
and created window for races. It also excluded target table
from prelocking causing problems with trigger execution.
The patch solves these problems by implementing new approach to
handling of CREATE TABLE ... SELECT for base tables.
We try to open and lock table to be created at the same time as
the rest of tables used by this statement. If such table does not
exist at this moment we create and place in the table cache special
placeholder for it which prevents its creation or any other usage
by other threads.
We still use old approach for creation of temporary tables.
Also note that we decided to postpone introduction of some tests
for concurrent behaviour of CREATE TABLE ... SELECT till 5.1.
The main reason for this is absence in 5.0 ability to set @@debug
variable at runtime, which can be circumvented only by using several
test files with individual .opt files. Since the latter is likely
to slowdown test-suite unnecessary we chose not to push this tests
into 5.0, but run them manually for this version and later push
their optimized version into 5.1
mysql-test/r/create.result:
Extended test coverage for CREATE TABLE ... SELECT. In particular added
tests for bug #24508 "Inconsistent results of CREATE TABLE ... SELECT
when temporary table exists" and bug #20662 "Infinite loop in CREATE
TABLE IF NOT EXISTS ... SELECT with locked tables".
mysql-test/r/trigger.result:
Added test case for bug #20903 "Crash when using CREATE TABLE .. SELECT
and triggers"
mysql-test/t/create.test:
Extended test coverage for CREATE TABLE ... SELECT. In particular added
tests for bug #24508 "Inconsistent results of CREATE TABLE ... SELECT
when temporary table exists" and bug #20662 "Infinite loop in CREATE
TABLE IF NOT EXISTS ... SELECT with locked tables".
mysql-test/t/trigger.test:
Added test case for bug #20903 "Crash when using CREATE TABLE .. SELECT
and triggers"
sql/lock.cc:
Now for creation of name-lock placeholder in lock_table_name() we use
auxiliary function table_cache_insert_placeholder().
sql/mysql_priv.h:
Made build_table_path() function available outside of sql_table.cc file.
reopen_name_locked_table() now has 3rd argument which controls linking
in of table being opened into THD::open_tables (this is useful in
cases when placeholder used for name-locking is already linked into
this list).
Added declaration of auxiliary function table_cache_insert_placeholder()
which is used for creation of table placeholders for name-locking.
Added declaration of table_cache_has_open_placeholder() function which
can be used for checking if table cache contains an open placeholder for
the table and if this placeholder was created by another thread.
(This function is needed only in 5.0 where we use it in various versions
of CREATE TABLE in order to protect it from concurrent CREATE TABLE
... SELECT operations for the table. Starting from 5.1 we use different
approach so it is going to be removed there).
Made close_old_data_files() static within sql_base.cc file.
Added auxiliary drop_open_table() routine.
Moved declaration of refresh_version to table.h header to make it
accessible from inline methods of TABLE class.
MYSQL_OPEN_IGNORE_LOCKED_TABLES flag is no longer used. Instead
MYSQL_OPEN_TEMPORARY_ONLY option was added.
sql/sql_base.cc:
Added support for the new approach to the handling of CREATE TABLE
... SELECT for base tables.
Now we try to open and lock table to be created at the same time as
the rest of tables used by this statement. If such table does not
exist at this moment we create and place in the table cache special
placeholder for it which prevents its creation or any other usage
by other threads.
Note significant distinctions of this placeholder from the placeholder
used for normal name-lock: 1) It is treated like open table by other
name-locks so it does not allow name-lock taking operations like DROP
TABLE or RENAME TABLE to proceed. 2) it is linked into THD::open_tables
list and automatically removed during close_thread_tables() call.
open_tables():
Implemented logic described above. To do this added
auxiliary check_if_table_exists() function.
Removed support for MYSQL_OPEN_IGNORE_LOCKED_TABLES option
which is no longer used.
Added MYSQL_OPEN_TEMPORARY_ONLY which is used to restrict
search for temporary tables only.
close_cached_tables()/close_thread_table()/reopen_tables()/
close_old_data_files()/table_is_used()/remove_table_from_cache():
Added support for open placeholders (note that we also use them
when we need to re-open tables during flush).
Added auxiliary drop_open_table() routine.
reopen_name_locked_table():
Now has 3rd argument which controls linking in of table being
opened into THD::open_tables (this is useful in cases when
placeholder used for name-locking is already linked into
this list).
Added auxiliary table_cache_insert_placeholder() routine which
simplifies creation of placeholders used for name-locking.
Added table_cache_has_open_placeholder() function which can be
used for checking if table cache contains an open placeholder for
the table and if this placeholder was created by another thread.
(This function is needed only in 5.0 where we use it in various versions
of CREATE TABLE in order to protect it from concurrent CREATE TABLE
... SELECT operations for the table. Starting from 5.1 we use different
approach so it is going to be removed there).
sql/sql_handler.cc:
Adjusted mysql_ha_mark_tables_for_reopen() routine to properly
handle placeholders which now can be linked into open tables
list.
sql/sql_insert.cc:
Introduced new approach to handling of base tables in CREATE TABLE
... SELECT statement.
Now we try to open and lock table to be created at the same time as
the rest of tables used by this statement. If such table does not
exist at this moment we create and place in the table cache special
placeholder for it which prevents its creation or any other usage
by other threads. By doing this we avoid races which existed with
previous approach in which we created, opened and locked target in
separate step without any special protection.
This also allows properly calculate prelocking set in cases when
target table already exists and has some on insert triggers.
Note that we don't employ the same approach for temporary tables
(this is okay as such tables are unaffected by other threads).
Changed create_table_from_items() and select_create methods to
implement this approach.
sql/sql_parse.cc:
The new approach to handling of CREATE TABLE ... SELECT for
base tables assumes that all tables (including table to be
created) are opened and (or) locked at the same time.
So in cases when we create base table we have to pass to
open_and_lock_tables() table list which includes target table.
sql/sql_prepare.cc:
The new approach to handling of CREATE TABLE ... SELECT for
base tables assumes that all tables (including table to be
created) are opened and (or) locked at the same time.
So in cases when we create base table we have to pass to
open_and_lock_tables() table list which includes target table.
sql/sql_table.cc:
Now mysql_create_table_internal(), mysql_create_like_table() and
mysql_alter_table() not only check that destination table doesn't
exist on disk but also check that there is no create placeholder
in table cache for it (i.e. there is no CREATE TABLE ... SELECT
operation in progress for it). Note that starting from 5.1 we
use different approach in order to to protect CREATE TABLE ... SELECT
from concurrent CREATE TABLE (ALTER TABLE ... RENAME) operations,
the latter simply take name-locks on table before its creation
(on target table name before renaming).
Also made build_table_path() available from other files and
asjusted calls to reopen_name_locked_table(), which now takes
extra argument, which controls linking of open table into
THD::open_tables list.
sql/sql_trigger.cc:
reopen_name_locked_tables() now has one more argument which controls
linking of opened table into the THD::open_tables list.
sql/sql_yacc.yy:
The new approach to handling of CREATE TABLE ... SELECT statement
for base tables assumes that all tables including table to be
created are open and (or) locked at the same time. Therefore
we need to set correct lock for target table.
sql/table.h:
Moved declaration of refresh_version variable from mysql_priv.h
to make it accessible from inline methods of TABLE class.
Renamed TABLE::locked_by_flush member to open_placeholder since
now it is also used for taking exclusive name-lock and not only
by flush.
Introduced TABLE::is_name_opened() helper method which can be used
to distinguish TABLE instances corresponding to open tables or
placeholders for them from closed instances (e.g. due to their old
version). Also introduced TABLE::needs_reopen_or_name_lock() helper
which allows to check if TABLE instance corresponds to outdated
version of table or to name-lock placeholder.
Introduced TABLE_LIST::create member which marks elements of
table list corresponds to the table to be created.
Adjusted TABLE_LIST::placeholder() method to take into account
name-lock placeholders for tables to be created (this, for example,
allows to properly handle such placeholders in lock_tables()).
2007-05-11 18:33:13 +02:00
|
|
|
(*table_ptr)->needs_reopen_or_name_lock())
|
2004-09-24 18:39:25 +02:00
|
|
|
{
|
2005-11-15 21:57:02 +01:00
|
|
|
/* The first time it is required, lock for close_thread_table(). */
|
|
|
|
if (! did_lock && ! is_locked)
|
|
|
|
{
|
|
|
|
VOID(pthread_mutex_lock(&LOCK_open));
|
|
|
|
did_lock= TRUE;
|
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
mysql_ha_flush_table(thd, table_ptr, mode_flags);
|
2003-11-18 22:06:47 +01:00
|
|
|
continue;
|
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
table_ptr= &(*table_ptr)->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-15 21:57:02 +01:00
|
|
|
/* Release the lock if it was taken by this function. */
|
|
|
|
if (did_lock)
|
|
|
|
VOID(pthread_mutex_unlock(&LOCK_open));
|
|
|
|
|
2004-09-24 18:39:25 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Flush (close) a table.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
mysql_ha_flush_table()
|
|
|
|
thd Thread identifier.
|
|
|
|
table The table to close.
|
|
|
|
mode_flags MYSQL_HA_CLOSE_FINAL finally close the table.
|
|
|
|
MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
|
|
|
|
|
|
|
|
DESCRIPTION
|
2006-06-26 19:14:35 +02:00
|
|
|
Broadcasts refresh if it closed the table.
|
2004-09-24 18:39:25 +02:00
|
|
|
The caller must lock LOCK_open.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 ok
|
|
|
|
*/
|
|
|
|
|
2004-10-06 16:20:39 +02:00
|
|
|
static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
|
2004-09-24 18:39:25 +02:00
|
|
|
{
|
|
|
|
TABLE_LIST *hash_tables;
|
|
|
|
TABLE *table= *table_ptr;
|
|
|
|
DBUG_ENTER("mysql_ha_flush_table");
|
2004-10-06 16:20:39 +02:00
|
|
|
DBUG_PRINT("enter",("'%s'.'%s' as '%s' flags: 0x%02x",
|
2005-01-06 12:00:13 +01:00
|
|
|
table->s->db, table->s->table_name,
|
|
|
|
table->alias, mode_flags));
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
|
2005-11-16 10:23:42 +01:00
|
|
|
(byte*) table->alias,
|
|
|
|
strlen(table->alias) + 1)))
|
2004-09-24 18:39:25 +02:00
|
|
|
{
|
|
|
|
if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE))
|
|
|
|
{
|
|
|
|
/* This is a final close. Remove from hash. */
|
|
|
|
hash_delete(&thd->handler_tables_hash, (byte*) hash_tables);
|
2003-11-18 22:06:47 +01:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Mark table as closed, ready for re-open. */
|
|
|
|
hash_tables->table= NULL;
|
2003-11-18 22:06:47 +01:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
}
|
|
|
|
|
2005-11-03 18:24:12 +01:00
|
|
|
safe_mutex_assert_owner(&LOCK_open);
|
2004-10-07 09:50:13 +02:00
|
|
|
(*table_ptr)->file->ha_index_or_rnd_end();
|
2005-11-15 21:57:02 +01:00
|
|
|
safe_mutex_assert_owner(&LOCK_open);
|
2004-09-24 18:39:25 +02:00
|
|
|
if (close_thread_table(thd, table_ptr))
|
|
|
|
{
|
|
|
|
/* Tell threads waiting for refresh that something has happened */
|
2006-06-26 19:14:35 +02:00
|
|
|
broadcast_refresh();
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|
2004-09-24 18:39:25 +02:00
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
2001-04-07 00:18:33 +02:00
|
|
|
}
|