Below is the list of changes that have just been committed into a local
5.0 repository of jani. When jani 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@stripped, 2007-04-12 12:50:02+03:00, jani@stripped +27 -0
Merge jamppa@stripped:/home/bk/mysql-5.0
into ua141d10.elisa.omakaista.fi:/home/my/bk/mysql-5.0-marvel
MERGE: 1.2425.1.16
client/mysqldump.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.257.1.2
mysql-test/r/sp.result@stripped, 2007-04-12 12:49:59+03:00,
jani@stripped +0 -0
Merged from main 5.0
MERGE: 1.222.1.2
mysql-test/t/sp.test@stripped, 2007-04-12 12:46:05+03:00, jani@stripped
+0 -1
Auto merged
MERGE: 1.212.1.2
mysys/my_malloc.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.12.1.1
mysys/my_static.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.17.1.1
mysys/safemalloc.c@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.27.1.1
ndb/src/mgmclient/CommandInterpreter.cpp@stripped, 2007-04-12 12:46:05+03:00,
jani@stripped +0 -0
Auto merged
MERGE: 1.72.1.4
sql-common/client.c@stripped, 2007-04-12 12:46:07+03:00, jani@stripped
+0 -0
Auto merged
MERGE: 1.110.1.1
sql-common/my_time.c@stripped, 2007-04-12 12:46:08+03:00, jani@stripped
+0 -0
Auto merged
MERGE: 1.31.1.1
sql/ha_archive.cc@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.83.1.1
sql/ha_innodb.cc@stripped, 2007-04-12 12:46:05+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.309.1.1
sql/ha_ndbcluster.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped
+0 -0
Auto merged
MERGE: 1.303.1.4
sql/handler.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.229.1.2
sql/item_cmpfunc.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped
+0 -0
Auto merged
MERGE: 1.241.1.1
sql/item_func.h@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.160.1.1
sql/log.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.206.1.3
sql/log_event.cc@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.229.1.1
sql/mysql_priv.h@stripped, 2007-04-12 12:46:06+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.440.1.1
sql/sp.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.127.1.1
sql/sp_head.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.239.1.1
sql/sql_delete.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.194.1.1
sql/sql_insert.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.228.1.1
sql/sql_load.cc@stripped, 2007-04-12 12:49:59+03:00, jani@stripped +2 -4
Merged from main 5.0
MERGE: 1.109.1.3
sql/sql_show.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.344.1.2
sql/sql_table.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.335.1.4
sql/sql_update.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0
-0
Auto merged
MERGE: 1.212.1.1
sql/table.cc@stripped, 2007-04-12 12:46:07+03:00, jani@stripped +0 -0
Auto merged
MERGE: 1.245.1.2
# 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: jani
# Host: ua141d10.elisa.omakaista.fi
# Root: /home/my/bk/mysql-5.0-marvel/RESYNC
--- 1.260/client/mysqldump.c 2007-04-12 12:50:13 +03:00
+++ 1.261/client/mysqldump.c 2007-04-12 12:50:13 +03:00
@@ -105,7 +105,8 @@
*lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
*where=0, *order_by=0,
*opt_compatible_mode_str= 0,
- *err_ptr= 0;
+ *err_ptr= 0,
+ *log_error_file= NULL;
static char **defaults_argv= 0;
static char compatible_mode_normal_str[255];
static ulong opt_compatible_mode= 0;
@@ -116,7 +117,9 @@
static int first_error=0;
static DYNAMIC_STRING extended_row;
#include <sslopt-vars.h>
-FILE *md_result_file= 0;
+FILE *md_result_file= 0;
+FILE *stderror_file=0;
+
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
#endif
@@ -306,6 +309,9 @@
0, 0, 0, 0, 0, 0},
{"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
(gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ {"log-error", OPT_ERROR_LOG_FILE, "Append warnings and errors to given file.",
+ (gptr*) &log_error_file, (gptr*) &log_error_file, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"master-data", OPT_MASTER_DATA,
"This causes the binary log position and filename to be appended to the "
"output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
@@ -3789,6 +3795,16 @@
free_resources(0);
exit(exit_code);
}
+
+ if (log_error_file)
+ {
+ if(!(stderror_file= freopen(log_error_file, "a+", stderr)))
+ {
+ free_resources(0);
+ exit(EX_MYSQLERR);
+ }
+ }
+
if (connect_to_db(current_host, current_user, opt_password))
{
free_resources(0);
@@ -3841,5 +3857,9 @@
if (!path)
write_footer(md_result_file);
free_resources();
+
+ if (stderror_file)
+ fclose(stderror_file);
+
return(first_error);
} /* main */
--- 1.231/sql/handler.cc 2007-04-12 12:50:13 +03:00
+++ 1.232/sql/handler.cc 2007-04-12 12:50:13 +03:00
@@ -2438,14 +2438,14 @@
Ask handler if the table exists in engine
RETURN
- 0 Table does not exist
- 1 Table exists
- # Error code
+ HA_ERR_NO_SUCH_TABLE Table does not exist
+ HA_ERR_TABLE_EXIST Table exists
+ # Error code
*/
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
{
- int error= 0;
+ int error= HA_ERR_NO_SUCH_TABLE;
DBUG_ENTER("ha_table_exists_in_engine");
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
#ifdef HAVE_NDBCLUSTER_DB
--- 1.242/sql/item_cmpfunc.cc 2007-04-12 12:50:13 +03:00
+++ 1.243/sql/item_cmpfunc.cc 2007-04-12 12:50:13 +03:00
@@ -1079,6 +1079,26 @@
}
+bool Item_func_opt_neg::eq(const Item *item, bool binary_cmp) const
+{
+ /* Assume we don't have rtti */
+ if (this == item)
+ return 1;
+ if (item->type() != FUNC_ITEM)
+ return 0;
+ Item_func *item_func=(Item_func*) item;
+ if (arg_count != item_func->arg_count ||
+ functype() != item_func->functype())
+ return 0;
+ if (negated != ((Item_func_opt_neg *) item_func)->negated)
+ return 0;
+ for (uint i=0; i < arg_count ; i++)
+ if (!args[i]->eq(item_func->arguments()[i], binary_cmp))
+ return 0;
+ return 1;
+}
+
+
void Item_func_interval::fix_length_and_dec()
{
use_decimal_comparison= (row->element_index(0)->result_type() == DECIMAL_RESULT)
||
--- 1.162/sql/item_func.h 2007-04-12 12:50:13 +03:00
+++ 1.163/sql/item_func.h 2007-04-12 12:50:13 +03:00
@@ -1414,7 +1414,7 @@
bool execute();
bool execute_impl(THD *thd);
bool init_result_field(THD *thd);
-
+
public:
Item_func_sp(Name_resolution_context *context_arg, sp_name *name);
@@ -1424,6 +1424,8 @@
virtual ~Item_func_sp()
{}
+
+ table_map used_tables() const { return RAND_TABLE_BIT; }
void cleanup();
--- 1.208/sql/log.cc 2007-04-12 12:50:14 +03:00
+++ 1.209/sql/log.cc 2007-04-12 12:50:14 +03:00
@@ -283,7 +283,7 @@
#ifdef __NT__
static int eventSource = 0;
-void setup_windows_event_source()
+static void setup_windows_event_source()
{
HKEY hRegKey= NULL;
DWORD dwError= 0;
@@ -2229,37 +2229,6 @@
} /* test_if_number */
-void print_buffer_to_file(enum loglevel level, const char *buffer)
-{
- time_t skr;
- struct tm tm_tmp;
- struct tm *start;
- DBUG_ENTER("print_buffer_to_file");
- DBUG_PRINT("enter",("buffer: %s", buffer));
-
- VOID(pthread_mutex_lock(&LOCK_error_log));
-
- skr=time(NULL);
- localtime_r(&skr, &tm_tmp);
- start=&tm_tmp;
- fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
- start->tm_year % 100,
- start->tm_mon+1,
- start->tm_mday,
- start->tm_hour,
- start->tm_min,
- start->tm_sec,
- (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
- "Warning" : "Note"),
- buffer);
-
- fflush(stderr);
-
- VOID(pthread_mutex_unlock(&LOCK_error_log));
- DBUG_VOID_RETURN;
-}
-
-
void sql_perror(const char *message)
{
#ifdef HAVE_STRERROR
@@ -2326,23 +2295,15 @@
}
#ifdef __NT__
-void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
- uint length, int buffLen)
+static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
+ size_t length, size_t buffLen)
{
HANDLE event;
- char *buffptr;
- LPCSTR *buffmsgptr;
+ char *buffptr= buff;
DBUG_ENTER("print_buffer_to_nt_eventlog");
- buffptr= buff;
- if (length > (uint)(buffLen-5))
- {
- char *newBuff= new char[length + 5];
- strcpy(newBuff, buff);
- buffptr= newBuff;
- }
- strmov(buffptr+length, "\r\n\r\n");
- buffmsgptr= (LPCSTR*) &buffptr; // Keep windows happy
+ /* Add ending CR/LF's to string, overwrite last chars if necessary */
+ strmov(buffptr+min(length, buffLen-5), "\r\n\r\n");
setup_windows_event_source();
if ((event= RegisterEventSource(NULL,"MySQL")))
@@ -2350,24 +2311,20 @@
switch (level) {
case ERROR_LEVEL:
ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
- buffmsgptr, NULL);
+ (LPCSTR*)&buffptr, NULL);
break;
case WARNING_LEVEL:
ReportEvent(event, EVENTLOG_WARNING_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
- buffmsgptr, NULL);
+ (LPCSTR*) &buffptr, NULL);
break;
case INFORMATION_LEVEL:
ReportEvent(event, EVENTLOG_INFORMATION_TYPE, 0, MSG_DEFAULT, NULL, 1,
- 0, buffmsgptr, NULL);
+ 0, (LPCSTR*) &buffptr, NULL);
break;
}
DeregisterEventSource(event);
}
- /* if we created a string buffer, then delete it */
- if (buffptr != buff)
- delete[] buffptr;
-
DBUG_VOID_RETURN;
}
#endif /* __NT__ */
@@ -2399,13 +2356,44 @@
va_list argsi __attribute__((unused)))
{}
#else /*!EMBEDDED_LIBRARY*/
+static void print_buffer_to_file(enum loglevel level, const char *buffer)
+{
+ time_t skr;
+ struct tm tm_tmp;
+ struct tm *start;
+ DBUG_ENTER("print_buffer_to_file");
+ DBUG_PRINT("enter",("buffer: %s", buffer));
+
+ VOID(pthread_mutex_lock(&LOCK_error_log));
+
+ skr=time(NULL);
+ localtime_r(&skr, &tm_tmp);
+ start=&tm_tmp;
+ fprintf(stderr, "%02d%02d%02d %2d:%02d:%02d [%s] %s\n",
+ start->tm_year % 100,
+ start->tm_mon+1,
+ start->tm_mday,
+ start->tm_hour,
+ start->tm_min,
+ start->tm_sec,
+ (level == ERROR_LEVEL ? "ERROR" : level == WARNING_LEVEL ?
+ "Warning" : "Note"),
+ buffer);
+
+ fflush(stderr);
+
+ VOID(pthread_mutex_unlock(&LOCK_error_log));
+ DBUG_VOID_RETURN;
+}
+
+
void vprint_msg_to_log(enum loglevel level, const char *format, va_list args)
{
char buff[1024];
- uint length;
+ size_t length;
DBUG_ENTER("vprint_msg_to_log");
- length= my_vsnprintf(buff, sizeof(buff)-5, format, args);
+ length= my_vsnprintf(buff, sizeof(buff), format, args);
print_buffer_to_file(level, buff);
#ifdef __NT__
--- 1.443/sql/mysql_priv.h 2007-04-12 12:50:14 +03:00
+++ 1.444/sql/mysql_priv.h 2007-04-12 12:50:14 +03:00
@@ -842,6 +842,8 @@
bool ignore);
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
TABLE_LIST *table_list);
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+ enum_duplicates duplic);
void mark_fields_used_by_triggers_for_insert_stmt(THD *thd, TABLE *table,
enum_duplicates duplic);
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
--- 1.195/sql/sql_delete.cc 2007-04-12 12:50:14 +03:00
+++ 1.196/sql/sql_delete.cc 2007-04-12 12:50:14 +03:00
@@ -217,7 +217,19 @@
thd->proc_info="updating";
if (table->triggers)
+ {
table->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+ if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER DELETE triggers that might access to subject table
+ and therefore might need delete to be done immediately. So we turn-off
+ the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+ }
+ }
while (!(error=info.read_record(&info)) && !thd->killed &&
!thd->net.report_error)
@@ -540,7 +552,19 @@
else
normal_tables= 1;
if (tbl->triggers)
+ {
tbl->triggers->mark_fields_used(thd, TRG_EVENT_DELETE);
+ if (tbl->triggers->has_triggers(TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER DELETE triggers that might access to subject
+ table and therefore might need delete to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) tbl->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+ }
+ }
}
else if ((tab->type != JT_SYSTEM && tab->type != JT_CONST) &&
walk == delete_tables)
--- 1.229/sql/sql_insert.cc 2007-04-12 12:50:14 +03:00
+++ 1.230/sql/sql_insert.cc 2007-04-12 12:50:14 +03:00
@@ -330,6 +330,51 @@
/*
+ Prepare triggers for INSERT-like statement.
+
+ SYNOPSIS
+ prepare_triggers_for_insert_stmt()
+ thd The current thread
+ table Table to which insert will happen
+ duplic Type of duplicate handling for insert which will happen
+
+ NOTE
+ Prepare triggers for INSERT-like statement by marking fields
+ used by triggers and inform handlers that batching of UPDATE/DELETE
+ cannot be done if there are BEFORE UPDATE/DELETE triggers.
+*/
+
+void prepare_triggers_for_insert_stmt(THD *thd, TABLE *table,
+ enum_duplicates duplic)
+{
+ if (table->triggers)
+ {
+ if (table->triggers->has_triggers(TRG_EVENT_DELETE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER DELETE triggers that might access to
+ subject table and therefore might need delete to be done
+ immediately. So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_DELETE_CANNOT_BATCH);
+ }
+ if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER UPDATE triggers that might access to subject
+ table and therefore might need update to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+ }
+ mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+ }
+}
+
+
+/*
Mark fields used by triggers for INSERT-like statement.
SYNOPSIS
@@ -589,7 +634,7 @@
(MODE_STRICT_TRANS_TABLES |
MODE_STRICT_ALL_TABLES)));
- mark_fields_used_by_triggers_for_insert_stmt(thd, table, duplic);
+ prepare_triggers_for_insert_stmt(thd, table, duplic);
if (table_list->prepare_where(thd, 0, TRUE) ||
table_list->prepare_check_option(thd))
@@ -2528,8 +2573,8 @@
table_list->prepare_check_option(thd));
if (!res)
- mark_fields_used_by_triggers_for_insert_stmt(thd, table,
- info.handle_duplicates);
+ prepare_triggers_for_insert_stmt(thd, table,
+ info.handle_duplicates);
DBUG_RETURN(res);
}
--- 1.111/sql/sql_load.cc 2007-04-12 12:50:14 +03:00
+++ 1.112/sql/sql_load.cc 2007-04-12 12:50:14 +03:00
@@ -222,7 +222,7 @@
DBUG_RETURN(TRUE);
}
- mark_fields_used_by_triggers_for_insert_stmt(thd, table, handle_duplicates);
+ prepare_triggers_for_insert_stmt(thd, table, handle_duplicates);
uint tot_length=0;
bool use_blobs= 0, use_vars= 0;
@@ -532,7 +532,7 @@
Item_field *sql_field;
TABLE *table= table_list->table;
ulonglong id;
- bool no_trans_update_stmt;
+ bool no_trans_update_stmt, err;
DBUG_ENTER("read_fixed_length");
id= 0;
@@ -624,7 +624,9 @@
DBUG_RETURN(-1);
}
- if (write_record(thd, table, &info))
+ err= write_record(thd, table, &info);
+ table->auto_increment_field_not_null= FALSE;
+ if (err)
DBUG_RETURN(1);
thd->no_trans_update.stmt= no_trans_update_stmt;
@@ -669,7 +671,7 @@
TABLE *table= table_list->table;
uint enclosed_length;
ulonglong id;
- bool no_trans_update_stmt;
+ bool no_trans_update_stmt, err;
DBUG_ENTER("read_sep_field");
enclosed_length=enclosed.length();
@@ -716,8 +718,6 @@
DBUG_RETURN(1);
}
field->set_null();
- if (field == table->next_number_field)
- table->auto_increment_field_not_null= TRUE;
if (!field->maybe_null())
{
if (field->type() == FIELD_TYPE_TIMESTAMP)
@@ -803,8 +803,9 @@
DBUG_RETURN(-1);
}
-
- if (write_record(thd, table, &info))
+ err= write_record(thd, table, &info);
+ table->auto_increment_field_not_null= FALSE;
+ if (err)
DBUG_RETURN(1);
/*
If auto_increment values are used, save the first one for
--- 1.345/sql/sql_show.cc 2007-04-12 12:50:14 +03:00
+++ 1.346/sql/sql_show.cc 2007-04-12 12:50:14 +03:00
@@ -496,9 +496,9 @@
}
#endif
if (!my_strcasecmp(system_charset_info, dbname,
- information_schema_name.str))
+ INFORMATION_SCHEMA_NAME.str))
{
- dbname= information_schema_name.str;
+ dbname= INFORMATION_SCHEMA_NAME.str;
create.default_table_charset= system_charset_info;
}
else
@@ -1823,7 +1823,8 @@
/* INFORMATION_SCHEMA name */
-LEX_STRING information_schema_name= {(char*)"information_schema", 18};
+LEX_STRING INFORMATION_SCHEMA_NAME=
+ { (char *) STRING_WITH_LEN("information_schema") };
/* This is only used internally, but we need it here as a forward reference */
extern ST_SCHEMA_TABLE schema_tables[];
@@ -2039,11 +2040,11 @@
*/
if (!idx_field_vals->db_value ||
!wild_case_compare(system_charset_info,
- information_schema_name.str,
+ INFORMATION_SCHEMA_NAME.str,
idx_field_vals->db_value))
{
*with_i_schema= 1;
- if (files->push_back(thd->strdup(information_schema_name.str)))
+ if (files->push_back(thd->strdup(INFORMATION_SCHEMA_NAME.str)))
return 1;
}
return (find_files(thd, files, NullS, mysql_data_home,
@@ -2058,11 +2059,11 @@
*/
if (lex->orig_sql_command != SQLCOM_END)
{
- if (!my_strcasecmp(system_charset_info, information_schema_name.str,
+ if (!my_strcasecmp(system_charset_info, INFORMATION_SCHEMA_NAME.str,
idx_field_vals->db_value))
{
*with_i_schema= 1;
- return files->push_back(thd->strdup(information_schema_name.str));
+ return files->push_back(thd->strdup(INFORMATION_SCHEMA_NAME.str));
}
return files->push_back(thd->strdup(idx_field_vals->db_value));
}
@@ -2071,7 +2072,7 @@
Create list of existing databases. It is used in case
of select from information schema table
*/
- if (files->push_back(thd->strdup(information_schema_name.str)))
+ if (files->push_back(thd->strdup(INFORMATION_SCHEMA_NAME.str)))
return 1;
*with_i_schema= 1;
return (find_files(thd, files, NullS,
@@ -2147,7 +2148,7 @@
*/
thd->reset_n_backup_open_tables_state(&open_tables_state_backup);
- if (lsel)
+ if (lsel && lsel->table_list.first)
{
TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first;
bool res;
@@ -3936,8 +3937,8 @@
We have to make non const db_name & table_name
because of lower_case_table_names
*/
- make_lex_string(thd, &db, information_schema_name.str,
- information_schema_name.length, 0);
+ make_lex_string(thd, &db, INFORMATION_SCHEMA_NAME.str,
+ INFORMATION_SCHEMA_NAME.length, 0);
make_lex_string(thd, &table, schema_table->table_name,
strlen(schema_table->table_name), 0);
if (schema_table->old_format(thd, schema_table) || /* Handle old syntax */
--- 1.338/sql/sql_table.cc 2007-04-12 12:50:14 +03:00
+++ 1.339/sql/sql_table.cc 2007-04-12 12:50:14 +03:00
@@ -407,6 +407,7 @@
set_or_name "SET" or "ENUM" string for warning message
name name of the checked column
typelib list of values for the column
+ dup_val_count returns count of duplicate elements
DESCRIPTION
This function prints an warning for each value in list
@@ -418,11 +419,12 @@
void check_duplicates_in_interval(const char *set_or_name,
const char *name, TYPELIB *typelib,
- CHARSET_INFO *cs)
+ CHARSET_INFO *cs, unsigned int *dup_val_count)
{
TYPELIB tmp= *typelib;
const char **cur_value= typelib->type_names;
unsigned int *cur_length= typelib->type_lengths;
+ *dup_val_count= 0;
for ( ; tmp.count > 1; cur_value++, cur_length++)
{
@@ -435,6 +437,7 @@
ER_DUPLICATED_VALUE_IN_TYPE,
ER(ER_DUPLICATED_VALUE_IN_TYPE),
name,*cur_value,set_or_name);
+ (*dup_val_count)++;
}
}
}
@@ -498,6 +501,7 @@
int *timestamps, int *timestamps_with_niladic,
uint table_flags)
{
+ unsigned int dup_val_count;
DBUG_ENTER("prepare_field");
/*
@@ -573,7 +577,7 @@
sql_field->unireg_check=Field::INTERVAL_FIELD;
check_duplicates_in_interval("ENUM",sql_field->field_name,
sql_field->interval,
- sql_field->charset);
+ sql_field->charset, &dup_val_count);
break;
case FIELD_TYPE_SET:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -583,7 +587,13 @@
sql_field->unireg_check=Field::BIT_FIELD;
check_duplicates_in_interval("SET",sql_field->field_name,
sql_field->interval,
- sql_field->charset);
+ sql_field->charset, &dup_val_count);
+ /* Check that count of unique members is not more then 64 */
+ if (sql_field->interval->count - dup_val_count > sizeof(longlong)*8)
+ {
+ my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
+ DBUG_RETURN(1);
+ }
break;
case FIELD_TYPE_DATE: // Rest of string types
case FIELD_TYPE_NEWDATE:
@@ -1697,6 +1707,7 @@
alias);
DBUG_RETURN(FALSE);
}
+ DBUG_PRINT("info",("1"));
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
DBUG_RETURN(TRUE);
}
@@ -1707,6 +1718,7 @@
{
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
goto warn;
+ DBUG_PRINT("info",("2"));
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
goto end;
}
@@ -1725,14 +1737,25 @@
{
bool create_if_not_exists =
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
- if (ha_table_exists_in_engine(thd, db, table_name))
- {
- DBUG_PRINT("info", ("Table with same name already existed in handler"));
-
- if (create_if_not_exists)
- goto warn;
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
- goto end;
+ int retcode = ha_table_exists_in_engine(thd, db, table_name);
+ DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
+ switch (retcode)
+ {
+ case HA_ERR_NO_SUCH_TABLE:
+ /* Normal case, no table exists. we can go and create it */
+ break;
+ case HA_ERR_TABLE_EXIST:
+ DBUG_PRINT("info", ("Table existed in handler"));
+
+ if (create_if_not_exists)
+ goto warn;
+ my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ goto end;
+ break;
+ default:
+ DBUG_PRINT("info", ("error: %u from storage engine", retcode));
+ my_error(retcode, MYF(0),table_name);
+ goto end;
}
}
@@ -2068,7 +2091,9 @@
/*
Check if this is a table type that stores index and data separately,
- like ISAM or MyISAM
+ like ISAM or MyISAM. We assume fixed order of engine file name
+ extentions array. First element of engine file name extentions array
+ is meta/index file extention. Second element - data file extention.
*/
if (!ext[0] || !ext[1])
goto end; // No data file
--- 1.214/sql/sql_update.cc 2007-04-12 12:50:14 +03:00
+++ 1.215/sql/sql_update.cc 2007-04-12 12:50:14 +03:00
@@ -436,7 +436,19 @@
MODE_STRICT_ALL_TABLES)));
if (table->triggers)
+ {
table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+ if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER UPDATE triggers that might access to subject
+ table and therefore might need update to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+ }
+ }
/*
We can use compare_record() to optimize away updates if
@@ -1001,6 +1013,20 @@
table->no_keyread=1;
table->used_keys.clear_all();
table->pos_in_table_list= tl;
+ if (table->triggers)
+ {
+ table->triggers->mark_fields_used(thd, TRG_EVENT_UPDATE);
+ if (table->triggers->has_triggers(TRG_EVENT_UPDATE,
+ TRG_ACTION_AFTER))
+ {
+ /*
+ The table has AFTER UPDATE triggers that might access to subject
+ table and therefore might need update to be done immediately.
+ So we turn-off the batching.
+ */
+ (void) table->file->extra(HA_EXTRA_UPDATE_CANNOT_BATCH);
+ }
+ }
}
}
--- 1.84/sql/ha_archive.cc 2007-04-12 12:50:14 +03:00
+++ 1.85/sql/ha_archive.cc 2007-04-12 12:50:14 +03:00
@@ -503,8 +503,8 @@
We just implement one additional file extension.
*/
static const char *ha_archive_exts[] = {
- ARZ,
ARM,
+ ARZ,
NullS
};
--- 1.306/sql/ha_ndbcluster.cc 2007-04-12 12:50:14 +03:00
+++ 1.307/sql/ha_ndbcluster.cc 2007-04-12 12:50:14 +03:00
@@ -203,6 +203,8 @@
{ 284, HA_ERR_TABLE_DEF_CHANGED, 0 },
+ {4009, HA_ERR_NO_CONNECTION, 1 },
+
{ 0, 1, 0 },
{ -1, -1, 1 }
@@ -2521,8 +2523,13 @@
ERR_RETURN(op->getNdbError());
}
- // Execute update operation
- if (!cursor && execute_no_commit(this,trans,false) != 0) {
+ /*
+ Execute update operation if we are not doing a scan for update
+ and there exist UPDATE AFTER triggers
+ */
+
+ if ((!cursor || m_update_cannot_batch) &&
+ execute_no_commit(this,trans,false) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@@ -2563,7 +2570,7 @@
no_uncommitted_rows_update(-1);
- if (!m_primary_key_update)
+ if (!(m_primary_key_update || m_delete_cannot_batch))
// If deleting from cursor, NoCommit will be handled in next_result
DBUG_RETURN(0);
}
@@ -3404,6 +3411,16 @@
DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
m_use_write= FALSE;
break;
+ case HA_EXTRA_DELETE_CANNOT_BATCH:
+ DBUG_PRINT("info", ("HA_EXTRA_DELETE_CANNOT_BATCH"));
+ m_delete_cannot_batch= TRUE;
+ break;
+ case HA_EXTRA_UPDATE_CANNOT_BATCH:
+ DBUG_PRINT("info", ("HA_EXTRA_UPDATE_CANNOT_BATCH"));
+ m_update_cannot_batch= TRUE;
+ break;
+ default:
+ break;
}
DBUG_RETURN(0);
@@ -3420,6 +3437,8 @@
m_retrieve_primary_key= FALSE;
m_ignore_dup_key= FALSE;
m_use_write= FALSE;
+ m_delete_cannot_batch= FALSE;
+ m_update_cannot_batch= FALSE;
DBUG_RETURN(0);
}
@@ -4785,6 +4804,8 @@
m_bulk_insert_rows((ha_rows) 1024),
m_rows_changed((ha_rows) 0),
m_bulk_insert_not_flushed(FALSE),
+ m_delete_cannot_batch(FALSE),
+ m_update_cannot_batch(FALSE),
m_ops_pending(0),
m_skip_auto_increment(TRUE),
m_blobs_pending(0),
@@ -5067,14 +5088,11 @@
dict->invalidateTable(name);
if (!(tab= dict->getTable(name)))
{
- const NdbError err= dict->getNdbError();
- if (err.code == 709)
- DBUG_RETURN(0);
- ERR_RETURN(err);
+ ERR_RETURN(dict->getNdbError());
}
DBUG_PRINT("info", ("Found table %s", tab->getName()));
- DBUG_RETURN(1);
+ DBUG_RETURN(HA_ERR_TABLE_EXIST);
}
@@ -5259,7 +5277,7 @@
DBUG_PRINT("info", ("%s existed on disk", name));
// The .ndb file exists on disk, but it's not in list of tables in ndb
// Verify that handler agrees table is gone.
- if (ndbcluster_table_exists_in_engine(thd, db, file_name) == 0)
+ if (ndbcluster_table_exists_in_engine(thd, db, file_name) == HA_ERR_NO_SUCH_TABLE)
{
DBUG_PRINT("info", ("NDB says %s does not exists", file_name));
it.remove();
@@ -6696,7 +6714,8 @@
DBUG_RETURN(NULL);
}
- List<NDB_SHARE> util_open_tables;
+ uint share_list_size= 0;
+ NDB_SHARE **share_list= NULL;
set_timespec(abstime, 0);
for (;;)
{
@@ -6726,7 +6745,22 @@
/* Lock mutex and fill list with pointers to all open tables */
NDB_SHARE *share;
pthread_mutex_lock(&ndbcluster_mutex);
- for (uint i= 0; i < ndbcluster_open_tables.records; i++)
+ uint i, record_count= ndbcluster_open_tables.records;
+ if (share_list_size < record_count)
+ {
+ NDB_SHARE ** new_share_list= new NDB_SHARE * [record_count];
+ if (!new_share_list)
+ {
+ sql_print_warning("ndb util thread: malloc failure, "
+ "query cache not maintained properly");
+ pthread_mutex_unlock(&ndbcluster_mutex);
+ goto next; // At least do not crash
+ }
+ delete [] share_list;
+ share_list_size= record_count;
+ share_list= new_share_list;
+ }
+ for (i= 0; i < record_count; i++)
{
share= (NDB_SHARE *)hash_element(&ndbcluster_open_tables, i);
share->use_count++; /* Make sure the table can't be closed */
@@ -6735,14 +6769,14 @@
i, share->table_name, share->use_count));
/* Store pointer to table */
- util_open_tables.push_back(share);
+ share_list[i]= share;
}
pthread_mutex_unlock(&ndbcluster_mutex);
- /* Iterate through the open files list */
- List_iterator_fast<NDB_SHARE> it(util_open_tables);
- while ((share= it++))
+ /* Iterate through the open files list */
+ for (i= 0; i < record_count; i++)
{
+ share= share_list[i];
/* Split tab- and dbname */
char buf[FN_REFLEN];
char *tabname, *db;
@@ -6791,10 +6825,7 @@
/* Decrease the use count and possibly free share */
free_share(share);
}
-
- /* Clear the list of open tables */
- util_open_tables.empty();
-
+next:
/* Calculate new time to wake up */
int secs= 0;
int msecs= ndb_cache_check_time;
@@ -6817,6 +6848,8 @@
}
}
+ if (share_list)
+ delete [] share_list;
thd->cleanup();
delete thd;
delete ndb;
@@ -7114,7 +7147,7 @@
Check that the field is part of the table of the handler
instance and that we expect a field with of this result type.
*/
- if (context->table == field->table)
+ if (context->table->s == field->table->s)
{
const NDBTAB *tab= (const NDBTAB *) context->ndb_table;
DBUG_PRINT("info", ("FIELD_ITEM"));
--- 1.224/mysql-test/r/sp.result 2007-04-12 12:50:14 +03:00
+++ 1.225/mysql-test/r/sp.result 2007-04-12 12:50:14 +03:00
@@ -5969,6 +5969,21 @@
21.300000071526 NULL
DROP FUNCTION bug25373|
DROP TABLE t3|
+DROP DATABASE IF EXISTS mysqltest1|
+DROP DATABASE IF EXISTS mysqltest2|
+CREATE DATABASE mysqltest1|
+CREATE DATABASE mysqltest2|
+CREATE PROCEDURE mysqltest1.p1()
+DROP DATABASE mysqltest2|
+use mysqltest2|
+CALL mysqltest1.p1()|
+Warnings:
+Note 1049 Unknown database 'mysqltest2'
+SELECT DATABASE()|
+DATABASE()
+NULL
+DROP DATABASE mysqltest1|
+use test|
drop function if exists bug20777|
drop table if exists examplebug20777|
create function bug20777(f1 bigint unsigned) returns bigint unsigned
@@ -6055,3 +6070,28 @@
drop function bug20777;
End of 5.0 tests.
drop table t1,t2;
+CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
+CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
+set @a=0;
+CREATE function bug27354() RETURNS int deterministic
+begin
+insert into t1 values (null);
+set @a=@a+1;
+return @a;
+end|
+update t2 set b=1 where a=bug27354();
+select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */;
+count(t_1.a) count(t_2.a)
+0 0
+insert into t2 values (1,1),(2,2),(3,3);
+update t2 set b=-b where a=bug27354();
+select * from t2 /* must return 1,-1 ... */;
+a b
+1 -1
+2 -2
+3 -3
+select count(*) from t1 /* must be 3 */;
+count(*)
+3
+drop table t1,t2;
+drop function bug27354;
--- 1.214/mysql-test/t/sp.test 2007-04-12 12:50:14 +03:00
+++ 1.215/mysql-test/t/sp.test 2007-04-12 12:50:14 +03:00
@@ -6929,6 +6929,47 @@
SELECT SUM(f2), bug25373(f1) FROM t3 GROUP BY bug25373(f1) WITH ROLLUP|
DROP FUNCTION bug25373|
DROP TABLE t3|
+
+
+#
+# BUG#25082: Default database change on trigger execution breaks replication.
+#
+# As it turned out, this bug has actually two bugs. So, here we have two test
+# cases -- one in sp.test, the other in sp-security.test.
+#
+
+#
+# Test case 1: error on dropping the current database.
+#
+
+# Prepare.
+
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest1|
+DROP DATABASE IF EXISTS mysqltest2|
+--enable_warnings
+
+CREATE DATABASE mysqltest1|
+CREATE DATABASE mysqltest2|
+
+# Test.
+
+CREATE PROCEDURE mysqltest1.p1()
+ DROP DATABASE mysqltest2|
+
+use mysqltest2|
+
+CALL mysqltest1.p1()|
+
+SELECT DATABASE()|
+
+# Cleanup.
+
+DROP DATABASE mysqltest1|
+
+use test|
+
+
#
# Bug#20777: Function w BIGINT UNSIGNED shows diff. behaviour --ps-protocol
--disable_warnings
@@ -6996,3 +7037,26 @@
delimiter ;|
drop table t1,t2;
+CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
+CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
+set @a=0;
+
+delimiter |;
+CREATE function bug27354() RETURNS int deterministic
+begin
+insert into t1 values (null);
+set @a=@a+1;
+return @a;
+end|
+
+delimiter ;|
+update t2 set b=1 where a=bug27354();
+select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */;
+insert into t2 values (1,1),(2,2),(3,3);
+update t2 set b=-b where a=bug27354();
+select * from t2 /* must return 1,-1 ... */;
+select count(*) from t1 /* must be 3 */;
+
+
+drop table t1,t2;
+drop function bug27354;
--- 1.128/sql/sp.cc 2007-04-12 12:50:14 +03:00
+++ 1.129/sql/sp.cc 2007-04-12 12:50:14 +03:00
@@ -441,14 +441,14 @@
{
sp_head *sp= newlex.sphead;
- if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
+ if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE)))
goto end;
delete sp;
ret= SP_PARSE_ERROR;
}
else
{
- if (dbchanged && (ret= mysql_change_db(thd, old_db.str, 1)))
+ if (dbchanged && (ret= mysql_change_db(thd, &old_db, TRUE)))
goto end;
*sphp= newlex.sphead;
(*sphp)->set_definer(&definer_user_name, &definer_host_name);
@@ -1896,7 +1896,7 @@
DBUG_RETURN(0);
}
- ret= mysql_change_db(thd, new_db.str, no_access_check);
+ ret= mysql_change_db(thd, &new_db, no_access_check);
*dbchangedp= ret == 0;
DBUG_RETURN(ret);
--- 1.241/sql/sp_head.cc 2007-04-12 12:50:14 +03:00
+++ 1.242/sql/sp_head.cc 2007-04-12 12:50:14 +03:00
@@ -954,6 +954,12 @@
m_first_instance->m_last_cached_sp == this) ||
(m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
+ /*
+ NOTE: The SQL Standard does not specify the context that should be
+ preserved for stored routines. However, at SAP/Walldorf meeting it was
+ decided that current database should be preserved.
+ */
+
if (m_db.length &&
(err_status= sp_use_new_db(thd, m_db, &old_db, 0, &dbchanged)))
goto done;
| Thread |
|---|
| • bk commit into 5.0 tree (jani:1.2430) | jani | 12 Apr |