Below is the list of changes that have just been committed into a local
5.1 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.2240 06/07/07 14:11:35 dlenev@stripped +10 -0
Merge bk-internal.mysql.com:/home/bk/mysql-5.1-runtime
into jabberwock.site:/home/dlenev/mysql-5.1-bg18437
sql/sql_table.cc
1.357 06/07/07 14:11:30 dlenev@stripped +0 -1
Manual merge.
sql/table.cc
1.228 06/07/07 14:03:34 dlenev@stripped +0 -0
Auto merged
sql/sql_update.cc
1.199 06/07/07 14:03:34 dlenev@stripped +0 -0
Auto merged
sql/sql_trigger.cc
1.59 06/07/07 14:03:34 dlenev@stripped +0 -0
Auto merged
sql/sql_parse.cc
1.567 06/07/07 14:03:33 dlenev@stripped +0 -0
Auto merged
sql/sql_insert.cc
1.210 06/07/07 14:03:33 dlenev@stripped +0 -0
Auto merged
sql/mysql_priv.h
1.419 06/07/07 14:03:33 dlenev@stripped +0 -0
Auto merged
sql/log_event.cc
1.233 06/07/07 14:03:33 dlenev@stripped +0 -0
Auto merged
sql/ha_partition.cc
1.61 06/07/07 14:03:33 dlenev@stripped +0 -0
Auto merged
sql/ha_ndbcluster.cc
1.338 06/07/07 14:03:32 dlenev@stripped +0 -0
Auto merged
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: dlenev
# Host: jabberwock.site
# Root: /home/dlenev/mysql-5.1-bg18437/RESYNC
--- 1.232/sql/log_event.cc 2006-07-06 22:55:27 +04:00
+++ 1.233/sql/log_event.cc 2006-07-07 14:03:33 +04:00
@@ -6138,6 +6138,7 @@
thd->lex->sql_command= SQLCOM_REPLACE;
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); // Needed for ndbcluster
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE); // Needed for ndbcluster
table->file->extra(HA_EXTRA_IGNORE_NO_KEY); // Needed for ndbcluster
/*
TODO: the cluster team (Tomas?) says that it's better if the engine knows
--- 1.418/sql/mysql_priv.h 2006-07-06 13:33:16 +04:00
+++ 1.419/sql/mysql_priv.h 2006-07-07 14:03:33 +04:00
@@ -1694,6 +1694,7 @@
bool make_global_read_lock_block_commit(THD *thd);
bool set_protect_against_global_read_lock(void);
void unset_protect_against_global_read_lock(void);
+void broadcast_refresh(void);
/* Lock based on name */
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
--- 1.209/sql/sql_insert.cc 2006-07-06 22:31:40 +04:00
+++ 1.210/sql/sql_insert.cc 2006-07-07 14:03:33 +04:00
@@ -181,9 +181,6 @@
}
}
}
- if (table->found_next_number_field)
- table->mark_auto_increment_column();
- table->mark_columns_needed_for_insert();
// For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
@@ -414,6 +411,9 @@
thd->proc_info="update";
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (duplic == DUP_REPLACE &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
/*
let's *try* to start bulk inserts. It won't necessary
start them as values_list.elements should be greater than
@@ -442,6 +442,8 @@
error= 1;
}
+ table->mark_columns_needed_for_insert();
+
if (table_list->prepare_where(thd, 0, TRUE) ||
table_list->prepare_check_option(thd))
error= 1;
@@ -615,6 +617,9 @@
thd->next_insert_id=0; // Reset this if wrongly used
if (duplic != DUP_ERROR || ignore)
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ if (duplic == DUP_REPLACE &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
/* Reset value of LAST_INSERT_ID if no rows where inserted */
if (!info.copied && thd->insert_id_used)
@@ -1961,9 +1966,8 @@
{
int error;
ulong max_rows;
- bool using_ignore=0,
- using_bin_log= mysql_bin_log.is_open();
-
+ bool using_ignore= 0, using_opt_replace= 0,
+ using_bin_log= mysql_bin_log.is_open();
delayed_row *row;
DBUG_ENTER("handle_inserts");
@@ -2026,6 +2030,13 @@
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
using_ignore=1;
}
+ if (info.handle_duplicates == DUP_REPLACE &&
+ (!table->triggers ||
+ !table->triggers->has_delete_triggers()))
+ {
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
+ using_opt_replace= 1;
+ }
thd.clear_error(); // reset error for binlog
if (write_record(&thd, table, &info))
{
@@ -2038,6 +2049,11 @@
using_ignore=0;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
}
+ if (using_opt_replace)
+ {
+ using_opt_replace= 0;
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
+ }
if (table->s->blob_fields)
free_delayed_insert_blobs(table);
thread_safe_sub(delayed_rows_in_use,1,&LOCK_delayed_status);
@@ -2283,6 +2299,9 @@
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (info.handle_duplicates == DUP_REPLACE &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
thd->no_trans_update= 0;
thd->abort_on_warning= (!info.ignore &&
(thd->variables.sql_mode &
@@ -2292,6 +2311,10 @@
check_that_all_fields_are_given_values(thd, table, table_list)) ||
table_list->prepare_where(thd, 0, TRUE) ||
table_list->prepare_check_option(thd));
+
+ if (!res)
+ table->mark_columns_needed_for_insert();
+
DBUG_RETURN(res);
}
@@ -2482,6 +2505,7 @@
error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0;
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
if (info.copied || info.deleted || info.updated)
{
@@ -2766,6 +2790,9 @@
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
+ if (info.handle_duplicates == DUP_REPLACE &&
+ (!table->triggers || !table->triggers->has_delete_triggers()))
+ table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
if (!thd->prelocked_mode)
table->file->ha_start_bulk_insert((ha_rows) 0);
thd->no_trans_update= 0;
@@ -2773,8 +2800,10 @@
(thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
- DBUG_RETURN(check_that_all_fields_are_given_values(thd, table,
- table_list));
+ if (check_that_all_fields_are_given_values(thd, table, table_list))
+ DBUG_RETURN(1);
+ table->mark_columns_needed_for_insert();
+ DBUG_RETURN(0);
}
@@ -2848,6 +2877,7 @@
else
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
VOID(pthread_mutex_lock(&LOCK_open));
mysql_unlock_tables(thd, thd->extra_lock);
if (!table->s->tmp_table)
@@ -2873,6 +2903,7 @@
if (table)
{
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
+ table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
handlerton *table_type=table->s->db_type;
if (!table->s->tmp_table)
{
--- 1.566/sql/sql_parse.cc 2006-07-02 02:12:48 +04:00
+++ 1.567/sql/sql_parse.cc 2006-07-07 14:03:33 +04:00
@@ -66,7 +66,6 @@
static int check_for_max_user_connections(THD *thd, USER_CONN *uc);
#endif
static void decrease_user_connections(USER_CONN *uc);
-static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_multi_update_lock(THD *thd);
static void remove_escape(char *name);
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
@@ -111,8 +110,6 @@
"NON-EXISTING", "ACTIVE", "IDLE", "PREPARED"
};
-static char empty_c_string[1]= {0}; // Used for not defined 'db'
-
#ifdef __WIN__
static void test_signal(int sig_ptr)
{
@@ -315,8 +312,7 @@
thd->db is saved in caller and needs to be freed by caller if this
function returns 0
*/
- thd->db= 0;
- thd->db_length= 0;
+ thd->reset_db(NULL, 0);
if (mysql_change_db(thd, db, FALSE))
{
/* Send the error to the client */
@@ -356,9 +352,8 @@
if connect failed. Also in case of 'CHANGE USER' failure, current
database will be switched to 'no database selected'.
*/
- thd->db= 0;
- thd->db_length= 0;
-
+ thd->reset_db(NULL, 0);
+
USER_RESOURCES ur;
int res= acl_getroot(thd, &ur, passwd, passwd_len);
#ifndef EMBEDDED_LIBRARY
@@ -1365,7 +1360,8 @@
DBUG_RETURN(0);
}
- /* This works because items are allocated with sql_alloc() */
+
+/* This works because items are allocated with sql_alloc() */
void free_items(Item *item)
{
@@ -1379,7 +1375,7 @@
DBUG_VOID_RETURN;
}
- /* This works because items are allocated with sql_alloc() */
+/* This works because items are allocated with sql_alloc() */
void cleanup_items(Item *item)
{
@@ -1389,7 +1385,26 @@
DBUG_VOID_RETURN;
}
-int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
+/*
+ Handle COM_TABLE_DUMP command
+
+ SYNOPSIS
+ mysql_table_dump
+ thd thread handle
+ db database name or an empty string. If empty,
+ the current database of the connection is used
+ tbl_name name of the table to dump
+
+ NOTES
+ This function is written to handle one specific command only.
+
+ RETURN VALUE
+ 0 success
+ 1 error, the error message is set in THD
+*/
+
+static
+int mysql_table_dump(THD* thd, char* db, char* tbl_name)
{
TABLE* table;
TABLE_LIST* table_list;
@@ -1426,7 +1441,7 @@
goto err;
}
net_flush(&thd->net);
- if ((error= table->file->dump(thd,fd)))
+ if ((error= table->file->dump(thd,-1)))
my_error(ER_GET_ERRNO, MYF(0), error);
err:
@@ -1678,7 +1693,7 @@
}
tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
- mysql_table_dump(thd, db, tbl_name, -1);
+ mysql_table_dump(thd, db, tbl_name);
break;
}
case COM_CHANGE_USER:
@@ -1853,11 +1868,8 @@
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
&LOCK_status);
bzero((char*) &table_list,sizeof(table_list));
- if (!(table_list.db=thd->db))
- {
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
+ if (thd->copy_db_to(&table_list.db, 0))
break;
- }
pend= strend(packet);
thd->convert_string(&conv_name, system_charset_info,
packet, (uint) (pend-packet), thd->charset());
@@ -2205,6 +2217,34 @@
}
+/*
+ Create a TABLE_LIST object for an INFORMATION_SCHEMA table.
+
+ SYNOPSIS
+ prepare_schema_table()
+ thd thread handle
+ lex current lex
+ table_ident table alias if it's used
+ schema_table_idx the type of the INFORMATION_SCHEMA table to be
+ created
+
+ DESCRIPTION
+ This function is used in the parser to convert a SHOW or DESCRIBE
+ table_name command to a SELECT from INFORMATION_SCHEMA.
+ It prepares a SELECT_LEX and a TABLE_LIST object to represent the
+ given command as a SELECT parse tree.
+
+ NOTES
+ Due to the way this function works with memory and LEX it cannot
+ be used outside the parser (parse tree transformations outside
+ the parser break PS and SP).
+
+ RETURN VALUE
+ 0 success
+ 1 out of memory or SHOW commands are not allowed
+ in this version of the server.
+*/
+
int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
enum enum_schema_tables schema_table_idx)
{
@@ -2233,13 +2273,13 @@
DBUG_RETURN(1);
#else
{
- char *db= lex->select_lex.db ? lex->select_lex.db : thd->db;
- if (!db)
+ char *db;
+ if (lex->select_lex.db == NULL &&
+ thd->copy_db_to(&lex->select_lex.db, 0))
{
- my_message(ER_NO_DB_ERROR,
- ER(ER_NO_DB_ERROR), MYF(0)); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ DBUG_RETURN(1);
}
+ db= lex->select_lex.db;
remove_escape(db); // Fix escaped '_'
if (check_db_name(db))
{
@@ -2256,11 +2296,6 @@
db);
DBUG_RETURN(1);
}
- /*
- We need to do a copy to make this prepared statement safe if this
- was thd->db
- */
- lex->select_lex.db= thd->strdup(db);
break;
}
#endif
@@ -2390,17 +2425,37 @@
}
-/****************************************************************************
-** mysql_execute_command
-** Execute command saved in thd and current_lex->sql_command
-****************************************************************************/
+/*
+ Execute command saved in thd and current_lex->sql_command
+
+ SYNOPSIS
+ mysql_execute_command()
+ thd Thread handle
+
+ IMPLEMENTATION
+
+ Before every operation that can request a write lock for a table
+ wait if a global read lock exists. However do not wait if this
+ thread has locked tables already. No new locks can be requested
+ until the other locks are released. The thread that requests the
+ global read lock waits for write locked tables to become unlocked.
+
+ Note that wait_if_global_read_lock() sets a protection against a new
+ global read lock when it succeeds. This needs to be released by
+ start_waiting_global_read_lock() after the operation.
+
+ RETURN
+ FALSE OK
+ TRUE Error
+*/
bool
mysql_execute_command(THD *thd)
{
- bool res= FALSE;
- int result= 0;
- LEX *lex= thd->lex;
+ bool res= FALSE;
+ bool need_start_waiting= FALSE; // have protection against global read lock
+ int result= 0;
+ LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= &lex->select_lex;
/* first table of first SELECT_LEX */
@@ -2677,8 +2732,7 @@
case SQLCOM_BACKUP_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ if (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
@@ -2690,8 +2744,7 @@
case SQLCOM_RESTORE_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, INSERT_ACL, all_tables, 0) ||
+ if (check_table_access(thd, INSERT_ACL, all_tables, 0) ||
check_global_access(thd, FILE_ACL))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
@@ -2703,8 +2756,7 @@
case SQLCOM_ASSIGN_TO_KEYCACHE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_access(thd, INDEX_ACL, first_table->db,
+ if (check_access(thd, INDEX_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
goto error;
@@ -2714,8 +2766,7 @@
case SQLCOM_PRELOAD_KEYS:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_access(thd, INDEX_ACL, first_table->db,
+ if (check_access(thd, INDEX_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
goto error;
@@ -2777,8 +2828,8 @@
case SQLCOM_LOAD_MASTER_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (!first_table->db)
- first_table->db= thd->db;
+ DBUG_ASSERT(first_table->db); /* Must be set in the parser */
+
if (check_access(thd, CREATE_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
@@ -2865,7 +2916,8 @@
TABLE in the same way. That way we avoid that a new table is
created during a gobal read lock.
*/
- if (wait_if_global_read_lock(thd, 0, 1))
+ if (!thd->locked_tables &&
+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
{
res= 1;
goto end_with_restore_list;
@@ -2901,7 +2953,7 @@
{
update_non_unique_table_error(create_table, "CREATE", duplicate);
res= 1;
- goto end_with_restart_wait;
+ goto end_with_restore_list;
}
}
/* If we create merge table, we have to test tables in merge, too */
@@ -2917,7 +2969,7 @@
{
update_non_unique_table_error(tab, "CREATE", duplicate);
res= 1;
- goto end_with_restart_wait;
+ goto end_with_restore_list;
}
}
}
@@ -2962,13 +3014,6 @@
send_ok(thd);
}
-end_with_restart_wait:
- /*
- Release the protection against the global read lock and wake
- everyone, who might want to set a global read lock.
- */
- start_waiting_global_read_lock(thd);
-
/* put tables back for PS rexecuting */
end_with_restore_list:
lex->link_first_table_back(create_table, link_to_local);
@@ -3039,25 +3084,8 @@
my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
goto error;
}
- if (!select_lex->db)
- {
- /*
- In the case of ALTER TABLE ... RENAME we should supply the
- default database if the new name is not explicitly qualified
- by a database. (Bug #11493)
- */
- if (lex->alter_info.flags & ALTER_RENAME)
- {
- if (! thd->db)
- {
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
- goto error;
- }
- select_lex->db= thd->db;
- }
- else
- select_lex->db= first_table->db;
- }
+ /* Must be set in the parser */
+ DBUG_ASSERT(select_lex->db);
if (check_access(thd, priv_needed, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)) ||
@@ -3089,6 +3117,13 @@
if (end_active_trans(thd))
goto error;
+ if (!thd->locked_tables &&
+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ {
+ res= 1;
+ break;
+ }
+
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_alter_table(thd, select_lex->db, lex->name,
&lex->create_info,
@@ -3104,8 +3139,6 @@
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *table;
- if (check_db_used(thd, all_tables))
- goto error;
for (table= first_table; table; table= table->next_local->next_local)
{
if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
@@ -3162,8 +3195,7 @@
if (lex->only_view)
first_table->skip_temporary= 1;
- if (check_db_used(thd, all_tables) ||
- check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
+ if (check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db,
&first_table->grant.privilege, 0, 0,
test(first_table->schema_table)))
goto error;
@@ -3176,8 +3208,7 @@
case SQLCOM_CHECKSUM:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0))
+ if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0))
goto error; /* purecov: inspected */
res = mysql_checksum_table(thd, first_table, &lex->check_opt);
break;
@@ -3185,8 +3216,7 @@
case SQLCOM_REPAIR:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
+ if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_repair_table(thd, first_table, &lex->check_opt);
@@ -3207,8 +3237,7 @@
case SQLCOM_CHECK:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0))
+ if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res = mysql_check_table(thd, first_table, &lex->check_opt);
@@ -3219,8 +3248,7 @@
case SQLCOM_ANALYZE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
+ if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= mysql_analyze_table(thd, first_table, &lex->check_opt);
@@ -3242,8 +3270,7 @@
case SQLCOM_OPTIMIZE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
+ if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0))
goto error; /* purecov: inspected */
thd->enable_slow_log= opt_log_slow_admin_statements;
res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ?
@@ -3344,6 +3371,14 @@
break;
/* Skip first table, which is the table we are inserting in */
select_lex->context.table_list= first_table->next_local;
+
+ if (!thd->locked_tables &&
+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ {
+ res= 1;
+ break;
+ }
+
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
lex->update_list, lex->value_list,
lex->duplicates, lex->ignore);
@@ -3367,6 +3402,14 @@
select_lex->options|= SELECT_NO_UNLOCK;
unit->set_limit(select_lex);
+
+ if (! thd->locked_tables &&
+ ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1)))
+ {
+ res= 1;
+ break;
+ }
+
if (!(res= open_and_lock_tables(thd, all_tables)))
{
/* Skip first table, which is the table we are inserting in */
@@ -3434,6 +3477,14 @@
break;
DBUG_ASSERT(select_lex->offset_limit == 0);
unit->set_limit(select_lex);
+
+ if (!thd->locked_tables &&
+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ {
+ res= 1;
+ break;
+ }
+
res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list,
unit->select_limit_cnt, select_lex->options,
@@ -3447,6 +3498,13 @@
(TABLE_LIST *)thd->lex->auxilliary_table_list.first;
multi_delete *result;
+ if (!thd->locked_tables &&
+ !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1)))
+ {
+ res= 1;
+ break;
+ }
+
if ((res= multi_delete_precheck(thd, all_tables)))
break;
@@ -3632,7 +3690,7 @@
break;
case SQLCOM_LOCK_TABLES:
unlock_locked_tables(thd);
- if (check_db_used(thd, all_tables) || end_active_trans(thd))
+ if (end_active_trans(thd))
goto error;
if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0))
goto error;
@@ -3771,12 +3829,8 @@
}
case SQLCOM_ALTER_DB:
{
- char *db= lex->name ? lex->name : thd->db;
- if (!db)
- {
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
- break;
- }
+ char *db= lex->name;
+ DBUG_ASSERT(db); /* Must be set in the parser */
if (!strip_sp(db) || check_db_name(db))
{
my_error(ER_WRONG_DB_NAME, MYF(0), db);
@@ -4113,7 +4167,7 @@
case SQLCOM_FLUSH:
{
bool write_to_binlog;
- if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables))
+ if (check_global_access(thd,RELOAD_ACL))
goto error;
/*
reload_acl_and_cache() will tell us if we are allowed to write to the
@@ -4162,15 +4216,12 @@
#endif
case SQLCOM_HA_OPEN:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables) ||
- check_table_access(thd, SELECT_ACL, all_tables, 0))
+ if (check_table_access(thd, SELECT_ACL, all_tables, 0))
goto error;
res= mysql_ha_open(thd, first_table, 0);
break;
case SQLCOM_HA_CLOSE:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if (check_db_used(thd, all_tables))
- goto error;
res= mysql_ha_close(thd, first_table);
break;
case SQLCOM_HA_READ:
@@ -4180,8 +4231,6 @@
if a user has no permissions to read a table, he won't be
able to open it (with SQLCOM_HA_OPEN) in the first place.
*/
- if (check_db_used(thd, all_tables))
- goto error;
unit->set_limit(select_lex);
res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str,
lex->insert_list, lex->ha_rkey_mode, select_lex->where,
@@ -4311,23 +4360,11 @@
case SQLCOM_CREATE_SPFUNCTION:
{
uint namelen;
- char *name, *db;
+ char *name;
int result;
DBUG_ASSERT(lex->sphead != 0);
-
- if (!lex->sphead->m_db.str || !lex->sphead->m_db.str[0])
- {
- if (!thd->db)
- {
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- }
- lex->sphead->m_db.length= strlen(thd->db);
- lex->sphead->m_db.str= thd->db;
- }
+ DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */
if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0,
is_schema_db(lex->sphead->m_db.str)))
@@ -4444,34 +4481,17 @@
}
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
- /*
- We need to copy name and db in order to use them for
- check_routine_access which is called after lex->sphead has
- been deleted.
- */
- name= thd->strdup(name);
- lex->sphead->m_db.str= db= thd->strmake(lex->sphead->m_db.str,
- lex->sphead->m_db.length);
res= (result= lex->sphead->create(thd));
if (result == SP_OK)
{
- /*
- We must cleanup the unit and the lex here because
- sp_grant_privileges calls (indirectly) db_find_routine,
- which in turn may call MYSQLparse with THD::lex.
- TODO: fix db_find_routine to use a temporary lex.
- */
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* only add privileges if really neccessary */
if (sp_automatic_privileges && !opt_noacl &&
check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS,
- db, name,
+ lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1))
{
- if (sp_grant_privileges(thd, db, name,
+ if (sp_grant_privileges(thd, lex->sphead->m_db.str, name,
lex->sql_command == SQLCOM_CREATE_PROCEDURE))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_PROC_AUTO_GRANT_FAIL,
@@ -4479,6 +4499,9 @@
close_thread_tables(thd);
}
#endif
+ lex->unit.cleanup();
+ delete lex->sphead;
+ lex->sphead= 0;
send_ok(thd);
}
else
@@ -4895,7 +4918,8 @@
view_store_options(thd, first_table, &buff);
buff.append(STRING_WITH_LEN("VIEW "));
/* Test if user supplied a db (ie: we did not use thd->db) */
- if (first_table->db != thd->db && first_table->db[0])
+ if (first_table->db && first_table->db[0] &&
+ (thd->db == NULL || strcmp(first_table->db, thd->db)))
{
append_identifier(thd, &buff, first_table->db,
first_table->db_length);
@@ -5177,11 +5201,22 @@
*/
if (!(sql_command_flags[lex->sql_command] & CF_HAS_ROW_COUNT))
thd->row_count_func= -1;
- DBUG_RETURN(res || thd->net.report_error);
+
+ goto finish;
error:
- res= 1; // would be better to set res=1 before "goto error"
- goto end;
+ res= TRUE;
+
+finish:
+ if (need_start_waiting)
+ {
+ /*
+ Release the protection against the global read lock and wake
+ everyone, who might want to set a global read lock.
+ */
+ start_waiting_global_read_lock(thd);
+ }
+ DBUG_RETURN(res || thd->net.report_error);
}
@@ -5548,7 +5583,7 @@
(want_access & ~EXTRA_ACL) &&
thd->db)
tables->grant.privilege= want_access;
- else if (tables->db && tables->db == thd->db)
+ else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0)
{
if (found && !grant_option) // db already checked
tables->grant.privilege=found_access;
@@ -5694,24 +5729,6 @@
}
-static bool check_db_used(THD *thd,TABLE_LIST *tables)
-{
- for (; tables; tables= tables->next_global)
- {
- if (!tables->db)
- {
- if (!(tables->db=thd->db))
- {
- my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
- MYF(0)); /* purecov: tested */
- return TRUE; /* purecov: tested */
- }
- }
- }
- return FALSE;
-}
-
-
/****************************************************************************
Check stack size; Send error if there isn't enough stack to continue
****************************************************************************/
@@ -6353,19 +6370,8 @@
ptr->db= table->db.str;
ptr->db_length= table->db.length;
}
- else if (thd->db)
- {
- ptr->db= thd->db;
- ptr->db_length= thd->db_length;
- }
- else
- {
- /* The following can't be "" as we may do 'casedn_str()' on it */
- ptr->db= empty_c_string;
- ptr->db_length= 0;
- }
- if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute())
- ptr->db= thd->strdup(ptr->db);
+ else if (thd->copy_db_to(&ptr->db, &ptr->db_length))
+ DBUG_RETURN(0);
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
@@ -7418,8 +7424,7 @@
/* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0);
- if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
- check_table_access(thd, SELECT_ACL, tables, 0))
+ if (check_table_access(thd, SELECT_ACL, tables, 0))
DBUG_RETURN(TRUE);
/*
@@ -7519,8 +7524,7 @@
my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
DBUG_RETURN(TRUE);
}
- DBUG_RETURN(check_db_used(thd, tables) ||
- check_one_table_access(thd, UPDATE_ACL, tables));
+ DBUG_RETURN(check_one_table_access(thd, UPDATE_ACL, tables));
}
--- 1.356/sql/sql_table.cc 2006-07-06 22:55:28 +04:00
+++ 1.357/sql/sql_table.cc 2006-07-07 14:11:30 +04:00
@@ -35,9 +35,7 @@
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to,
- List<create_field> &create,
- enum enum_duplicates handle_duplicates,
- bool ignore,
+ List<create_field> &create, bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
static bool prepare_blob_field(THD *thd, create_field *sql_field);
@@ -4955,8 +4953,7 @@
HA_CREATE_INFO *lex_create_info,
TABLE_LIST *table_list,
List<create_field> &fields, List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates, bool ignore,
+ uint order_num, ORDER *order, bool ignore,
ALTER_INFO *alter_info, bool do_send_ok)
{
TABLE *table,*new_table=0;
@@ -5794,8 +5791,7 @@
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
new_table->next_number_field=new_table->found_next_number_field;
- error=copy_data_between_tables(table,new_table,create_list,
- handle_duplicates, ignore,
+ error=copy_data_between_tables(table, new_table, create_list, ignore,
order_num, order, &copied, &deleted);
}
thd->last_insert_id=next_insert_id; // Needed for correct log
@@ -6209,7 +6205,6 @@
static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
- enum enum_duplicates handle_duplicates,
bool ignore,
uint order_num, ORDER *order,
ha_rows *copied,
@@ -6308,8 +6303,7 @@
/* Tell handler that we have values for all columns in the to table */
to->use_all_columns();
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
- if (ignore ||
- handle_duplicates == DUP_REPLACE)
+ if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
thd->row_count= 0;
restore_record(to, s->default_values); // Create empty record
@@ -6336,7 +6330,7 @@
}
if ((error=to->file->ha_write_row((byte*) to->record[0])))
{
- if (!ignore || handle_duplicates != DUP_ERROR ||
+ if (!ignore ||
to->file->is_fatal_error(error, HA_CHECK_DUP))
{
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
@@ -6428,7 +6422,7 @@
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, lex->create_list,
lex->key_list, 0, (ORDER *) 0,
- DUP_ERROR, 0, &lex->alter_info, do_send_ok));
+ 0, &lex->alter_info, do_send_ok));
}
--- 1.227/sql/table.cc 2006-07-03 19:14:30 +04:00
+++ 1.228/sql/table.cc 2006-07-07 14:03:34 +04:00
@@ -3925,16 +3925,7 @@
void st_table::mark_columns_needed_for_delete()
{
if (triggers)
- {
- if (triggers->bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] ||
- triggers->bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER])
- {
- /* TODO: optimize to only add columns used by trigger */
- use_all_columns();
- return;
- }
- }
-
+ triggers->mark_fields_used(TRG_EVENT_DELETE);
if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
{
Field **reg_field;
@@ -3985,15 +3976,7 @@
{
DBUG_ENTER("mark_columns_needed_for_update");
if (triggers)
- {
- if (triggers->bodies[TRG_EVENT_UPDATE][TRG_ACTION_BEFORE] ||
- triggers->bodies[TRG_EVENT_UPDATE][TRG_ACTION_AFTER])
- {
- /* TODO: optimize to only add columns used by trigger */
- use_all_columns();
- DBUG_VOID_RETURN;
- }
- }
+ triggers->mark_fields_used(TRG_EVENT_UPDATE);
if (file->ha_table_flags() & HA_REQUIRES_KEY_COLUMNS_FOR_DELETE)
{
/* Mark all used key columns for read */
@@ -4036,13 +4019,14 @@
{
if (triggers)
{
- if (triggers->bodies[TRG_EVENT_INSERT][TRG_ACTION_BEFORE] ||
- triggers->bodies[TRG_EVENT_INSERT][TRG_ACTION_AFTER])
- {
- /* TODO: optimize to only add columns used by trigger */
- use_all_columns();
- return;
- }
+ /*
+ We don't need to mark columns which are used by ON DELETE and
+ ON UPDATE triggers, which may be invoked in case of REPLACE or
+ INSERT ... ON DUPLICATE KEY UPDATE, since before doing actual
+ row replacement or update write_record() will mark all table
+ fields as used.
+ */
+ triggers->mark_fields_used(TRG_EVENT_INSERT);
}
if (found_next_number_field)
mark_auto_increment_column();
--- 1.58/sql/sql_trigger.cc 2006-07-06 13:33:17 +04:00
+++ 1.59/sql/sql_trigger.cc 2006-07-07 14:03:34 +04:00
@@ -928,8 +928,7 @@
save_db.str= thd->db;
save_db.length= thd->db_length;
- thd->db_length= strlen(db);
- thd->db= (char *) db;
+ thd->reset_db((char*) db, strlen(db));
while ((trg_create_str= it++))
{
trg_sql_mode= itm++;
@@ -1038,8 +1037,7 @@
lex_end(&lex);
}
- thd->db= save_db.str;
- thd->db_length= save_db.length;
+ thd->reset_db(save_db.str, save_db.length);
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
@@ -1052,8 +1050,7 @@
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
- thd->db= save_db.str;
- thd->db_length= save_db.length;
+ thd->reset_db(save_db.str, save_db.length);
DBUG_RETURN(1);
}
--- 1.337/sql/ha_ndbcluster.cc 2006-07-02 02:12:47 +04:00
+++ 1.338/sql/ha_ndbcluster.cc 2006-07-07 14:03:32 +04:00
@@ -7424,7 +7424,7 @@
do
{
- Uint64 rows, commits, mem;
+ Uint64 rows, commits, fixed_mem, var_mem;
Uint32 size;
Uint32 count= 0;
Uint64 sum_rows= 0;
@@ -7462,7 +7462,10 @@
pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows);
pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits);
pOp->getValue(NdbDictionary::Column::ROW_SIZE, (char*)&size);
- pOp->getValue(NdbDictionary::Column::FRAGMENT_MEMORY, (char*)&mem);
+ pOp->getValue(NdbDictionary::Column::FRAGMENT_FIXED_MEMORY,
+ (char*)&fixed_mem);
+ pOp->getValue(NdbDictionary::Column::FRAGMENT_VARSIZED_MEMORY,
+ (char*)&var_mem);
if (pTrans->execute(NdbTransaction::NoCommit,
NdbTransaction::AbortOnError,
@@ -7478,7 +7481,7 @@
sum_commits+= commits;
if (sum_row_size < size)
sum_row_size= size;
- sum_mem+= mem;
+ sum_mem+= fixed_mem + var_mem;
count++;
}
@@ -9870,7 +9873,6 @@
}
else
{
-#ifdef NOT_YET
if (!current_thd->variables.new_mode)
{
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
@@ -9879,9 +9881,8 @@
ndbcluster_hton_name,
"LIST, RANGE and HASH partition disabled by default,"
" use --new option to enable");
- return HA_ERR_UNSUPPORTED;
+ DBUG_RETURN(HA_ERR_UNSUPPORTED);
}
-#endif
/*
Create a shadow field for those tables that have user defined
partitioning. This field stores the value of the partition
--- 1.60/sql/ha_partition.cc 2006-07-01 08:22:13 +04:00
+++ 1.61/sql/ha_partition.cc 2006-07-07 14:03:33 +04:00
@@ -4666,6 +4666,27 @@
*/
break;
}
+ case HA_EXTRA_WRITE_CAN_REPLACE:
+ case HA_EXTRA_WRITE_CANNOT_REPLACE:
+ {
+ /*
+ Informs handler that write_row() can replace rows which conflict
+ with row being inserted by PK/unique key without reporting error
+ to the SQL-layer.
+
+ This optimization is not safe for partitioned table in general case
+ since we may have to put new version of row into partition which is
+ different from partition in which old version resides (for example
+ when we partition by non-PK column or by some column which is not
+ part of unique key which were violated).
+ And since NDB which is the only engine at the moment that supports
+ this optimization handles partitioning on its own we simple disable
+ it here. (BTW for NDB this optimization is safe since it supports
+ only KEY partitioning and won't use this optimization for tables
+ which have additional unique constraints).
+ */
+ break;
+ }
default:
{
/* Temporary crash to discover what is wrong */
| Thread |
|---|
| • bk commit into 5.1 tree (dlenev:1.2240) | dlenev | 7 Jul |