summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <igor@rurik.mysql.com>2005-11-17 20:26:34 -0800
committerunknown <igor@rurik.mysql.com>2005-11-17 20:26:34 -0800
commit806482c7e45aceac81fe3999197d3a3724653c03 (patch)
treeca8541a960d83f3cbf7beb7e3bc30e40d3b224fe
parent2e4045e45d764615d030eca79694d21e5034709e (diff)
parent57ad6b20ed8b22b010af1c354b23591570f12b09 (diff)
downloadmariadb-git-806482c7e45aceac81fe3999197d3a3724653c03.tar.gz
Merge rurik.mysql.com:/home/igor/mysql-5.0
into rurik.mysql.com:/home/igor/dev/mysql-5.0-2 sql/sql_prepare.cc: Auto merged
-rw-r--r--mysql-test/r/sp-error.result18
-rw-r--r--mysql-test/r/trigger.result25
-rw-r--r--mysql-test/t/sp-error.test22
-rw-r--r--mysql-test/t/trigger.test39
-rw-r--r--sql/ha_innodb.cc34
-rw-r--r--sql/ha_innodb.h5
-rw-r--r--sql/mysqld.cc8
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sp_head.cc21
-rw-r--r--sql/sql_prepare.cc18
-rw-r--r--tests/mysql_client_test.c63
11 files changed, 227 insertions, 30 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 2f4b420a2ae..26bb0fa4694 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -975,6 +975,24 @@ return 1;
END |
drop table t1|
drop function bug_13627_f|
+drop function if exists bug12329;
+create table t1 as select 1 a;
+create table t2 as select 1 a;
+create function bug12329() returns int return (select a from t1);
+prepare stmt1 from 'select bug12329()';
+execute stmt1;
+bug12329()
+1
+drop function bug12329;
+create function bug12329() returns int return (select a+100 from t2);
+select bug12329();
+bug12329()
+101
+execute stmt1;
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
+deallocate prepare stmt1;
+drop function bug12329;
+drop table t1, t2;
create database mysqltest1;
use mysqltest1;
drop database mysqltest1;
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index d3fbb56e493..af99dea58b9 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -738,3 +738,28 @@ f1
1
drop trigger t1_bi;
drop tables t1, t2;
+create table t1 (id int);
+create table t2 (id int);
+create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id);
+prepare stmt1 from "insert into t1 values (10)";
+create procedure p1() insert into t1 values (10);
+call p1();
+drop trigger t1_bi;
+execute stmt1;
+call p1();
+deallocate prepare stmt1;
+drop procedure p1;
+create table t3 (id int);
+create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id);
+prepare stmt1 from "insert into t1 values (10)";
+create procedure p1() insert into t1 values (10);
+call p1();
+drop trigger t1_bi;
+create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id);
+execute stmt1;
+ERROR HY000: Table 't3' was not locked with LOCK TABLES
+call p1();
+ERROR HY000: Table 't3' was not locked with LOCK TABLES
+deallocate prepare stmt1;
+drop procedure p1;
+drop table t1, t2, t3;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index f16562227f3..4cc141fea4b 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -1403,6 +1403,28 @@ drop function bug_13627_f|
delimiter ;|
+# BUG#12329: "Bogus error msg when executing PS with stored procedure after
+# SP was re-created". See also test for related bug#13399 in trigger.test
+--disable_warnings
+drop function if exists bug12329;
+--enable_warnings
+create table t1 as select 1 a;
+create table t2 as select 1 a;
+create function bug12329() returns int return (select a from t1);
+prepare stmt1 from 'select bug12329()';
+execute stmt1;
+drop function bug12329;
+create function bug12329() returns int return (select a+100 from t2);
+select bug12329();
+# Until we implement proper mechanism for invalidation of PS/SP when table
+# or SP's are changed the following statement will fail with 'Table ... was
+# not locked' error (this mechanism should be based on the new TDC).
+--error 1100
+execute stmt1;
+deallocate prepare stmt1;
+drop function bug12329;
+drop table t1, t2;
+
#
# Bug#13514 "server crash when create a stored procedure before choose a
# database" and
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index cd79eb82ace..02d994128e2 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -875,3 +875,42 @@ drop function f1;
drop view v1;
drop table t1, t2, t3;
--enable_parsing
+
+#
+# Test for bug #13399 "Crash when executing PS/SP which should activate
+# trigger which is now dropped". See also test for similar bug for stored
+# routines in sp-error.test (#12329).
+create table t1 (id int);
+create table t2 (id int);
+create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id);
+prepare stmt1 from "insert into t1 values (10)";
+create procedure p1() insert into t1 values (10);
+call p1();
+# Actually it is enough to do FLUSH TABLES instead of DROP TRIGGER
+drop trigger t1_bi;
+# Server should not crash on these two statements
+execute stmt1;
+call p1();
+deallocate prepare stmt1;
+drop procedure p1;
+
+# Let us test more complex situation when we alter trigger in such way that
+# it uses different set of tables (or simply add new trigger).
+create table t3 (id int);
+create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id);
+prepare stmt1 from "insert into t1 values (10)";
+create procedure p1() insert into t1 values (10);
+call p1();
+# Altering trigger forcing it use different set of tables
+drop trigger t1_bi;
+create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id);
+# Until we implement proper mechanism for invalidation of PS/SP when table
+# or SP's are changed these two statements will fail with 'Table ... was
+# not locked' error (this mechanism should be based on the new TDC).
+--error 1100
+execute stmt1;
+--error 1100
+call p1();
+deallocate prepare stmt1;
+drop procedure p1;
+drop table t1, t2, t3;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 556186d5584..60ec6f8e2bb 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -142,15 +142,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: */
@@ -1210,6 +1211,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 78cd0f927e9..eb4e10e545f 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -206,8 +206,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/mysqld.cc b/sql/mysqld.cc
index 890b1716212..b22330152e8 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -5418,7 +5418,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",
@@ -5442,9 +5443,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 5a6ff7d05ad..89ad00d7839 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -818,7 +818,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},
@@ -836,7 +836,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 e3cdc909048..6248a60521b 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2906,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/sql_prepare.cc b/sql/sql_prepare.cc
index a5cf678aa3a..b3e558c94d0 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -1827,13 +1827,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))
@@ -1842,7 +1845,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);
@@ -2187,13 +2189,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);
@@ -2313,6 +2317,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;
@@ -2374,6 +2380,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;
@@ -2388,7 +2397,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/tests/mysql_client_test.c b/tests/mysql_client_test.c
index b065a0dfa03..e0f3fd91e5c 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -14419,7 +14419,7 @@ static void test_bug14210()
myquery(rc);
}
-/* Bug#13488 */
+/* Bug#13488: wrong column metadata when fetching from cursor */
static void test_bug13488()
{
@@ -14488,6 +14488,66 @@ static void test_bug13488()
}
/*
+ Bug#13524: warnings of a previous command are not reset when fetching
+ from a cursor.
+*/
+
+static void test_bug13524()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ unsigned int warning_count;
+ const ulong type= CURSOR_TYPE_READ_ONLY;
+ const char *query= "select * from t1";
+
+ myheader("test_bug13524");
+
+ rc= mysql_query(mysql, "drop table if exists t1, t2");
+ myquery(rc);
+ rc= mysql_query(mysql, "create table t1 (a int not null primary key)");
+ myquery(rc);
+ rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)");
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+ rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (const void*) &type);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_prepare(stmt, query, strlen(query));
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ warning_count= mysql_warning_count(mysql);
+ DIE_UNLESS(warning_count == 0);
+
+ /* Check that DROP TABLE produced a warning (no such table) */
+ rc= mysql_query(mysql, "drop table if exists t2");
+ myquery(rc);
+ warning_count= mysql_warning_count(mysql);
+ DIE_UNLESS(warning_count == 1);
+
+ /*
+ Check that fetch from a cursor cleared the warning from the previous
+ command.
+ */
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+ warning_count= mysql_warning_count(mysql);
+ DIE_UNLESS(warning_count == 0);
+
+ /* Cleanup */
+ mysql_stmt_close(stmt);
+ rc= mysql_query(mysql, "drop table t1");
+ myquery(rc);
+}
+
+
+/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -14744,6 +14804,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug12243", test_bug12243 },
{ "test_bug14210", test_bug14210 },
{ "test_bug13488", test_bug13488 },
+ { "test_bug13524", test_bug13524 },
{ 0, 0 }
};