summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <guilhem@mysql.com>2005-11-19 10:43:28 +0100
committerunknown <guilhem@mysql.com>2005-11-19 10:43:28 +0100
commit380690316f2b14b80376d18da189505de35568f4 (patch)
tree50c76691f3d387a96de6c97132369326378c35ab /sql
parenta06f394e68a2aa0207a908198ef3fbdb938725da (diff)
parent6ba79a251681a765f491db1428a467a0a06a69bd (diff)
downloadmariadb-git-380690316f2b14b80376d18da189505de35568f4.tar.gz
Merge mysql.com:/home/mysql_src/mysql-5.0-van
into mysql.com:/home/mysql_src/mysql-5.1-merge-of-5.0 (2nd try; Pekka kindly accepted to fix storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp and storage/ndb/src/kernel/vm/SimulatedBlock.cpp after I push). configure.in: Auto merged mysql-test/r/ndb_charset.result: Auto merged mysql-test/t/view.test: Auto merged mysys/base64.c: Auto merged sql/ha_archive.cc: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_innodb.h: Auto merged sql/lock.cc: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/set_var.cc: Auto merged sql/sp_head.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_handler.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_select.cc: Auto merged sql/sql_show.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_yacc.yy: Auto merged storage/myisam/ft_parser.c: Auto merged storage/ndb/include/kernel/AttributeDescriptor.hpp: Auto merged storage/ndb/src/kernel/vm/SimulatedBlock.hpp: Auto merged storage/ndb/tools/ndb_size.pl: Auto merged storage/ndb/tools/ndb_size.tmpl: Auto merged mysql-test/t/disabled.def: merge storage/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp: used "ul", Pekka said he'll fix storage/ndb/src/kernel/vm/SimulatedBlock.cpp: used "ul", Pekka said he'll fix
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_archive.cc3
-rw-r--r--sql/ha_innodb.cc34
-rw-r--r--sql/ha_innodb.h5
-rw-r--r--sql/item.h6
-rw-r--r--sql/lock.cc18
-rw-r--r--sql/mysql_priv.h3
-rw-r--r--sql/mysqld.cc8
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sp_head.cc85
-rw-r--r--sql/sp_head.h13
-rw-r--r--sql/sql_base.cc7
-rw-r--r--sql/sql_class.cc2
-rw-r--r--sql/sql_handler.cc51
-rw-r--r--sql/sql_parse.cc12
-rw-r--r--sql/sql_prepare.cc18
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/sql_show.cc17
-rw-r--r--sql/sql_table.cc24
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/sql_yacc.yy60
20 files changed, 238 insertions, 144 deletions
diff --git a/sql/ha_archive.cc b/sql/ha_archive.cc
index 39f4c6667a0..488343c5402 100644
--- a/sql/ha_archive.cc
+++ b/sql/ha_archive.cc
@@ -249,7 +249,8 @@ ha_archive::ha_archive(TABLE *table_arg)
buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
/* The size of the offset value we will use for position() */
- ref_length = sizeof(z_off_t);
+ ref_length = 2 << ((zlibCompileFlags() >> 6) & 3);
+ DBUG_ASSERT(ref_length <= sizeof(z_off_t));
}
/*
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b84930a2870..7dcb0b677e5 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -141,15 +141,16 @@ uint innobase_init_flags = 0;
ulong innobase_cache_size = 0;
ulong innobase_large_page_size = 0;
-/* The default values for the following, type long, start-up parameters
-are declared in mysqld.cc: */
+/* The default values for the following, type long or longlong, start-up
+parameters are declared in mysqld.cc: */
long innobase_mirrored_log_groups, innobase_log_files_in_group,
- innobase_log_file_size, innobase_log_buffer_size,
- innobase_buffer_pool_awe_mem_mb,
- innobase_buffer_pool_size, innobase_additional_mem_pool_size,
- innobase_file_io_threads, innobase_lock_wait_timeout,
- innobase_force_recovery, innobase_open_files;
+ innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
+ innobase_additional_mem_pool_size, innobase_file_io_threads,
+ innobase_lock_wait_timeout, innobase_force_recovery,
+ innobase_open_files;
+
+longlong innobase_buffer_pool_size, innobase_log_file_size;
/* The default values for the following char* start-up parameters
are determined in innobase_init below: */
@@ -1231,6 +1232,25 @@ innobase_init(void)
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
+ /* Check that values don't overflow on 32-bit systems. */
+ if (sizeof(ulint) == 4) {
+ if (innobase_buffer_pool_size > UINT_MAX32) {
+ sql_print_error(
+ "innobase_buffer_pool_size can't be over 4GB"
+ " on 32-bit systems");
+
+ DBUG_RETURN(0);
+ }
+
+ if (innobase_log_file_size > UINT_MAX32) {
+ sql_print_error(
+ "innobase_log_file_size can't be over 4GB"
+ " on 32-bit systems");
+
+ DBUG_RETURN(0);
+ }
+ }
+
os_innodb_umask = (ulint)my_umask;
/* First calculate the default path for innodb_data_home_dir etc.,
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 32de25c78c6..c249cdf2bf4 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -218,8 +218,9 @@ extern ulong innobase_large_page_size;
extern char *innobase_home, *innobase_tmpdir, *innobase_logdir;
extern long innobase_lock_scan_time;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
-extern long innobase_log_file_size, innobase_log_buffer_size;
-extern long innobase_buffer_pool_size, innobase_additional_mem_pool_size;
+extern longlong innobase_buffer_pool_size, innobase_log_file_size;
+extern long innobase_log_buffer_size;
+extern long innobase_additional_mem_pool_size;
extern long innobase_buffer_pool_awe_mem_mb;
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
extern long innobase_force_recovery;
diff --git a/sql/item.h b/sql/item.h
index 8bc659c3060..332eac70145 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1603,7 +1603,11 @@ public:
void make_field(Send_field *field);
bool fix_fields(THD *, Item **);
int save_in_field(Field *field, bool no_conversions);
- void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
+ void save_org_in_field(Field *field)
+ {
+ (*ref)->save_org_in_field(field);
+ null_value= (*ref)->null_value;
+ }
enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
Field *get_tmp_table_field()
diff --git a/sql/lock.cc b/sql/lock.cc
index 0af22cac399..8af0c9d142a 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -814,10 +814,13 @@ static void print_lock_error(int error, const char *table)
access to them is protected with a mutex LOCK_global_read_lock
- (XXX: one should never take LOCK_open if LOCK_global_read_lock is taken,
- otherwise a deadlock may occur - see mysql_rm_table. Other mutexes could
- be a problem too - grep the code for global_read_lock if you want to use
- any other mutex here)
+ (XXX: one should never take LOCK_open if LOCK_global_read_lock is
+ taken, otherwise a deadlock may occur. Other mutexes could be a
+ problem too - grep the code for global_read_lock if you want to use
+ any other mutex here) Also one must not hold LOCK_open when calling
+ wait_if_global_read_lock(). When the thread with the global read lock
+ tries to close its tables, it needs to take LOCK_open in
+ close_thread_table().
How blocking of threads by global read lock is achieved: that's
advisory. Any piece of code which should be blocked by global read lock must
@@ -936,6 +939,13 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
DBUG_ENTER("wait_if_global_read_lock");
LINT_INIT(old_message);
+ /*
+ Assert that we do not own LOCK_open. If we would own it, other
+ threads could not close their tables. This would make a pretty
+ deadlock.
+ */
+ safe_mutex_assert_not_owner(&LOCK_open);
+
(void) pthread_mutex_lock(&LOCK_global_read_lock);
if ((need_exit_cond= must_wait))
{
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index ab5770ece71..c45035da5af 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -912,7 +912,8 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen);
bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
-int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags);
+int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
+ bool is_locked);
/* mysql_ha_flush mode_flags bits */
#define MYSQL_HA_CLOSE_FINAL 0x00
#define MYSQL_HA_REOPEN_ON_USAGE 0x01
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 0d65ef8a279..477c20f390a 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5529,7 +5529,8 @@ log and this option does nothing anymore.",
{"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
(gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
- GET_LONG, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, ~0L, 0, 1024*1024L, 0},
+ GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
+ 1024*1024L, 0},
{"innodb_concurrency_tickets", OPT_INNODB_CONCURRENCY_TICKETS,
"Number of times a thread is allowed to enter InnoDB within the same \
SQL query after it has once got the ticket",
@@ -5553,9 +5554,10 @@ log and this option does nothing anymore.",
(gptr*) &innobase_log_buffer_size, (gptr*) &innobase_log_buffer_size, 0,
GET_LONG, REQUIRED_ARG, 1024*1024L, 256*1024L, ~0L, 0, 1024, 0},
{"innodb_log_file_size", OPT_INNODB_LOG_FILE_SIZE,
- "Size of each log file in a log group in megabytes.",
+ "Size of each log file in a log group.",
(gptr*) &innobase_log_file_size, (gptr*) &innobase_log_file_size, 0,
- GET_LONG, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, ~0L, 0, 1024*1024L, 0},
+ GET_LL, REQUIRED_ARG, 5*1024*1024L, 1*1024*1024L, LONGLONG_MAX, 0,
+ 1024*1024L, 0},
{"innodb_log_files_in_group", OPT_INNODB_LOG_FILES_IN_GROUP,
"Number of log files in the log group. InnoDB writes to the files in a circular fashion. Value 3 is recommended here.",
(gptr*) &innobase_log_files_in_group, (gptr*) &innobase_log_files_in_group,
diff --git a/sql/set_var.cc b/sql/set_var.cc
index cfe75742d1a..29eae82c3ae 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -693,7 +693,7 @@ struct show_var_st init_vars[]= {
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
{sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS},
{"innodb_buffer_pool_awe_mem_mb", (char*) &innobase_buffer_pool_awe_mem_mb, SHOW_LONG },
- {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
+ {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONGLONG },
{"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
{sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
{sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
@@ -711,7 +711,7 @@ struct show_var_st init_vars[]= {
{"innodb_log_arch_dir", (char*) &innobase_log_arch_dir, SHOW_CHAR_PTR},
{"innodb_log_archive", (char*) &innobase_log_archive, SHOW_MY_BOOL},
{"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
- {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG},
+ {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONGLONG},
{"innodb_log_files_in_group", (char*) &innobase_log_files_in_group, SHOW_LONG},
{"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
{sys_innodb_max_dirty_pages_pct.name, (char*) &sys_innodb_max_dirty_pages_pct, SHOW_SYS},
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index d6453ffb4a4..c76ed813bc6 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -120,6 +120,45 @@ sp_get_flags_for_command(LEX *lex)
case SQLCOM_DEALLOCATE_PREPARE:
flags= sp_head::CONTAINS_DYNAMIC_SQL;
break;
+ case SQLCOM_CREATE_TABLE:
+ if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)
+ flags= 0;
+ else
+ flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
+ break;
+ case SQLCOM_DROP_TABLE:
+ if (lex->drop_temporary)
+ flags= 0;
+ else
+ flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
+ break;
+ case SQLCOM_CREATE_INDEX:
+ case SQLCOM_CREATE_DB:
+ case SQLCOM_CREATE_VIEW:
+ case SQLCOM_CREATE_TRIGGER:
+ case SQLCOM_CREATE_USER:
+ case SQLCOM_ALTER_TABLE:
+ case SQLCOM_BEGIN:
+ case SQLCOM_RENAME_TABLE:
+ case SQLCOM_RENAME_USER:
+ case SQLCOM_DROP_INDEX:
+ case SQLCOM_DROP_DB:
+ case SQLCOM_DROP_USER:
+ case SQLCOM_DROP_VIEW:
+ case SQLCOM_DROP_TRIGGER:
+ case SQLCOM_TRUNCATE:
+ case SQLCOM_COMMIT:
+ case SQLCOM_ROLLBACK:
+ case SQLCOM_LOAD_MASTER_DATA:
+ case SQLCOM_LOCK_TABLES:
+ case SQLCOM_CREATE_PROCEDURE:
+ case SQLCOM_CREATE_SPFUNCTION:
+ case SQLCOM_ALTER_PROCEDURE:
+ case SQLCOM_ALTER_FUNCTION:
+ case SQLCOM_DROP_PROCEDURE:
+ case SQLCOM_DROP_FUNCTION:
+ flags= sp_head::HAS_COMMIT_OR_ROLLBACK;
+ break;
default:
flags= 0;
break;
@@ -476,7 +515,7 @@ void
sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
{
DBUG_ENTER("sp_head::init_strings");
- uint n; /* Counter for nul trimming */
+ uchar *endp; /* Used to trim the end */
/* During parsing, we must use thd->mem_root */
MEM_ROOT *root= thd->mem_root;
@@ -509,17 +548,20 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
(char *)m_param_begin, m_params.length);
}
- m_body.length= lex->ptr - m_body_begin;
- /* Trim nuls at the end */
- n= 0;
- while (m_body.length && m_body_begin[m_body.length-1] == '\0')
- {
- m_body.length-= 1;
- n+= 1;
- }
+ /* If ptr has overrun end_of_query then end_of_query is the end */
+ endp= (lex->ptr > lex->end_of_query ? lex->end_of_query : lex->ptr);
+ /*
+ Trim "garbage" at the end. This is sometimes needed with the
+ "/ * ! VERSION... * /" wrapper in dump files.
+ */
+ while (m_body_begin < endp &&
+ (endp[-1] <= ' ' || endp[-1] == '*' ||
+ endp[-1] == '/' || endp[-1] == ';'))
+ endp-= 1;
+
+ m_body.length= endp - m_body_begin;
m_body.str= strmake_root(root, (char *)m_body_begin, m_body.length);
- m_defstr.length= lex->ptr - lex->buf;
- m_defstr.length-= n;
+ m_defstr.length= endp - lex->buf;
m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length);
DBUG_VOID_RETURN;
}
@@ -2864,33 +2906,34 @@ sp_head::add_used_tables_to_table_list(THD *thd,
DBUG_ENTER("sp_head::add_used_tables_to_table_list");
/*
- Use persistent arena for table list allocation to be PS friendly.
+ Use persistent arena for table list allocation to be PS/SP friendly.
+ Note that we also have to copy database/table names and alias to PS/SP
+ memory since current instance of sp_head object can pass away before
+ next execution of PS/SP for which tables are added to prelocking list.
+ This will be fixed by introducing of proper invalidation mechanism
+ once new TDC is ready.
*/
arena= thd->activate_stmt_arena_if_needed(&backup);
for (i=0 ; i < m_sptabs.records ; i++)
{
- char *tab_buff;
+ char *tab_buff, *key_buff;
TABLE_LIST *table;
SP_TABLE *stab= (SP_TABLE *)hash_element(&m_sptabs, i);
if (stab->temp)
continue;
if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) *
- stab->lock_count)))
+ stab->lock_count)) ||
+ !(key_buff= (char*)thd->memdup(stab->qname.str,
+ stab->qname.length + 1)))
DBUG_RETURN(FALSE);
for (uint j= 0; j < stab->lock_count; j++)
{
table= (TABLE_LIST *)tab_buff;
- /*
- It's enough to just copy the pointers as the data will not change
- during the lifetime of the SP. If the SP is used by PS, we assume
- that the PS will be invalidated if the functions is deleted or
- changed.
- */
- table->db= stab->qname.str;
+ table->db= key_buff;
table->db_length= stab->db_length;
table->table_name= table->db + table->db_length + 1;
table->table_name_length= stab->table_name_length;
diff --git a/sql/sp_head.h b/sql/sp_head.h
index d1a122fd410..8c2d58a696e 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -115,10 +115,13 @@ public:
MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s)
CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE
IS_INVOKED= 32, // Is set if this sp_head is being used
- HAS_SET_AUTOCOMMIT_STMT = 64 // Is set if a procedure with 'set autocommit'
+ HAS_SET_AUTOCOMMIT_STMT= 64,// Is set if a procedure with 'set autocommit'
+ /* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */
+ HAS_COMMIT_OR_ROLLBACK= 128
};
- int m_type; // TYPE_ENUM_FUNCTION or TYPE_ENUM_PROCEDURE
+ /* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */
+ int m_type;
uint m_flags; // Boolean attributes of a stored routine
enum enum_field_types m_returns; // For FUNCTIONs only
Field::geometry_type m_geom_returns;
@@ -292,6 +295,12 @@ public:
my_error(ER_SP_NO_RETSET, MYF(0), where);
else if (m_flags & HAS_SET_AUTOCOMMIT_STMT)
my_error(ER_SP_CANT_SET_AUTOCOMMIT, MYF(0));
+ else if (m_type != TYPE_ENUM_PROCEDURE &&
+ (m_flags & sp_head::HAS_COMMIT_OR_ROLLBACK))
+ {
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ return TRUE;
+ }
return test(m_flags &
(CONTAINS_DYNAMIC_SQL|MULTI_RESULTS|HAS_SET_AUTOCOMMIT_STMT));
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 30dec528845..f91a5e14835 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -311,7 +311,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->proc_info="Flushing tables";
close_old_data_files(thd,thd->open_tables,1,1);
- mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL);
+ mysql_ha_flush(thd, tables, MYSQL_HA_REOPEN_ON_USAGE | MYSQL_HA_FLUSH_ALL,
+ TRUE);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info",
@@ -1238,7 +1239,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
/* close handler tables which are marked for flush */
if (thd->handler_tables)
- mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table && table->in_use ;
@@ -1642,7 +1643,7 @@ bool wait_for_tables(THD *thd)
{
thd->some_tables_deleted=0;
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
- mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE);
+ mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
if (!table_is_used(thd->open_tables,1))
break;
(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index de5be091968..4ca6e6486df 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -376,7 +376,7 @@ void THD::cleanup(void)
close_thread_tables(this);
}
mysql_ha_flush(this, (TABLE_LIST*) 0,
- MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL);
+ MYSQL_HA_CLOSE_FINAL | MYSQL_HA_FLUSH_ALL, FALSE);
hash_free(&handler_tables_hash);
delete_dynamic(&user_var_events);
hash_free(&user_vars);
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 5f065e2a8b8..e9c695419d8 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -336,6 +336,7 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
ha_rows select_limit_cnt, ha_rows offset_limit_cnt)
{
TABLE_LIST *hash_tables;
+ TABLE **table_ptr;
TABLE *table;
MYSQL_LOCK *lock;
List<Item> list;
@@ -368,6 +369,28 @@ bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
DBUG_PRINT("info-in-hash",("'%s'.'%s' as '%s' tab %p",
hash_tables->db, hash_tables->table_name,
hash_tables->alias, table));
+ /* Table might have been flushed. */
+ if (table && (table->s->version != refresh_version))
+ {
+ /*
+ We must follow the thd->handler_tables chain, 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 != table);
+ table_ptr= &(*table_ptr)->next)
+ {}
+ (*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 */
+ VOID(pthread_cond_broadcast(&COND_refresh));
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ table= hash_tables->table= NULL;
+ }
if (!table)
{
/*
@@ -594,6 +617,7 @@ err0:
MYSQL_HA_REOPEN_ON_USAGE mark for reopen.
MYSQL_HA_FLUSH_ALL flush all tables, not only
those marked for flush.
+ is_locked If LOCK_open is locked.
DESCRIPTION
The list of HANDLER tables may be NULL, in which case all HANDLER
@@ -601,7 +625,6 @@ err0:
If 'tables' is NULL and MYSQL_HA_FLUSH_ALL is not set,
all HANDLER tables marked for flush are closed.
Broadcasts a COND_refresh condition, for every table closed.
- The caller must lock LOCK_open.
NOTE
Since mysql_ha_flush() is called when the base table has to be closed,
@@ -611,10 +634,12 @@ err0:
0 ok
*/
-int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
+int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags,
+ bool is_locked)
{
TABLE_LIST *tmp_tables;
TABLE **table_ptr;
+ bool did_lock= FALSE;
DBUG_ENTER("mysql_ha_flush");
DBUG_PRINT("enter", ("tables: %p mode_flags: 0x%02x", tables, mode_flags));
@@ -640,6 +665,12 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
(*table_ptr)->s->db,
(*table_ptr)->s->table_name,
(*table_ptr)->alias));
+ /* 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;
+ }
mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
}
@@ -658,6 +689,12 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
if ((mode_flags & MYSQL_HA_FLUSH_ALL) ||
((*table_ptr)->s->version != refresh_version))
{
+ /* 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;
+ }
mysql_ha_flush_table(thd, table_ptr, mode_flags);
continue;
}
@@ -665,6 +702,10 @@ int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags)
}
}
+ /* Release the lock if it was taken by this function. */
+ if (did_lock)
+ VOID(pthread_mutex_unlock(&LOCK_open));
+
DBUG_RETURN(0);
}
@@ -696,8 +737,8 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
table->alias, mode_flags));
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
- (byte*) (*table_ptr)->alias,
- strlen((*table_ptr)->alias) + 1)))
+ (byte*) table->alias,
+ strlen(table->alias) + 1)))
{
if (! (mode_flags & MYSQL_HA_REOPEN_ON_USAGE))
{
@@ -711,7 +752,9 @@ static int mysql_ha_flush_table(THD *thd, TABLE **table_ptr, uint mode_flags)
}
}
+ safe_mutex_assert_owner(&LOCK_open);
(*table_ptr)->file->ha_index_or_rnd_end();
+ safe_mutex_assert_owner(&LOCK_open);
if (close_thread_table(thd, table_ptr))
{
/* Tell threads waiting for refresh that something has happened */
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index dd5c57afaad..26b9e2d1718 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2398,18 +2398,6 @@ mysql_execute_command(THD *thd)
reset_one_shot_variables(thd);
DBUG_RETURN(0);
}
-#ifndef TO_BE_DELETED
- /*
- This is a workaround to deal with the shortcoming in 3.23.44-3.23.46
- masters in RELEASE_LOCK() logging. We re-write SELECT RELEASE_LOCK()
- as DO RELEASE_LOCK()
- */
- if (lex->sql_command == SQLCOM_SELECT)
- {
- lex->sql_command = SQLCOM_DO;
- lex->insert_list = &select_lex->item_list;
- }
-#endif
}
else
#endif /* HAVE_REPLICATION */
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index d7c9ad54931..d5282ef6b7f 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1829,13 +1829,16 @@ static bool init_param_array(Prepared_statement *stmt)
void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
{
- Prepared_statement *stmt= new Prepared_statement(thd, &thd->protocol_prep);
+ Prepared_statement *stmt;
bool error;
DBUG_ENTER("mysql_stmt_prepare");
DBUG_PRINT("prep_query", ("%s", packet));
- if (stmt == 0)
+ /* First of all clear possible warnings from the previous command */
+ mysql_reset_thd_for_next_command(thd);
+
+ if (! (stmt= new Prepared_statement(thd, &thd->protocol_prep)))
DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
if (thd->stmt_map.insert(stmt))
@@ -1844,7 +1847,6 @@ void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
DBUG_VOID_RETURN; /* out of memory */
}
- mysql_reset_thd_for_next_command(thd);
/* Reset warnings from previous command */
mysql_reset_errors(thd, 0);
sp_cache_flush_obsolete(&thd->sp_proc_cache);
@@ -2188,13 +2190,15 @@ void mysql_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
packet+= 9; /* stmt_id + 5 bytes of flags */
+ /* First of all clear possible warnings from the previous command */
+ mysql_reset_thd_for_next_command(thd);
+
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN;
DBUG_PRINT("exec_query", ("%s", stmt->query));
DBUG_PRINT("info",("stmt: %p", stmt));
- mysql_reset_thd_for_next_command(thd);
sp_cache_flush_obsolete(&thd->sp_proc_cache);
sp_cache_flush_obsolete(&thd->sp_func_cache);
@@ -2314,6 +2318,8 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
Server_side_cursor *cursor;
DBUG_ENTER("mysql_stmt_fetch");
+ /* First of all clear possible warnings from the previous command */
+ mysql_reset_thd_for_next_command(thd);
statistic_increment(thd->status_var.com_stmt_fetch, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_fetch")))
DBUG_VOID_RETURN;
@@ -2375,6 +2381,9 @@ void mysql_stmt_reset(THD *thd, char *packet)
Prepared_statement *stmt;
DBUG_ENTER("mysql_stmt_reset");
+ /* First of all clear possible warnings from the previous command */
+ mysql_reset_thd_for_next_command(thd);
+
statistic_increment(thd->status_var.com_stmt_reset, &LOCK_status);
if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
@@ -2389,7 +2398,6 @@ void mysql_stmt_reset(THD *thd, char *packet)
stmt->state= Query_arena::PREPARED;
- mysql_reset_thd_for_next_command(thd);
send_ok(thd);
DBUG_VOID_RETURN;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index c97c6426477..ad520302692 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -11011,7 +11011,7 @@ static int test_if_order_by_key(ORDER *order, TABLE *table, uint idx,
for (; order ; order=order->next, const_key_parts>>=1)
{
- Field *field=((Item_field*) (*order->item))->field;
+ Field *field=((Item_field*) (*order->item)->real_item())->field;
int flag;
/*
@@ -11151,8 +11151,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
DBUG_ENTER("test_if_skip_sort_order");
LINT_INIT(ref_key_parts);
- /* Check which keys can be used to resolve ORDER BY */
- usable_keys.set_all();
+ /*
+ Check which keys can be used to resolve ORDER BY.
+ We must not try to use disabled keys.
+ */
+ usable_keys= table->s->keys_in_use;
+
for (ORDER *tmp_order=order; tmp_order ; tmp_order=tmp_order->next)
{
Item *item= (*tmp_order->item)->real_item();
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1362f1818a4..3091656d9dc 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1470,7 +1470,7 @@ static bool show_status_array(THD *thd, const char *wild,
case SHOW_SLAVE_RUNNING:
{
pthread_mutex_lock(&LOCK_active_mi);
- end= strmov(buff, (active_mi->slave_running &&
+ end= strmov(buff, (active_mi && active_mi->slave_running &&
active_mi->rli.slave_running) ? "ON" : "OFF");
pthread_mutex_unlock(&LOCK_active_mi);
break;
@@ -1481,12 +1481,15 @@ static bool show_status_array(THD *thd, const char *wild,
TODO: in 5.1 with multimaster, have one such counter per line in
SHOW SLAVE STATUS, and have the sum over all lines here.
*/
- pthread_mutex_lock(&LOCK_active_mi);
- pthread_mutex_lock(&active_mi->rli.data_lock);
- end= int10_to_str(active_mi->rli.retried_trans, buff, 10);
- pthread_mutex_unlock(&active_mi->rli.data_lock);
- pthread_mutex_unlock(&LOCK_active_mi);
- break;
+ pthread_mutex_lock(&LOCK_active_mi);
+ if (active_mi)
+ {
+ pthread_mutex_lock(&active_mi->rli.data_lock);
+ end= int10_to_str(active_mi->rli.retried_trans, buff, 10);
+ pthread_mutex_unlock(&active_mi->rli.data_lock);
+ }
+ pthread_mutex_unlock(&LOCK_active_mi);
+ break;
}
case SHOW_SLAVE_SKIP_ERRORS:
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 4c06d4646fb..93315e3b9f1 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -159,23 +159,28 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
/* mark for close and remove all cached entries */
- thd->mysys_var->current_mutex= &LOCK_open;
- thd->mysys_var->current_cond= &COND_refresh;
- VOID(pthread_mutex_lock(&LOCK_open));
-
if (!drop_temporary)
{
if ((error= wait_if_global_read_lock(thd, 0, 1)))
{
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->table_name);
- goto err;
+ DBUG_RETURN(TRUE);
}
else
need_start_waiters= TRUE;
}
+
+ /*
+ Acquire LOCK_open after wait_if_global_read_lock(). If we would hold
+ LOCK_open during wait_if_global_read_lock(), other threads could not
+ close their tables. This would make a pretty deadlock.
+ */
+ thd->mysys_var->current_mutex= &LOCK_open;
+ thd->mysys_var->current_cond= &COND_refresh;
+ VOID(pthread_mutex_lock(&LOCK_open));
+
error= mysql_rm_table_part2(thd, tables, if_exists, drop_temporary, 0, 0);
-err:
pthread_mutex_unlock(&LOCK_open);
pthread_mutex_lock(&thd->mysys_var->mutex);
@@ -288,7 +293,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *db=table->db;
db_type table_type= DB_TYPE_UNKNOWN;
- mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, TRUE);
if (!close_temporary_table(thd, db, table->table_name))
{
tmp_table_deleted=1;
@@ -2313,7 +2318,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
- mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
+ mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL, FALSE);
for (table= tables; table; table= table->next_local)
{
char table_name[NAME_LEN*2+2];
@@ -3426,8 +3431,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
new_db= db;
used_fields=create_info->used_fields;
+
+ mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL, FALSE);
- mysql_ha_flush(thd, table_list, MYSQL_HA_CLOSE_FINAL);
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index b642d24b30d..4067201bf18 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -495,7 +495,7 @@ static const int num_view_backups= 3;
static File_option view_parameters[]=
{{{(char*) STRING_WITH_LEN("query")},
offsetof(TABLE_LIST, query),
- FILE_OPTIONS_STRING},
+ FILE_OPTIONS_ESTRING},
{{(char*) STRING_WITH_LEN("md5")},
offsetof(TABLE_LIST, md5),
FILE_OPTIONS_STRING},
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 91d4f26286b..092d73a6ccd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1182,11 +1182,6 @@ create:
| CREATE opt_unique_or_fulltext INDEX_SYM ident key_alg ON table_ident
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_CREATE_INDEX;
if (!lex->current_select->add_table_to_list(lex->thd, $7, NULL,
TL_OPTION_UPDATING))
@@ -3831,11 +3826,6 @@ alter:
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_ALTER_TABLE;
lex->name= 0;
lex->duplicates= DUP_ERROR;
@@ -4237,11 +4227,6 @@ start:
START_SYM TRANSACTION_SYM start_transaction_opts
{
LEX *lex= Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_BEGIN;
lex->start_transaction_opt= $3;
}
@@ -4426,13 +4411,7 @@ opt_no_write_to_binlog:
rename:
RENAME table_or_tables
{
- LEX *lex= Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
- lex->sql_command=SQLCOM_RENAME_TABLE;
+ Lex->sql_command= SQLCOM_RENAME_TABLE;
}
table_to_table_list
{}
@@ -6569,21 +6548,10 @@ drop:
lex->sql_command = SQLCOM_DROP_TABLE;
lex->drop_temporary= $2;
lex->drop_if_exists= $4;
- if (!lex->drop_temporary && lex->sphead &&
- lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
}
| DROP INDEX_SYM ident ON table_ident {}
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_DROP_INDEX;
lex->alter_info.drop_list.empty();
lex->alter_info.drop_list.push_back(new Alter_drop(Alter_drop::KEY,
@@ -6629,13 +6597,7 @@ drop:
}
| DROP VIEW_SYM if_exists table_list opt_restrict
{
- THD *thd= YYTHD;
- LEX *lex= thd->lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
+ LEX *lex= Lex;
lex->sql_command= SQLCOM_DROP_VIEW;
lex->drop_if_exists= $3;
}
@@ -8612,6 +8574,9 @@ option_value:
names.length= 5;
if (spc && spc->find_pvar(&names))
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
+ else
+ yyerror(ER(ER_SYNTAX_ERROR));
+
YYABORT;
}
| NAMES_SYM charset_name_or_default opt_collate
@@ -9301,11 +9266,6 @@ begin:
BEGIN_SYM
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command = SQLCOM_BEGIN;
lex->start_transaction_opt= 0;
}
@@ -9338,11 +9298,6 @@ commit:
COMMIT_SYM opt_work opt_chain opt_release
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_COMMIT;
lex->tx_chain= $3;
lex->tx_release= $4;
@@ -9353,11 +9308,6 @@ rollback:
ROLLBACK_SYM opt_work opt_chain opt_release
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- YYABORT;
- }
lex->sql_command= SQLCOM_ROLLBACK;
lex->tx_chain= $3;
lex->tx_release= $4;