#At file:///home/hakan/work/mysql/mysql-6.0-falcon-team-to-merge/
2828 Hakan Kuecuekyilmaz 2008-09-20 [merge]
Merge.
added:
mysql-test/r/test_wl4435.result
sql/records.h
sql/transaction.cc
sql/transaction.h
modified:
.bzr-mysql/default.conf
.bzrignore
client/Makefile.am
include/mysql.h
include/mysql.h.pp
include/mysql_com.h
libmysql/client_settings.h
libmysql/libmysql.c
libmysql/libmysql.def
libmysqld/CMakeLists.txt
libmysqld/Makefile.am
libmysqld/lib_sql.cc
libmysqld/libmysqld.def
mysql-test/r/events_bugs.result
mysql-test/r/ps.result
mysql-test/suite/falcon/r/falcon_bug_34164.result
mysql-test/t/events_bugs.test
mysql-test/t/ps.test
sql/CMakeLists.txt
sql/Makefile.am
sql/backup/backup_test.cc
sql/backup/be_snapshot.cc
sql/backup/kernel.cc
sql/events.cc
sql/field.cc
sql/field.h
sql/handler.cc
sql/handler.h
sql/item.cc
sql/item.h
sql/lock.cc
sql/log_event.cc
sql/log_event_old.cc
sql/mysql_priv.h
sql/procedure.h
sql/protocol.cc
sql/protocol.h
sql/records.cc
sql/repl_failsafe.cc
sql/rpl_injector.cc
sql/rpl_injector.h
sql/rpl_rli.cc
sql/rpl_tblmap.cc
sql/rpl_tblmap.h
sql/set_var.cc
sql/slave.cc
sql/sp_head.cc
sql/sql_acl.cc
sql/sql_base.cc
sql/sql_cache.h
sql/sql_class.cc
sql/sql_class.h
sql/sql_cursor.cc
sql/sql_do.cc
sql/sql_error.cc
sql/sql_handler.cc
sql/sql_help.cc
sql/sql_insert.cc
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_parse.cc
sql/sql_partition.cc
sql/sql_prepare.cc
sql/sql_profile.cc
sql/sql_repl.cc
sql/sql_select.cc
sql/sql_select.h
sql/sql_show.cc
sql/sql_table.cc
sql/sql_yacc.yy
sql/structs.h
sql/table.cc
sql/table.h
storage/falcon/BDB.cpp
storage/falcon/InfoTable.h
storage/falcon/ha_falcon.cpp
storage/falcon/ha_falcon.h
storage/innobase/handler/ha_innodb.cc
storage/maria/ha_maria.cc
tests/mysql_client_test.c
=== modified file '.bzr-mysql/default.conf'
--- a/.bzr-mysql/default.conf 2008-09-11 18:36:05 +0000
+++ b/.bzr-mysql/default.conf 2008-09-16 17:58:49 +0000
@@ -1,5 +1,5 @@
-[MYSQL]
-tree_location = bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0-falcon
-post_commit_to = commits@stripped
-post_push_to = commits@stripped
-tree_name = mysql-6.0-falcon
+[MYSQL]
+tree_location = bzr+ssh://bk-internal.mysql.com/bzrroot/server/mysql-6.0-falcon
+post_commit_to = commits@stripped
+post_push_to = commits@stripped
+tree_name = mysql-6.0-falcon
=== modified file '.bzrignore'
--- a/.bzrignore 2008-08-26 10:20:41 +0000
+++ b/.bzrignore 2008-09-12 09:22:46 +0000
@@ -1891,3 +1891,5 @@ zlib/*.vcproj
extra/libevent/event-config.h
libmysqld/ddl_blocker.cc
libmysqld/mdl.cc
+client/transaction.h
+libmysqld/transaction.cc
=== modified file 'client/Makefile.am'
--- a/client/Makefile.am 2008-08-20 16:21:14 +0000
+++ b/client/Makefile.am 2008-09-04 18:30:34 +0000
@@ -107,7 +107,8 @@ sql_src=log_event.h mysql_priv.h rpl_con
rpl_utility.h rpl_tblmap.h rpl_tblmap.cc \
log_event.cc my_decimal.h my_decimal.cc \
log_event_old.h log_event_old.cc \
- rpl_record_old.h rpl_record_old.cc
+ rpl_record_old.h rpl_record_old.cc \
+ transaction.h
strings_src=decimal.c dtoa.c
link_sources:
=== modified file 'include/mysql.h'
--- a/include/mysql.h 2007-11-26 19:11:48 +0000
+++ b/include/mysql.h 2008-08-07 17:52:43 +0000
@@ -714,6 +714,7 @@ my_bool STDCALL mysql_rollback(MYSQL * m
my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool STDCALL mysql_more_results(MYSQL *mysql);
int STDCALL mysql_next_result(MYSQL *mysql);
+int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt);
void STDCALL mysql_close(MYSQL *sock);
=== modified file 'include/mysql.h.pp'
--- a/include/mysql.h.pp 2008-08-20 07:07:09 +0000
+++ b/include/mysql.h.pp 2008-09-12 08:38:48 +0000
@@ -612,4 +612,5 @@ my_bool mysql_rollback(MYSQL * mysql);
my_bool mysql_autocommit(MYSQL * mysql, my_bool auto_mode);
my_bool mysql_more_results(MYSQL *mysql);
int mysql_next_result(MYSQL *mysql);
+int mysql_stmt_next_result(MYSQL_STMT *stmt);
void mysql_close(MYSQL *sock);
=== modified file 'include/mysql_com.h'
--- a/include/mysql_com.h 2008-06-17 20:04:19 +0000
+++ b/include/mysql_com.h 2008-08-07 17:52:43 +0000
@@ -154,6 +154,7 @@ enum enum_server_command
#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
+#define CLIENT_PS_MULTI_RESULTS (1UL << 18) /* Multi-results in PS-protocol */
#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
@@ -177,6 +178,7 @@ enum enum_server_command
CLIENT_SECURE_CONNECTION | \
CLIENT_MULTI_STATEMENTS | \
CLIENT_MULTI_RESULTS | \
+ CLIENT_PS_MULTI_RESULTS | \
CLIENT_SSL_VERIFY_SERVER_CERT | \
CLIENT_REMEMBER_OPTIONS)
@@ -221,6 +223,11 @@ enum enum_server_command
#define SERVER_QUERY_WAS_SLOW 2048
/**
+ To mark ResultSet containing output parameter values.
+*/
+#define SERVER_PS_OUT_PARAMS 4096
+
+/**
Server status flags that must be cleared when starting
execution of a new SQL statement.
Flags from this set are only added to the
=== modified file 'libmysql/client_settings.h'
--- a/libmysql/client_settings.h 2007-09-29 19:31:08 +0000
+++ b/libmysql/client_settings.h 2008-08-07 17:52:43 +0000
@@ -16,9 +16,13 @@
extern uint mysql_port;
extern char * mysql_unix_port;
-#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \
- CLIENT_TRANSACTIONS | \
- CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION)
+#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \
+ CLIENT_LONG_FLAG | \
+ CLIENT_TRANSACTIONS | \
+ CLIENT_PROTOCOL_41 | \
+ CLIENT_SECURE_CONNECTION | \
+ CLIENT_MULTI_RESULTS | \
+ CLIENT_PS_MULTI_RESULTS)
sig_handler my_pipe_sig_handler(int sig);
void read_user_name(char *name);
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2008-06-17 20:04:19 +0000
+++ b/libmysql/libmysql.c 2008-08-07 17:52:43 +0000
@@ -1725,6 +1725,8 @@ static void alloc_stmt_fields(MYSQL_STMT
MEM_ROOT *alloc= &stmt->mem_root;
MYSQL *mysql= stmt->mysql;
+ DBUG_ASSERT(mysql->field_count);
+
stmt->field_count= mysql->field_count;
/*
@@ -1746,6 +1748,7 @@ static void alloc_stmt_fields(MYSQL_STMT
field= stmt->fields;
field && fields < end; fields++, field++)
{
+ field->catalog = strdup_root(alloc,fields->catalog);
field->db = strdup_root(alloc,fields->db);
field->table = strdup_root(alloc,fields->table);
field->org_table= strdup_root(alloc,fields->org_table);
@@ -2484,6 +2487,33 @@ static void reinit_result_set_metadata(M
}
+static void prepare_to_fetch_result(MYSQL_STMT *stmt)
+{
+ if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
+ {
+ stmt->mysql->status= MYSQL_STATUS_READY;
+ stmt->read_row_func= stmt_read_row_from_cursor;
+ }
+ else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
+ {
+ /*
+ This is a single-row result set, a result set with no rows, EXPLAIN,
+ SHOW VARIABLES, or some other command which either a) bypasses the
+ cursors framework in the server and writes rows directly to the
+ network or b) is more efficient if all (few) result set rows are
+ precached on client and server's resources are freed.
+ */
+ mysql_stmt_store_result(stmt);
+ }
+ else
+ {
+ stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
+ stmt->unbuffered_fetch_cancelled= FALSE;
+ stmt->read_row_func= stmt_read_row_unbuffered;
+ }
+}
+
+
/*
Send placeholders data to server (if there are placeholders)
and execute prepared statement.
@@ -2551,28 +2581,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STM
if (mysql->field_count)
{
reinit_result_set_metadata(stmt);
- if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
- {
- mysql->status= MYSQL_STATUS_READY;
- stmt->read_row_func= stmt_read_row_from_cursor;
- }
- else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
- {
- /*
- This is a single-row result set, a result set with no rows, EXPLAIN,
- SHOW VARIABLES, or some other command which either a) bypasses the
- cursors framework in the server and writes rows directly to the
- network or b) is more efficient if all (few) result set rows are
- precached on client and server's resources are freed.
- */
- mysql_stmt_store_result(stmt);
- }
- else
- {
- stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
- stmt->unbuffered_fetch_cancelled= FALSE;
- stmt->read_row_func= stmt_read_row_unbuffered;
- }
+ prepare_to_fetch_result(stmt);
}
DBUG_RETURN(test(stmt->last_errno));
}
@@ -4831,6 +4840,46 @@ int STDCALL mysql_next_result(MYSQL *mys
}
+int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
+{
+ MYSQL *mysql= stmt->mysql;
+ int rc;
+ DBUG_ENTER("mysql_stmt_next_result");
+
+ if (!mysql)
+ DBUG_RETURN(1);
+
+ if (stmt->last_errno)
+ DBUG_RETURN(stmt->last_errno);
+
+ if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
+ {
+ if (reset_stmt_handle(stmt, RESET_STORE_RESULT))
+ DBUG_RETURN(1);
+ }
+
+ rc= mysql_next_result(mysql);
+
+ if (rc)
+ DBUG_RETURN(rc);
+
+ stmt->state= MYSQL_STMT_EXECUTE_DONE;
+ stmt->bind_result_done= FALSE;
+
+ if (mysql->field_count)
+ {
+ alloc_stmt_fields(stmt);
+ prepare_to_fetch_result(stmt);
+ }
+ else
+ {
+ stmt->field_count= mysql->field_count;
+ }
+
+ DBUG_RETURN(0);
+}
+
+
MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql)
{
return (*mysql->methods->use_result)(mysql);
=== modified file 'libmysql/libmysql.def'
--- a/libmysql/libmysql.def 2007-12-04 15:27:44 +0000
+++ b/libmysql/libmysql.def 2008-08-11 10:03:45 +0000
@@ -142,3 +142,4 @@ EXPORTS
mysql_get_character_set_info
get_defaults_options
modify_defaults_file
+ mysql_stmt_next_result
=== modified file 'libmysqld/CMakeLists.txt'
--- a/libmysqld/CMakeLists.txt 2008-07-09 07:12:43 +0000
+++ b/libmysqld/CMakeLists.txt 2008-08-08 01:33:43 +0000
@@ -203,6 +203,7 @@ SET(LIBMYSQLD_SOURCES emb_qcache.cc libm
../sql/scheduler.cc ../sql/sql_audit.cc
../sql/ddl_blocker.cc ../sql/si_objects.cc
../sql/event_parse_data.cc ../sql/mdl.cc
+ ../sql/transaction.cc
${GEN_SOURCES}
${LIB_SOURCES})
=== modified file 'libmysqld/Makefile.am'
--- a/libmysqld/Makefile.am 2008-07-09 07:12:43 +0000
+++ b/libmysqld/Makefile.am 2008-08-08 01:33:43 +0000
@@ -78,8 +78,7 @@ sqlsources = derror.cc field.cc field_co
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \
rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \
- debug_sync.cc \
- sql_tablespace.cc \
+ debug_sync.cc sql_tablespace.cc transaction.cc \
rpl_injector.cc my_user.c partition_info.cc \
sql_servers.cc ddl_blocker.cc si_objects.cc sql_audit.cc \
event_parse_data.cc mdl.cc
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2008-08-13 19:17:28 +0000
+++ b/libmysqld/lib_sql.cc 2008-09-04 18:30:34 +0000
@@ -870,7 +870,7 @@ void Protocol_text::remove_last_row()
}
-bool Protocol::send_fields(List<Item> *list, uint flags)
+bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
@@ -879,7 +879,7 @@ bool Protocol::send_fields(List<Item> *l
CHARSET_INFO *thd_cs= thd->variables.character_set_results;
CHARSET_INFO *cs= system_charset_info;
MYSQL_DATA *data;
- DBUG_ENTER("send_fields");
+ DBUG_ENTER("send_result_set_metadata");
if (!thd->mysql) // bootstrap file handling
DBUG_RETURN(0);
@@ -972,7 +972,7 @@ bool Protocol::send_fields(List<Item> *l
if (flags & SEND_EOF)
write_eof_packet(thd, thd->server_status, thd->total_warn_count);
- DBUG_RETURN(prepare_for_send(list));
+ DBUG_RETURN(prepare_for_send(list->elements));
err:
my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
=== modified file 'libmysqld/libmysqld.def'
--- a/libmysqld/libmysqld.def 2007-12-04 15:27:44 +0000
+++ b/libmysqld/libmysqld.def 2008-08-11 10:03:45 +0000
@@ -170,3 +170,4 @@ EXPORTS
my_charset_bin
my_charset_same
modify_defaults_file
+ mysql_stmt_next_result
=== modified file 'mysql-test/r/events_bugs.result'
--- a/mysql-test/r/events_bugs.result 2008-02-19 14:09:52 +0000
+++ b/mysql-test/r/events_bugs.result 2008-09-12 19:34:30 +0000
@@ -736,3 +736,5 @@ select name from mysql.event where name
name
drop event e1;
DROP DATABASE events_test;
+# restore the defeault
+SET GLOBAL event_scheduler = 'on';
=== modified file 'mysql-test/r/ps.result'
--- a/mysql-test/r/ps.result 2008-07-24 10:00:56 +0000
+++ b/mysql-test/r/ps.result 2008-08-07 17:52:43 +0000
@@ -2920,4 +2920,165 @@ execute stmt;
Db Name Definer Time zone Type Execute at Interval value Interval field Starts Ends Status Originator character_set_client collation_connection Database Collation
drop table t1;
deallocate prepare stmt;
+
End of 5.1 tests.
+
+#
+# WL#4435: Support OUT-parameters in prepared statements.
+#
+
+DROP PROCEDURE IF EXISTS p_string;
+DROP PROCEDURE IF EXISTS p_double;
+DROP PROCEDURE IF EXISTS p_int;
+DROP PROCEDURE IF EXISTS p_decimal;
+
+CREATE PROCEDURE p_string(
+IN v0 INT,
+OUT v1 CHAR(32),
+IN v2 CHAR(32),
+INOUT v3 CHAR(32))
+BEGIN
+SET v0 = -1;
+SET v1 = 'test_v1';
+SET v2 = 'n/a';
+SET v3 = 'test_v3';
+END|
+
+CREATE PROCEDURE p_double(
+IN v0 INT,
+OUT v1 DOUBLE(4, 2),
+IN v2 DOUBLE(4, 2),
+INOUT v3 DOUBLE(4, 2))
+BEGIN
+SET v0 = -1;
+SET v1 = 12.34;
+SET v2 = 98.67;
+SET v3 = 56.78;
+END|
+
+CREATE PROCEDURE p_int(
+IN v0 CHAR(10),
+OUT v1 INT,
+IN v2 INT,
+INOUT v3 INT)
+BEGIN
+SET v0 = 'n/a';
+SET v1 = 1234;
+SET v2 = 9876;
+SET v3 = 5678;
+END|
+
+CREATE PROCEDURE p_decimal(
+IN v0 INT,
+OUT v1 DECIMAL(4, 2),
+IN v2 DECIMAL(4, 2),
+INOUT v3 DECIMAL(4, 2))
+BEGIN
+SET v0 = -1;
+SET v1 = 12.34;
+SET v2 = 98.67;
+SET v3 = 56.78;
+END|
+
+PREPARE stmt_str FROM 'CALL p_string(?, ?, ?, ?)';
+PREPARE stmt_dbl FROM 'CALL p_double(?, ?, ?, ?)';
+PREPARE stmt_int FROM 'CALL p_int(?, ?, ?, ?)';
+PREPARE stmt_dec FROM 'CALL p_decimal(?, ?, ?, ?)';
+
+SET @x_str_1 = NULL;
+SET @x_str_2 = NULL;
+SET @x_str_3 = NULL;
+SET @x_dbl_1 = NULL;
+SET @x_dbl_2 = NULL;
+SET @x_dbl_3 = NULL;
+SET @x_int_1 = NULL;
+SET @x_int_2 = NULL;
+SET @x_int_3 = NULL;
+SET @x_dec_1 = NULL;
+SET @x_dec_2 = NULL;
+SET @x_dec_3 = NULL;
+
+-- Testing strings...
+
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+@x_int_1 @x_str_1 @x_str_2 @x_str_3
+NULL test_v1 NULL test_v3
+
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+@x_int_1 @x_str_1 @x_str_2 @x_str_3
+NULL test_v1 NULL test_v3
+
+-- Testing doubles...
+
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+@x_int_1 @x_dbl_1 @x_dbl_2 @x_dbl_3
+NULL 12.34 NULL 56.78
+
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+@x_int_1 @x_dbl_1 @x_dbl_2 @x_dbl_3
+NULL 12.34 NULL 56.78
+
+-- Testing ints...
+
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+@x_str_1 @x_int_1 @x_int_2 @x_int_3
+test_v1 1234 NULL 5678
+
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+@x_str_1 @x_int_1 @x_int_2 @x_int_3
+test_v1 1234 NULL 5678
+
+-- Testing decs...
+
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+@x_int_1 @x_dec_1 @x_dec_2 @x_dec_3
+1234 12.34 NULL 56.78
+
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+@x_int_1 @x_dec_1 @x_dec_2 @x_dec_3
+1234 12.34 NULL 56.78
+
+DEALLOCATE PREPARE stmt_str;
+DEALLOCATE PREPARE stmt_dbl;
+DEALLOCATE PREPARE stmt_int;
+DEALLOCATE PREPARE stmt_dec;
+
+DROP PROCEDURE p_string;
+DROP PROCEDURE p_double;
+DROP PROCEDURE p_int;
+DROP PROCEDURE p_decimal;
+
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+
+CREATE PROCEDURE p1(OUT v1 CHAR(10))
+SET v1 = 'test1';
+
+CREATE PROCEDURE p2(OUT v2 CHAR(10))
+BEGIN
+SET @query = 'CALL p1(?)';
+PREPARE stmt1 FROM @query;
+EXECUTE stmt1 USING @u1;
+DEALLOCATE PREPARE stmt1;
+SET v2 = @u1;
+END|
+
+CALL p2(@a);
+SELECT @a;
+@a
+test1
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+# End of WL#4435.
+
+End of 6.0 tests.
=== added file 'mysql-test/r/test_wl4435.result'
--- a/mysql-test/r/test_wl4435.result 1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/test_wl4435.result 2008-08-07 17:52:43 +0000
@@ -0,0 +1,114 @@
+
+exec_counter: 0
+num_fields: 4
+ - 0: name: 'a1'/'a1'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 1: name: 'a2'/'a2'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 2: name: 'a3'/'a3'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 3: name: 'a4'/'a4'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 246; decimals: 1
+Data:
+ int: 1; str: '11'; dbl: 12.340000; dec: '56.7';
+ int: 2; str: '12'; dbl: 56.780000; dec: '90.1';
+ int: 3; str: '13'; dbl: 23.450000; dec: '67.8';
+EOF
+mysql_stmt_next_result(): 0; field_count: 5
+num_fields: 5
+ - 0: name: 'b0'/'b0'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 1: name: 'b1'/'b1'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 2: name: 'b2'/'b2'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 3: name: 'b3'/'b3'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 4: name: 'b4'/'b4'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 246; decimals: 1
+Data:
+ int: 100; int: 10; str: '110'; dbl: 70.700000; dec: '10.1';
+ int: 200; int: 20; str: '120'; dbl: 80.800000; dec: '20.2';
+ int: 300; int: 30; str: '130'; dbl: 90.900000; dec: '30.3';
+EOF
+mysql_stmt_next_result(): 0; field_count: 8
+num_fields: 8
+ - 0: name: 'v_str_1'/'v_str_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 1: name: 'v_dbl_1'/'v_dbl_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 2: name: 'v_dec_1'/'v_dec_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 8; max_length: 0; type: 246; decimals: 3
+ - 3: name: 'v_int_1'/'v_int_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 4: name: 'v_str_2'/'v_str_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 64; max_length: 0; type: 254; decimals: 0
+ - 5: name: 'v_dbl_2'/'v_dbl_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 5; decimals: 3
+ - 6: name: 'v_dec_2'/'v_dec_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 9; max_length: 0; type: 246; decimals: 4
+ - 7: name: 'v_int_2'/'v_int_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+Data:
+ str: 'test_1'; dbl: 12.340000; dec: '567.891'; int: 2345; str: 'test_2'; dbl: 67.891000; dec: '234.6789'; int: 6789;
+EOF
+mysql_stmt_next_result(): 0; field_count: 0
+
+exec_counter: 1
+num_fields: 4
+ - 0: name: 'a1'/'a1'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 1: name: 'a2'/'a2'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 2: name: 'a3'/'a3'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 3: name: 'a4'/'a4'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 246; decimals: 1
+Data:
+ int: 1; str: '11'; dbl: 12.340000; dec: '56.7';
+ int: 2; str: '12'; dbl: 56.780000; dec: '90.1';
+ int: 3; str: '13'; dbl: 23.450000; dec: '67.8';
+EOF
+mysql_stmt_next_result(): 0; field_count: 5
+num_fields: 5
+ - 0: name: 'b0'/'b0'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 1: name: 'b1'/'b1'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 2: name: 'b2'/'b2'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 3: name: 'b3'/'b3'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 4: name: 'b4'/'b4'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 246; decimals: 1
+Data:
+ int: 100; int: 10; str: '110'; dbl: 70.700000; dec: '10.1';
+ int: 200; int: 20; str: '120'; dbl: 80.800000; dec: '20.2';
+ int: 300; int: 30; str: '130'; dbl: 90.900000; dec: '30.3';
+EOF
+mysql_stmt_next_result(): 0; field_count: 8
+num_fields: 8
+ - 0: name: 'v_str_1'/'v_str_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 1: name: 'v_dbl_1'/'v_dbl_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 2: name: 'v_dec_1'/'v_dec_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 8; max_length: 0; type: 246; decimals: 3
+ - 3: name: 'v_int_1'/'v_int_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 4: name: 'v_str_2'/'v_str_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 64; max_length: 0; type: 254; decimals: 0
+ - 5: name: 'v_dbl_2'/'v_dbl_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 5; decimals: 3
+ - 6: name: 'v_dec_2'/'v_dec_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 9; max_length: 0; type: 246; decimals: 4
+ - 7: name: 'v_int_2'/'v_int_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+Data:
+ str: 'test_1'; dbl: 12.340000; dec: '567.891'; int: 2345; str: 'test_2'; dbl: 67.891000; dec: '234.6789'; int: 6789;
+EOF
+mysql_stmt_next_result(): 0; field_count: 0
+
+exec_counter: 2
+num_fields: 4
+ - 0: name: 'a1'/'a1'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 1: name: 'a2'/'a2'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 2: name: 'a3'/'a3'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 3: name: 'a4'/'a4'; table: 't1'/'t1'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 246; decimals: 1
+Data:
+ int: 1; str: '11'; dbl: 12.340000; dec: '56.7';
+ int: 2; str: '12'; dbl: 56.780000; dec: '90.1';
+ int: 3; str: '13'; dbl: 23.450000; dec: '67.8';
+EOF
+mysql_stmt_next_result(): 0; field_count: 5
+num_fields: 5
+ - 0: name: 'b0'/'b0'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 1: name: 'b1'/'b1'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 2: name: 'b2'/'b2'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 3: name: 'b3'/'b3'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 4: name: 'b4'/'b4'; table: 't2'/'t2'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 246; decimals: 1
+Data:
+ int: 100; int: 10; str: '110'; dbl: 70.700000; dec: '10.1';
+ int: 200; int: 20; str: '120'; dbl: 80.800000; dec: '20.2';
+ int: 300; int: 30; str: '130'; dbl: 90.900000; dec: '30.3';
+EOF
+mysql_stmt_next_result(): 0; field_count: 8
+num_fields: 8
+ - 0: name: 'v_str_1'/'v_str_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 32; max_length: 0; type: 254; decimals: 0
+ - 1: name: 'v_dbl_1'/'v_dbl_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 2: name: 'v_dec_1'/'v_dec_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 8; max_length: 0; type: 246; decimals: 3
+ - 3: name: 'v_int_1'/'v_int_1'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+ - 4: name: 'v_str_2'/'v_str_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 64; max_length: 0; type: 254; decimals: 0
+ - 5: name: 'v_dbl_2'/'v_dbl_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 5; max_length: 0; type: 5; decimals: 3
+ - 6: name: 'v_dec_2'/'v_dec_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 9; max_length: 0; type: 246; decimals: 4
+ - 7: name: 'v_int_2'/'v_int_2'; table: 'p1'/'p1'; db: 'client_test_db'; catalog: 'def'; length: 11; max_length: 0; type: 3; decimals: 0
+Data:
+ str: 'test_1'; dbl: 12.340000; dec: '567.891'; int: 2345; str: 'test_2'; dbl: 67.891000; dec: '234.6789'; int: 6789;
+EOF
+mysql_stmt_next_result(): 0; field_count: 0
=== modified file 'mysql-test/suite/falcon/r/falcon_bug_34164.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_34164.result 2008-03-06 17:31:28 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_34164.result 2008-09-12 08:52:36 +0000
@@ -29,6 +29,8 @@ a b
Warnings:
Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
UPDATE t1 SET b = 11 WHERE a = 1;
+Warnings:
+Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
# Establish connection conn2 (user = root)
USE test2;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
@@ -48,12 +50,16 @@ UPDATE t1 SET b = 111 WHERE a = 1;
# Switch to conn1
COMMIT;
# Switch to conn2
+Warnings:
+Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
SELECT * FROM t1;
a b
1 111
2 2
3 3
4 4
+Warnings:
+Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
COMMIT;
# Switch to conn1
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
@@ -73,6 +79,8 @@ a b
Warnings:
Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
UPDATE t1 SET b = 22 WHERE a = 2;
+Warnings:
+Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
# Switch to conn2
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SHOW VARIABLES LIKE 'tx_isolation';
@@ -91,12 +99,16 @@ UPDATE t1 SET b = 222 WHERE a = 2;
# Switch to conn1
COMMIT;
# Switch to conn2
+Warnings:
+Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
SELECT * FROM t1;
a b
1 111
2 222
3 3
4 4
+Warnings:
+Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
COMMIT;
# Switch to default connection
SET GLOBAL FALCON_CONSISTENT_READ=ON;
@@ -119,6 +131,8 @@ a b
Warnings:
Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
UPDATE t1 SET b = 33 WHERE a = 3;
+Warnings:
+Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
# Establish connection conn4 (user = root)
USE test2;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
@@ -145,6 +159,8 @@ a b
2 222
3 3
4 4
+Warnings:
+Warning 1568 Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.
COMMIT;
# Switch to conn3
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
@@ -164,6 +180,8 @@ a b
Warnings:
Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
UPDATE t1 SET b = 44 WHERE a = 4;
+Warnings:
+Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
# Switch to conn4
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SHOW VARIABLES LIKE 'tx_isolation';
@@ -189,6 +207,8 @@ a b
2 222
3 33
4 4
+Warnings:
+Warning 1568 Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.
COMMIT;
SELECT * FROM t1;
a b
=== modified file 'mysql-test/t/events_bugs.test'
--- a/mysql-test/t/events_bugs.test 2008-02-07 10:47:39 +0000
+++ b/mysql-test/t/events_bugs.test 2008-09-12 19:34:30 +0000
@@ -120,6 +120,14 @@ select event_schema, event_name, sql_mod
--echo "Let's check whether we change the sql_mode on ALTER EVENT"
set sql_mode='traditional';
alter event e_16407 do select 1;
+
+# wait for it to stop or we will get very spurious test failures
+let $wait_condition=
+ select count(*) = 0
+ from information_schema.processlist
+ where db = 'events_test' and info not like '%processlist%';
+--source include/wait_condition.inc
+
select event_schema, event_name, sql_mode from information_schema.events order by event_schema, event_name;
drop event e_16407;
@@ -970,5 +978,7 @@ let $wait_condition=
--source include/wait_condition.inc
DROP DATABASE events_test;
+--echo # restore the defeault
+SET GLOBAL event_scheduler = 'on';
# THIS MUST BE THE LAST LINE in this file.
=== modified file 'mysql-test/t/ps.test'
--- a/mysql-test/t/ps.test 2008-05-21 10:17:29 +0000
+++ b/mysql-test/t/ps.test 2008-08-07 17:52:43 +0000
@@ -2998,5 +2998,209 @@ execute stmt;
drop table t1;
deallocate prepare stmt;
+###########################################################################
+--echo
--echo End of 5.1 tests.
+
+###########################################################################
+
+--echo
+--echo #
+--echo # WL#4435: Support OUT-parameters in prepared statements.
+--echo #
+--echo
+
+# The idea of this test case is to check that
+# - OUT-parameters of four allowed types (string, double, int, decimal) work
+# properly;
+# - INOUT and OUT parameters work properly;
+# - A mix of IN and OUT parameters work properly;
+
+--disable_warnings
+DROP PROCEDURE IF EXISTS p_string;
+DROP PROCEDURE IF EXISTS p_double;
+DROP PROCEDURE IF EXISTS p_int;
+DROP PROCEDURE IF EXISTS p_decimal;
+--enable_warnings
+
+delimiter |;
+
+--echo
+CREATE PROCEDURE p_string(
+ IN v0 INT,
+ OUT v1 CHAR(32),
+ IN v2 CHAR(32),
+ INOUT v3 CHAR(32))
+BEGIN
+ SET v0 = -1;
+ SET v1 = 'test_v1';
+ SET v2 = 'n/a';
+ SET v3 = 'test_v3';
+END|
+
+--echo
+CREATE PROCEDURE p_double(
+ IN v0 INT,
+ OUT v1 DOUBLE(4, 2),
+ IN v2 DOUBLE(4, 2),
+ INOUT v3 DOUBLE(4, 2))
+BEGIN
+ SET v0 = -1;
+ SET v1 = 12.34;
+ SET v2 = 98.67;
+ SET v3 = 56.78;
+END|
+
+--echo
+CREATE PROCEDURE p_int(
+ IN v0 CHAR(10),
+ OUT v1 INT,
+ IN v2 INT,
+ INOUT v3 INT)
+BEGIN
+ SET v0 = 'n/a';
+ SET v1 = 1234;
+ SET v2 = 9876;
+ SET v3 = 5678;
+END|
+
+--echo
+CREATE PROCEDURE p_decimal(
+ IN v0 INT,
+ OUT v1 DECIMAL(4, 2),
+ IN v2 DECIMAL(4, 2),
+ INOUT v3 DECIMAL(4, 2))
+BEGIN
+ SET v0 = -1;
+ SET v1 = 12.34;
+ SET v2 = 98.67;
+ SET v3 = 56.78;
+END|
+
+delimiter ;|
+
+--echo
+PREPARE stmt_str FROM 'CALL p_string(?, ?, ?, ?)';
+PREPARE stmt_dbl FROM 'CALL p_double(?, ?, ?, ?)';
+PREPARE stmt_int FROM 'CALL p_int(?, ?, ?, ?)';
+PREPARE stmt_dec FROM 'CALL p_decimal(?, ?, ?, ?)';
+
+--echo
+SET @x_str_1 = NULL;
+SET @x_str_2 = NULL;
+SET @x_str_3 = NULL;
+SET @x_dbl_1 = NULL;
+SET @x_dbl_2 = NULL;
+SET @x_dbl_3 = NULL;
+SET @x_int_1 = NULL;
+SET @x_int_2 = NULL;
+SET @x_int_3 = NULL;
+SET @x_dec_1 = NULL;
+SET @x_dec_2 = NULL;
+SET @x_dec_3 = NULL;
+
+--echo
+--echo -- Testing strings...
+
+--echo
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+
+--echo
+EXECUTE stmt_str USING @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+SELECT @x_int_1, @x_str_1, @x_str_2, @x_str_3;
+
+--echo
+--echo -- Testing doubles...
+
+--echo
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+
+--echo
+EXECUTE stmt_dbl USING @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+SELECT @x_int_1, @x_dbl_1, @x_dbl_2, @x_dbl_3;
+
+--echo
+--echo -- Testing ints...
+
+--echo
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+
+--echo
+EXECUTE stmt_int USING @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+SELECT @x_str_1, @x_int_1, @x_int_2, @x_int_3;
+
+--echo
+--echo -- Testing decs...
+
+--echo
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+
+--echo
+EXECUTE stmt_dec USING @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+SELECT @x_int_1, @x_dec_1, @x_dec_2, @x_dec_3;
+
+--echo
+DEALLOCATE PREPARE stmt_str;
+DEALLOCATE PREPARE stmt_dbl;
+DEALLOCATE PREPARE stmt_int;
+DEALLOCATE PREPARE stmt_dec;
+
+--echo
+DROP PROCEDURE p_string;
+DROP PROCEDURE p_double;
+DROP PROCEDURE p_int;
+DROP PROCEDURE p_decimal;
+
+#
+# Another test case for WL#4435: check out parameters in Dynamic SQL.
+#
+
+--echo
+--disable_warnings
+DROP PROCEDURE IF EXISTS p1;
+DROP PROCEDURE IF EXISTS p2;
+--enable_warnings
+
+--echo
+
+CREATE PROCEDURE p1(OUT v1 CHAR(10))
+ SET v1 = 'test1';
+
+--echo
+
+delimiter |;
+CREATE PROCEDURE p2(OUT v2 CHAR(10))
+BEGIN
+ SET @query = 'CALL p1(?)';
+ PREPARE stmt1 FROM @query;
+ EXECUTE stmt1 USING @u1;
+ DEALLOCATE PREPARE stmt1;
+
+ SET v2 = @u1;
+END|
+delimiter ;|
+
+--echo
+
+CALL p2(@a);
+SELECT @a;
+
+--echo
+
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+--echo
+--echo # End of WL#4435.
+
+###########################################################################
+
+--echo
+--echo End of 6.0 tests.
+
+###########################################################################
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt 2008-07-09 07:12:43 +0000
+++ b/sql/CMakeLists.txt 2008-08-08 01:33:43 +0000
@@ -75,7 +75,7 @@ ADD_EXECUTABLE(mysqld
sql_tablespace.cc events.cc ../sql-common/my_user.c
partition_info.cc rpl_utility.cc rpl_injector.cc sql_locale.cc
rpl_rli.cc rpl_mi.cc sql_servers.cc sql_audit.cc
- sql_connect.cc scheduler.cc
+ sql_connect.cc scheduler.cc transaction.cc
ddl_blocker.cc si_objects.cc
sql_profile.cc event_parse_data.cc mdl.cc
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2008-07-09 07:12:43 +0000
+++ b/sql/Makefile.am 2008-08-11 12:40:09 +0000
@@ -87,9 +87,9 @@ noinst_HEADERS = item.h item_func.h item
sql_plugin.h authors.h event_parse_data.h \
event_data_objects.h event_scheduler.h \
sql_partition.h partition_info.h partition_element.h \
- probes.h sql_audit.h \
+ probes.h sql_audit.h transaction.h \
contributors.h sql_servers.h ddl_blocker.h \
- si_objects.h sql_plist.h mdl.h
+ si_objects.h sql_plist.h mdl.h records.h
mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \
item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -136,7 +136,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.
sql_builtin.cc sql_tablespace.cc partition_info.cc \
sql_servers.cc sql_audit.cc sha2.cc \
ddl_blocker.cc si_objects.cc event_parse_data.cc \
- mdl.cc
+ mdl.cc transaction.cc
if HAVE_DTRACE
mysqld_SOURCES += probes.d
=== modified file 'sql/backup/backup_test.cc'
--- a/sql/backup/backup_test.cc 2008-08-20 13:23:10 +0000
+++ b/sql/backup/backup_test.cc 2008-09-05 14:16:07 +0000
@@ -42,7 +42,7 @@ int execute_backup_test_command(THD *thd
field_list.push_back(new Item_empty_string("name", 5));
field_list.push_back(new Item_empty_string("type", 4));
field_list.push_back(new Item_empty_string("serialization", 13));
- protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
+ protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
//obs::ObjIterator *it= obs::get_databases(thd);
List_iterator<LEX_STRING> it(*db_list);
=== modified file 'sql/backup/be_snapshot.cc'
--- a/sql/backup/be_snapshot.cc 2008-07-07 12:51:56 +0000
+++ b/sql/backup/be_snapshot.cc 2008-08-08 19:58:37 +0000
@@ -44,6 +44,7 @@
#include "backup_engine.h"
#include "be_snapshot.h"
#include "backup_aux.h"
+#include "transaction.h"
namespace snapshot_backup {
@@ -72,8 +73,8 @@ result_t Backup::cleanup()
locking_thd->lock_state= LOCK_DONE; // set lock done so destructor won't wait
if (m_trans_start)
{
- ha_autocommit_or_rollback(locking_thd->m_thd, 0);
- end_active_trans(locking_thd->m_thd);
+ trans_commit_stmt(locking_thd->m_thd);
+ trans_commit_implicit(locking_thd->m_thd);
m_trans_start= FALSE;
}
if (tables_open)
@@ -102,9 +103,10 @@ result_t Backup::lock()
state.
*/
locking_thd->m_thd->lex->sql_command= SQLCOM_SELECT;
- locking_thd->m_thd->lex->start_transaction_opt|=
+ locking_thd->m_thd->lex->start_transaction_opt=
MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
- int res= begin_trans(locking_thd->m_thd);
+ int res= trans_begin(locking_thd->m_thd,
+ locking_thd->m_thd->lex->start_transaction_opt);
if (res)
DBUG_RETURN(ERROR);
m_trans_start= TRUE;
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-09-11 16:28:29 +0000
+++ b/sql/backup/kernel.cc 2008-09-16 17:58:49 +0000
@@ -84,6 +84,7 @@
#include "be_nodata.h"
#include "ddl_blocker.h"
#include "backup_progress.h"
+#include "transaction.h"
/**
@@ -299,9 +300,7 @@ int send_reply(Backup_restore_ctx &conte
// FIXME: detect errors if reported.
// FIXME: error logging.
field_list.push_back(new Item_empty_string(STRING_WITH_LEN("backup_id")));
- // FIXME: detect errors if reported.
- // FIXME: error logging.
- protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
+ protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
/*
Send field data.
@@ -804,8 +803,8 @@ int Backup_restore_ctx::close()
*/
if (m_thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
{
- ha_autocommit_or_rollback(m_thd, 0);
- end_active_trans(m_thd);
+ trans_commit_stmt(m_thd);
+ trans_commit_implicit(m_thd);
}
// unlock tables if they are still locked
=== modified file 'sql/events.cc'
--- a/sql/events.cc 2008-07-26 16:38:20 +0000
+++ b/sql/events.cc 2008-08-07 17:52:43 +0000
@@ -682,7 +682,7 @@ send_show_create_event(THD *thd, Event_t
field_list.push_back(
new Item_empty_string("Database Collation", MY_CS_NAME_SIZE));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2008-07-25 17:21:55 +0000
+++ b/sql/field.cc 2008-08-10 14:49:52 +0000
@@ -1775,7 +1775,7 @@ bool Field::optimize_range(uint idx, uin
}
-Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type __attribute__((unused)))
{
Field *tmp;
@@ -1796,7 +1796,7 @@ Field *Field::new_field(MEM_ROOT *root,
}
-Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field::new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
@@ -1813,7 +1813,7 @@ Field *Field::new_key_field(MEM_ROOT *ro
/* This is used to generate a field in TABLE from TABLE_SHARE */
-Field *Field::clone(MEM_ROOT *root, struct st_table *new_table)
+Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
{
Field *tmp;
if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
@@ -6778,7 +6778,7 @@ uint Field_string::get_key_image(uchar *
}
-Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field_string::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type)
{
Field *field;
@@ -7334,7 +7334,7 @@ int Field_varstring::cmp_binary(const uc
}
-Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field_varstring::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type)
{
Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table,
@@ -7346,7 +7346,7 @@ Field *Field_varstring::new_field(MEM_RO
Field *Field_varstring::new_key_field(MEM_ROOT *root,
- struct st_table *new_table,
+ TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
@@ -8468,7 +8468,7 @@ void Field_enum::sql_type(String &res) c
}
-Field *Field_enum::new_field(MEM_ROOT *root, struct st_table *new_table,
+Field *Field_enum::new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type)
{
Field_enum *res= (Field_enum*) Field::new_field(root, new_table, keep_type);
@@ -8751,7 +8751,7 @@ Field_bit::do_last_null_byte() const
Field *Field_bit::new_key_field(MEM_ROOT *root,
- struct st_table *new_table,
+ TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
=== modified file 'sql/field.h'
--- a/sql/field.h 2008-08-28 11:17:29 +0000
+++ b/sql/field.h 2008-09-04 18:30:34 +0000
@@ -59,8 +59,8 @@ public:
Note that you can use table->in_use as replacement for current_thd member
only inside of val_*() and store() members (e.g. you can't use it in cons)
*/
- struct st_table *table; // Pointer for table
- struct st_table *orig_table; // Pointer to original table
+ TABLE *table; // Pointer for table
+ TABLE *orig_table; // Pointer to original table
const char **table_name, *field_name;
LEX_STRING comment;
/* Bitmap of indexes that start with this field */
@@ -321,12 +321,12 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table,
+ virtual Field *new_field(MEM_ROOT *root, TABLE *new_table,
bool keep_type);
- virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ virtual Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
- Field *clone(MEM_ROOT *mem_root, struct st_table *new_table);
+ Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
@@ -1547,7 +1547,7 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_STRING; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
virtual uint get_key_image(uchar *buff,uint length, imagetype type);
private:
int do_save_field_metadata(uchar *first_byte);
@@ -1635,8 +1635,8 @@ public:
enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
- Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
+ Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
uint is_equal(Create_field *new_field);
@@ -1867,7 +1867,7 @@ public:
{
flags|=ENUM_FLAG;
}
- Field *new_field(MEM_ROOT *root, struct st_table *new_table, bool keep_type);
+ Field *new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
enum_field_types type() const { return MYSQL_TYPE_STRING; }
enum Item_result cmp_type () const { return INT_RESULT; }
enum Item_result cast_to_int_type () const { return INT_RESULT; }
@@ -2000,7 +2000,7 @@ public:
uint param_data, bool low_byte_first);
virtual void set_default();
- Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
+ Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
void set_bit_ptr(uchar *bit_ptr_arg, uchar bit_ofs_arg)
@@ -2123,7 +2123,7 @@ public:
A class for sending info to the client
*/
-class Send_field {
+class Send_field :public Sql_alloc {
public:
const char *db_name;
const char *table_name,*org_table_name;
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2008-09-03 14:40:19 +0000
+++ b/sql/handler.cc 2008-09-04 18:30:34 +0000
@@ -27,6 +27,7 @@
#include "rpl_filter.h"
#include <myisampack.h>
#include "myisam.h"
+#include "transaction.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -816,16 +817,16 @@ void ha_close_connection(THD* thd)
a transaction in a given engine is read-write and will not
involve the two-phase commit protocol!
- At the end of a statement, server call
- ha_autocommit_or_rollback() is invoked. This call in turn
- invokes handlerton::prepare() for every involved engine.
- Prepare is followed by a call to handlerton::commit_one_phase()
- If a one-phase commit will suffice, handlerton::prepare() is not
- invoked and the server only calls handlerton::commit_one_phase().
- At statement commit, the statement-related read-write engine
- flag is propagated to the corresponding flag in the normal
- transaction. When the commit is complete, the list of registered
- engines is cleared.
+ At the end of a statement, server call trans_commit_stmt is
+ invoked. This call in turn invokes handlerton::prepare()
+ for every involved engine. Prepare is followed by a call
+ to handlerton::commit_one_phase() If a one-phase commit
+ will suffice, handlerton::prepare() is not invoked and
+ the server only calls handlerton::commit_one_phase().
+ At statement commit, the statement-related read-write
+ engine flag is propagated to the corresponding flag in the
+ normal transaction. When the commit is complete, the list
+ of registered engines is cleared.
Rollback is handled in a similar fashion.
@@ -836,7 +837,7 @@ void ha_close_connection(THD* thd)
do not "register" in thd->transaction lists, and thus do not
modify the transaction state. Besides, each DDL in
MySQL is prefixed with an implicit normal transaction commit
- (a call to end_active_trans()), and thus leaves nothing
+ (a call to trans_commit_implicit()), and thus leaves nothing
to modify.
However, as it has been pointed out with CREATE TABLE .. SELECT,
some DDL statements can start a *new* transaction.
@@ -1277,42 +1278,6 @@ int ha_rollback_trans(THD *thd, bool all
DBUG_RETURN(error);
}
-/**
- This is used to commit or rollback a single statement depending on
- the value of error.
-
- @note
- Note that if the autocommit is on, then the following call inside
- InnoDB will commit or rollback the whole transaction (= the statement). The
- autocommit mechanism built into InnoDB is based on counting locks, but if
- the user has used LOCK TABLES then that mechanism does not know to do the
- commit.
-*/
-int ha_autocommit_or_rollback(THD *thd, int error)
-{
- DBUG_ENTER("ha_autocommit_or_rollback");
-
- if (thd->transaction.stmt.ha_list)
- {
- if (!error)
- {
- if (ha_commit_trans(thd, 0))
- error=1;
- }
- else
- {
- (void) ha_rollback_trans(thd, 0);
- if (thd->transaction_rollback_request && !thd->in_sub_stmt)
- (void) ha_rollback(thd);
- }
-
- thd->variables.tx_isolation=thd->session_tx_isolation;
- }
-
- DBUG_RETURN(error);
-}
-
-
struct xahton_st {
XID *xid;
int result;
@@ -1584,7 +1549,7 @@ bool mysql_xa_recover(THD *thd)
field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(1);
@@ -3317,7 +3282,7 @@ int ha_enable_transaction(THD *thd, bool
So, let's commit an open transaction (if any) now.
*/
if (!(error= ha_commit_trans(thd, 0)))
- error= end_trans(thd, COMMIT);
+ error= trans_commit_implicit(thd);
}
DBUG_RETURN(error);
}
@@ -5053,7 +5018,7 @@ bool ha_show_status(THD *thd, handlerton
field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
field_list.push_back(new Item_empty_string("Status",10));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
return TRUE;
=== modified file 'sql/handler.h'
--- a/sql/handler.h 2008-09-11 18:36:05 +0000
+++ b/sql/handler.h 2008-09-16 17:58:49 +0000
@@ -572,7 +572,8 @@ class st_alter_tablespace : public Sql_a
/* The handler for a table type. Will be included in the TABLE structure */
-struct st_table;
+struct TABLE;
+struct TABLE_SHARE;
/*
Make sure that the order of schema_tables and enum_schema_tables are the same.
@@ -615,8 +616,6 @@ enum enum_schema_tables
SCH_VIEWS
};
-typedef struct st_table TABLE;
-typedef struct st_table_share TABLE_SHARE;
struct st_foreign_key_info;
typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
typedef bool (stat_print_fn)(THD *thd, const char *type, uint type_len,
@@ -691,6 +690,7 @@ struct handler_iterator {
void *buffer;
};
+class handler;
/*
handlerton is a singleton structure - one instance per storage engine -
to provide access to storage engine functionality that works on the
@@ -1386,8 +1386,8 @@ class handler :public Sql_alloc
public:
typedef ulonglong Table_flags;
protected:
- struct st_table_share *table_share; /* The table definition */
- struct st_table *table; /* The current open table */
+ TABLE_SHARE *table_share; /* The table definition */
+ TABLE *table; /* The current open table */
Table_flags cached_table_flags; /* Set on init() and open() */
ha_rows estimation_rows_to_insert;
@@ -2457,10 +2457,6 @@ extern TYPELIB tx_isolation_typelib;
extern TYPELIB myisam_stats_method_typelib;
extern ulong total_ha, total_ha_2pc;
- /* Wrapper functions */
-#define ha_commit(thd) (ha_commit_trans((thd), TRUE))
-#define ha_rollback(thd) (ha_rollback_trans((thd), TRUE))
-
/* lookups */
handlerton *ha_default_handlerton(THD *thd);
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name);
@@ -2537,13 +2533,12 @@ int ha_release_temporary_latches(THD *th
int ha_start_consistent_snapshot(THD *thd);
int ha_commit_or_rollback_by_xid(XID *xid, bool commit);
int ha_commit_one_phase(THD *thd, bool all);
+int ha_commit_trans(THD *thd, bool all);
int ha_rollback_trans(THD *thd, bool all);
int ha_prepare(THD *thd);
int ha_recover(HASH *commit_list);
/* transactions: these functions never call handlerton functions directly */
-int ha_commit_trans(THD *thd, bool all);
-int ha_autocommit_or_rollback(THD *thd, int error);
int ha_enable_transaction(THD *thd, bool on);
/* savepoints */
=== modified file 'sql/item.cc'
--- a/sql/item.cc 2008-08-20 18:05:57 +0000
+++ b/sql/item.cc 2008-09-04 18:30:34 +0000
@@ -2515,7 +2515,8 @@ Item_param::Item_param(uint pos_in_query
param_type(MYSQL_TYPE_VARCHAR),
pos_in_query(pos_in_query_arg),
set_param_func(default_set_param_func),
- limit_clause_param(FALSE)
+ limit_clause_param(FALSE),
+ m_out_param_info(NULL)
{
name= (char*) "?";
/*
@@ -2596,6 +2597,17 @@ void Item_param::set_decimal(const char
DBUG_VOID_RETURN;
}
+void Item_param::set_decimal(const my_decimal *dv)
+{
+ state= DECIMAL_VALUE;
+
+ my_decimal2decimal(dv, &decimal_value);
+
+ decimals= (uint8) decimal_value.frac;
+ unsigned_flag= !decimal_value.sign();
+ max_length= my_decimal_precision_to_length(decimal_value.intg + decimals,
+ decimals, unsigned_flag);
+}
/**
Set parameter value from MYSQL_TIME value.
@@ -3217,6 +3229,158 @@ Item_param::set_param_type_and_swap_valu
str_value_ptr.swap(src->str_value_ptr);
}
+
+/**
+ This operation is intended to store some item value in Item_param to be
+ used later.
+
+ @param thd thread context
+ @param ctx stored procedure runtime context
+ @param it a pointer to an item in the tree
+
+ @return Error status
+ @retval TRUE on error
+ @retval FALSE on success
+*/
+
+bool
+Item_param::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ Item *value= *it;
+
+ if (value->is_null())
+ {
+ set_null();
+ return FALSE;
+ }
+
+ null_value= FALSE;
+
+ switch (value->result_type()) {
+ case STRING_RESULT:
+ {
+ char str_buffer[STRING_BUFFER_USUAL_SIZE];
+ String sv_buffer(str_buffer, sizeof(str_buffer), &my_charset_bin);
+ String *sv= value->val_str(&sv_buffer);
+
+ if (!sv)
+ return TRUE;
+
+ set_str(sv->c_ptr_safe(), sv->length());
+ str_value_ptr.set(str_value.ptr(),
+ str_value.length(),
+ str_value.charset());
+ collation.set(str_value.charset(), DERIVATION_COERCIBLE);
+ decimals= 0;
+ param_type= MYSQL_TYPE_STRING;
+
+ break;
+ }
+
+ case REAL_RESULT:
+ set_double(value->val_real());
+ param_type= MYSQL_TYPE_DOUBLE;
+ break;
+
+ case INT_RESULT:
+ set_int(value->val_int(), value->max_length);
+ param_type= MYSQL_TYPE_LONG;
+ break;
+
+ case DECIMAL_RESULT:
+ {
+ my_decimal dv_buf;
+ my_decimal *dv= value->val_decimal(&dv_buf);
+
+ if (!dv)
+ return TRUE;
+
+ set_decimal(dv);
+ param_type= MYSQL_TYPE_NEWDECIMAL;
+
+ break;
+ }
+
+ default:
+ /* That can not happen. */
+
+ DBUG_ASSERT(TRUE); // Abort in debug mode.
+
+ set_null(); // Set to NULL in release mode.
+ return FALSE;
+ }
+
+ item_result_type= value->result_type();
+ item_type= value->type();
+ return FALSE;
+}
+
+
+/**
+ Setter of Item_param::m_out_param_info.
+
+ m_out_param_info is used to store information about store routine
+ OUT-parameters, such as stored routine name, database, stored routine
+ variable name. It is supposed to be set in sp_head::execute() after
+ Item_param::set_value() is called.
+*/
+
+void
+Item_param::set_out_param_info(Send_field *info)
+{
+ m_out_param_info= info;
+}
+
+
+/**
+ Getter of Item_param::m_out_param_info.
+
+ m_out_param_info is used to store information about store routine
+ OUT-parameters, such as stored routine name, database, stored routine
+ variable name. It is supposed to be retrieved in
+ Protocol_binary::send_out_parameters() during creation of OUT-parameter
+ result set.
+*/
+
+const Send_field *
+Item_param::get_out_param_info() const
+{
+ return m_out_param_info;
+}
+
+
+/**
+ Fill meta-data information for the corresponding column in a result set.
+ If this is an OUT-parameter of a stored procedure, preserve meta-data of
+ stored-routine variable.
+
+ @param field container for meta-data to be filled
+*/
+
+void Item_param::make_field(Send_field *field)
+{
+ Item::make_field(field);
+
+ if (!m_out_param_info)
+ return;
+
+ /*
+ This is an OUT-parameter of stored procedure. We should use
+ OUT-parameter info to fill out the names.
+ */
+
+ field->db_name= m_out_param_info->db_name;
+ field->table_name= m_out_param_info->table_name;
+ field->org_table_name= m_out_param_info->org_table_name;
+ field->col_name= m_out_param_info->col_name;
+ field->org_col_name= m_out_param_info->org_col_name;
+ field->length= m_out_param_info->length;
+ field->charsetnr= m_out_param_info->charsetnr;
+ field->flags= m_out_param_info->flags;
+ field->decimals= m_out_param_info->decimals;
+ field->type= m_out_param_info->type;
+}
+
/****************************************************************************
Item_copy_string
****************************************************************************/
@@ -3250,7 +3414,7 @@ my_decimal *Item_copy_string::val_decima
/*
- Functions to convert item to field (for send_fields)
+ Functions to convert item to field (for send_result_set_metadata)
*/
/* ARGSUSED */
=== modified file 'sql/item.h'
--- a/sql/item.h 2008-08-20 10:29:58 +0000
+++ b/sql/item.h 2008-09-04 18:30:34 +0000
@@ -443,6 +443,11 @@ public:
TRUE if error has occured.
*/
virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it)= 0;
+
+ virtual void set_out_param_info(Send_field *info) {}
+
+ virtual const Send_field *get_out_param_info() const
+ { return NULL; }
};
@@ -1609,7 +1614,8 @@ public:
/* Item represents one placeholder ('?') of prepared statement */
-class Item_param :public Item
+class Item_param :public Item,
+ private Settable_routine_parameter
{
char cnvbuf[MAX_FIELD_WIDTH];
String cnvstr;
@@ -1697,6 +1703,7 @@ public:
void set_int(longlong i, uint32 max_length_arg);
void set_double(double i);
void set_decimal(const char *str, ulong length);
+ void set_decimal(const my_decimal *dv);
bool set_str(const char *str, ulong length);
bool set_longdata(const char *str, ulong length);
void set_time(MYSQL_TIME *tm, timestamp_type type, uint32 max_length_arg);
@@ -1746,6 +1753,25 @@ public:
/** Item is a argument to a limit clause. */
bool limit_clause_param;
void set_param_type_and_swap_value(Item_param *from);
+
+private:
+ virtual inline Settable_routine_parameter *
+ get_settable_routine_parameter()
+ {
+ return this;
+ }
+
+ virtual bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+
+ virtual void set_out_param_info(Send_field *info);
+
+public:
+ virtual const Send_field *get_out_param_info() const;
+
+ virtual void make_field(Send_field *field);
+
+private:
+ Send_field *m_out_param_info;
};
@@ -2098,7 +2124,7 @@ public:
/**
Item_empty_string -- is a utility class to put an item into List<Item>
- which is then used in protocol.send_fields() when sending SHOW output to
+ which is then used in protocol.send_result_set_metadata() when sending SHOW output to
the client.
*/
=== modified file 'sql/lock.cc'
--- a/sql/lock.cc 2008-07-09 07:12:43 +0000
+++ b/sql/lock.cc 2008-08-08 01:33:43 +0000
@@ -74,6 +74,7 @@
*/
#include "mysql_priv.h"
+#include "transaction.h"
#include <hash.h>
#include <assert.h>
@@ -1440,7 +1441,7 @@ int try_transactional_lock(THD *thd, TAB
err:
/* We need to explicitly commit if autocommit mode is active. */
- (void) ha_autocommit_or_rollback(thd, 0);
+ trans_commit_stmt(thd);
/* Close the tables. The locks (if taken) persist in the storage engines. */
close_tables_for_reopen(thd, &table_list, FALSE);
thd->in_lock_tables= FALSE;
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2008-08-28 09:59:54 +0000
+++ b/sql/log_event.cc 2008-09-04 18:30:34 +0000
@@ -31,6 +31,7 @@
#include "rpl_filter.h"
#include "rpl_utility.h"
#include "rpl_record.h"
+#include "transaction.h"
#include <my_dir.h>
#endif /* MYSQL_CLIENT */
@@ -5093,7 +5094,7 @@ int Xid_log_event::do_apply_event(Relay_
/* For a slave Xid_log_event is COMMIT */
general_log_print(thd, COM_QUERY,
"COMMIT /* implicit, from Xid_log_event */");
- return end_trans(thd, COMMIT);
+ return trans_commit(thd);
}
Log_event::enum_skip_reason
@@ -7417,7 +7418,7 @@ Rows_log_event::do_update_pos(Relay_log_
are involved, commit the transaction and flush the pending event to the
binlog.
*/
- error= ha_autocommit_or_rollback(thd, 0);
+ error= trans_commit_stmt(thd);
/*
Now what if this is not a transactional engine? we still need to
=== modified file 'sql/log_event_old.cc'
--- a/sql/log_event_old.cc 2008-06-28 11:00:59 +0000
+++ b/sql/log_event_old.cc 2008-08-08 01:33:43 +0000
@@ -6,6 +6,7 @@
#endif
#include "log_event_old.h"
#include "rpl_record_old.h"
+#include "transaction.h"
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
@@ -1827,7 +1828,7 @@ Old_rows_log_event::do_update_pos(Relay_
are involved, commit the transaction and flush the pending event to the
binlog.
*/
- error= ha_autocommit_or_rollback(thd, 0);
+ error= trans_commit_stmt(thd);
/*
Now what if this is not a transactional engine? we still need to
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2008-09-11 16:28:29 +0000
+++ b/sql/mysql_priv.h 2008-09-16 17:58:49 +0000
@@ -688,8 +688,6 @@ enum enum_parsing_place
IN_ON
};
-struct st_table;
-
class THD;
enum enum_check_fields
@@ -890,15 +888,6 @@ bool parse_sql(THD *thd,
Parser_state *parser_state,
Object_creation_ctx *creation_ctx);
-enum enum_mysql_completiontype {
- ROLLBACK_RELEASE=-2, ROLLBACK=1, ROLLBACK_AND_CHAIN=7,
- COMMIT_RELEASE=-1, COMMIT=0, COMMIT_AND_CHAIN=6
-};
-
-bool begin_trans(THD *thd);
-bool end_active_trans(THD *thd);
-int end_trans(THD *thd, enum enum_mysql_completiontype completion);
-
Item *negate_expression(THD *thd, Item *expr);
/* log.cc */
@@ -928,6 +917,7 @@ bool general_log_write(THD *thd, enum en
#include "tztime.h"
#ifdef MYSQL_SERVER
#include "sql_servers.h"
+#include "records.h"
#include "opt_range.h"
#ifdef HAVE_QUERY_CACHE
=== modified file 'sql/procedure.h'
--- a/sql/procedure.h 2008-03-21 15:48:28 +0000
+++ b/sql/procedure.h 2008-08-07 17:52:43 +0000
@@ -23,7 +23,7 @@
#define PROC_NO_SORT 1 /**< Bits in flags */
#define PROC_GROUP 2 /**< proc must have group */
-/* Procedure items used by procedures to store values for send_fields */
+/* Procedure items used by procedures to store values for send_result_set_metadata */
class Item_proc :public Item
{
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2008-08-11 19:37:53 +0000
+++ b/sql/protocol.cc 2008-09-04 18:30:34 +0000
@@ -68,7 +68,7 @@ bool Protocol_binary::net_store_data(con
exactly one byte to store length. It allows not to use
the "convert" member as a temporary buffer, conversion
is done directly to the "packet" member.
- The limit 251 is good enough to optimize send_fields()
+ The limit 251 is good enough to optimize send_result_set_metadata()
because column, table, database names fit into this limit.
*/
@@ -246,7 +246,7 @@ static uchar eof_buff[1]= { (uchar) 254
@param thd Thread handler
@param no_flush Set to 1 if there will be more data to the client,
- like in send_fields().
+ like in send_result_set_metadata().
*/
void
@@ -562,16 +562,16 @@ bool Protocol::flush()
1 Error (Note that in this case the error is not sent to the
client)
*/
-bool Protocol::send_fields(List<Item> *list, uint flags)
+bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
{
List_iterator_fast<Item> it(*list);
Item *item;
- uchar buff[80];
+ uchar buff[MAX_FIELD_WIDTH];
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
Protocol_text prot(thd);
String *local_packet= prot.storage_packet();
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
- DBUG_ENTER("send_fields");
+ DBUG_ENTER("send_result_set_metadata");
if (flags & SEND_NUM_ROWS)
{ // Packet with number of elements
@@ -704,7 +704,7 @@ bool Protocol::send_fields(List<Item> *l
*/
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
}
- DBUG_RETURN(prepare_for_send(list));
+ DBUG_RETURN(prepare_for_send(list->elements));
err:
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
@@ -723,6 +723,38 @@ bool Protocol::write()
/**
+ Send one result set row.
+
+ @param row_items a collection of column values for that row
+
+ @return Error status.
+ @retval TRUE Error.
+ @retval FALSE Success.
+*/
+
+bool Protocol::send_result_set_row(List<Item> *row_items)
+{
+ char buffer[MAX_FIELD_WIDTH];
+ String str_buffer(buffer, sizeof (buffer), &my_charset_bin);
+ List_iterator_fast<Item> it(*row_items);
+
+ DBUG_ENTER("Protocol::send_result_set_row");
+
+ for (Item *item= it++; item; item= it++)
+ {
+ if (item->send(this, &str_buffer) || thd->is_error())
+ {
+ this->free(); // Free used buffer
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
Send \\0 end terminated string.
@param from NullS or \\0 terminated string
@@ -1047,6 +1079,53 @@ bool Protocol_text::store_time(MYSQL_TIM
return net_store_data((uchar*) buff, length);
}
+/**
+ Assign OUT-parameters to user variables.
+
+ @param sp_params List of PS/SP parameters (both input and output).
+
+ @return Error status.
+ @retval FALSE Success.
+ @retval TRUE Error.
+*/
+
+bool Protocol_text::send_out_parameters(List<Item_param> *sp_params)
+{
+ DBUG_ASSERT(sp_params->elements ==
+ thd->lex->prepared_stmt_params.elements);
+
+ List_iterator_fast<Item_param> item_param_it(*sp_params);
+ List_iterator_fast<LEX_STRING> user_var_name_it(thd->lex->prepared_stmt_params);
+
+ while (true)
+ {
+ Item_param *item_param= item_param_it++;
+ LEX_STRING *user_var_name= user_var_name_it++;
+
+ if (!item_param || !user_var_name)
+ break;
+
+ if (!item_param->get_out_param_info())
+ continue; // It's an IN-parameter.
+
+ Item_func_set_user_var *suv=
+ new Item_func_set_user_var(*user_var_name, item_param);
+ /*
+ Item_func_set_user_var is not fixed after construction, call
+ fix_fields().
+ */
+ if (suv->fix_fields(thd, NULL))
+ return TRUE;
+
+ if (suv->check(FALSE))
+ return TRUE;
+
+ if (suv->update())
+ return TRUE;
+ }
+
+ return FALSE;
+}
/****************************************************************************
Functions to handle the binary protocol used with prepared statements
@@ -1067,14 +1146,13 @@ bool Protocol_text::store_time(MYSQL_TIM
[..]..[[length]data] data
****************************************************************************/
-bool Protocol_binary::prepare_for_send(List<Item> *item_list)
+bool Protocol_binary::prepare_for_send(uint num_columns)
{
- Protocol::prepare_for_send(item_list);
+ Protocol::prepare_for_send(num_columns);
bit_fields= (field_count+9)/8;
- if (packet->alloc(bit_fields+1))
- return 1;
+ return packet->alloc(bit_fields+1);
+
/* prepare_for_resend will be called after this one */
- return 0;
}
@@ -1262,3 +1340,80 @@ bool Protocol_binary::store_time(MYSQL_T
buff[0]=(char) length; // Length is stored first
return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
}
+
+/**
+ Send a result set with OUT-parameter values by means of PS-protocol.
+
+ @param sp_params List of PS/SP parameters (both input and output).
+
+ @return Error status.
+ @retval FALSE Success.
+ @retval TRUE Error.
+*/
+
+bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
+{
+ if (!(thd->client_capabilities & CLIENT_PS_MULTI_RESULTS))
+ {
+ /* The client does not support OUT-parameters. */
+ return FALSE;
+ }
+
+ List<Item> out_param_lst;
+
+ {
+ List_iterator_fast<Item_param> item_param_it(*sp_params);
+
+ while (true)
+ {
+ Item_param *item_param= item_param_it++;
+
+ if (!item_param)
+ break;
+
+ if (!item_param->get_out_param_info())
+ continue; // It's an IN-parameter.
+
+ if (out_param_lst.push_back(item_param))
+ return TRUE;
+ }
+ }
+
+ if (!out_param_lst.elements)
+ return FALSE;
+
+ /*
+ We have to set SERVER_PS_OUT_PARAMS in THD::server_status, because it
+ is used in send_result_set_metadata().
+ */
+
+ thd->server_status|= SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS;
+
+ /* Send meta-data. */
+ if (send_result_set_metadata(&out_param_lst, SEND_NUM_ROWS | SEND_EOF))
+ return TRUE;
+
+ /* Send data. */
+
+ prepare_for_resend();
+
+ if (send_result_set_row(&out_param_lst))
+ return TRUE;
+
+ if (write())
+ return TRUE;
+
+ /* Restore THD::server_status. */
+ thd->server_status&= ~SERVER_PS_OUT_PARAMS;
+
+ /*
+ Reset SERVER_MORE_RESULTS_EXISTS bit, because this is the last packet
+ for sure.
+ */
+ thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
+
+ /* Send EOF-packet. */
+ net_send_eof(thd, thd->server_status, 0);
+
+ return FALSE;
+}
=== modified file 'sql/protocol.h'
--- a/sql/protocol.h 2008-02-11 16:11:22 +0000
+++ b/sql/protocol.h 2008-08-07 17:52:43 +0000
@@ -20,6 +20,7 @@
class i_string;
class THD;
+class Item_param;
typedef struct st_mysql_field MYSQL_FIELD;
typedef struct st_mysql_rows MYSQL_ROWS;
@@ -53,7 +54,8 @@ public:
void init(THD* thd_arg);
enum { SEND_NUM_ROWS= 1, SEND_DEFAULTS= 2, SEND_EOF= 4 };
- virtual bool send_fields(List<Item> *list, uint flags);
+ virtual bool send_result_set_metadata(List<Item> *list, uint flags);
+ bool send_result_set_row(List<Item> *row_items);
bool store(I_List<i_string> *str_list);
bool store(const char *from, CHARSET_INFO *cs);
@@ -71,9 +73,9 @@ public:
inline bool store(String *str)
{ return store((char*) str->ptr(), str->length(), str->charset()); }
- virtual bool prepare_for_send(List<Item> *item_list)
+ virtual bool prepare_for_send(uint num_columns)
{
- field_count=item_list->elements;
+ field_count= num_columns;
return 0;
}
virtual bool flush();
@@ -95,6 +97,8 @@ public:
virtual bool store_date(MYSQL_TIME *time)=0;
virtual bool store_time(MYSQL_TIME *time)=0;
virtual bool store(Field *field)=0;
+
+ virtual bool send_out_parameters(List<Item_param> *sp_params)=0;
#ifdef EMBEDDED_LIBRARY
int begin_dataset();
virtual void remove_last_row() {}
@@ -136,6 +140,8 @@ public:
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
+
+ virtual bool send_out_parameters(List<Item_param> *sp_params);
#ifdef EMBEDDED_LIBRARY
void remove_last_row();
#endif
@@ -150,7 +156,7 @@ private:
public:
Protocol_binary() {}
Protocol_binary(THD *thd_arg) :Protocol(thd_arg) {}
- virtual bool prepare_for_send(List<Item> *item_list);
+ virtual bool prepare_for_send(uint num_columns);
virtual void prepare_for_resend();
#ifdef EMBEDDED_LIBRARY
virtual bool write();
@@ -171,6 +177,9 @@ public:
virtual bool store(float nr, uint32 decimals, String *buffer);
virtual bool store(double from, uint32 decimals, String *buffer);
virtual bool store(Field *field);
+
+ virtual bool send_out_parameters(List<Item_param> *sp_params);
+
virtual enum enum_protocol_type type() { return PROTOCOL_BINARY; };
};
=== modified file 'sql/records.cc'
--- a/sql/records.cc 2008-07-17 19:55:18 +0000
+++ b/sql/records.cc 2008-08-11 12:40:09 +0000
@@ -13,6 +13,9 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifdef USE_PRAGMA_INTERFACE
+#pragma implementation /* gcc class implementation */
+#endif
/**
@file
@@ -21,8 +24,10 @@
Functions for easy reading of records, possible through a cache
*/
+#include "records.h"
#include "mysql_priv.h"
+
static int rr_quick(READ_RECORD *info);
int rr_sequential(READ_RECORD *info);
static int rr_from_tempfile(READ_RECORD *info);
=== added file 'sql/records.h'
--- a/sql/records.h 1970-01-01 00:00:00 +0000
+++ b/sql/records.h 2008-09-12 09:09:27 +0000
@@ -0,0 +1,76 @@
+#ifndef SQL_RECORDS_H
+#define SQL_RECORDS_H
+/* Copyright (C) 2008 Sun/MySQL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+#include <my_global.h> /* for uint typedefs */
+
+struct st_join_table;
+class handler;
+struct TABLE;
+class THD;
+class SQL_SELECT;
+
+/**
+ A context for reading through a single table using a chosen access method:
+ index read, scan, etc, use of cache, etc.
+
+ Use by:
+ READ_RECORD read_record;
+ init_read_record(&read_record, ...);
+ while (read_record.read_record())
+ {
+ ...
+ }
+ end_read_record();
+*/
+
+struct READ_RECORD
+{
+ typedef int (*Read_func)(READ_RECORD*);
+ typedef int (*Setup_func)(struct st_join_table*);
+
+ TABLE *table; /* Head-form */
+ handler *file;
+ TABLE **forms; /* head and ref forms */
+ Read_func read_record;
+ THD *thd;
+ SQL_SELECT *select;
+ uint cache_records;
+ uint ref_length,struct_length,reclength,rec_cache_size,error_offset;
+ uint index;
+ uchar *ref_pos; /* pointer to form->refpos */
+ uchar *record;
+ uchar *rec_buf; /* to read field values after filesort */
+ uchar *cache,*cache_pos,*cache_end,*read_positions;
+ struct st_io_cache *io_cache;
+ bool print_error, ignore_not_found_rows;
+ struct st_join_table *do_insideout_scan;
+
+public:
+ READ_RECORD() {}
+};
+
+void init_read_record(READ_RECORD *info, THD *thd, TABLE *reg_form,
+ SQL_SELECT *select, int use_record_cache,
+ bool print_errors, bool disable_rr_cache);
+void init_read_record_idx(READ_RECORD *info, THD *thd, TABLE *table,
+ bool print_error, uint idx);
+void end_read_record(READ_RECORD *info);
+
+#endif /* SQL_RECORDS_H */
=== modified file 'sql/repl_failsafe.cc'
--- a/sql/repl_failsafe.cc 2008-03-27 19:02:15 +0000
+++ b/sql/repl_failsafe.cc 2008-08-07 17:52:43 +0000
@@ -470,7 +470,7 @@ bool show_new_master(THD* thd)
field_list.push_back(new Item_empty_string("Log_name", 20));
field_list.push_back(new Item_return_int("Log_pos", 10,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
@@ -664,7 +664,7 @@ bool show_slave_hosts(THD* thd)
field_list.push_back(new Item_return_int("Master_id", 10,
MYSQL_TYPE_LONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
=== modified file 'sql/rpl_injector.cc'
--- a/sql/rpl_injector.cc 2008-05-29 15:44:11 +0000
+++ b/sql/rpl_injector.cc 2008-08-08 01:33:43 +0000
@@ -15,6 +15,7 @@
#include "mysql_priv.h"
#include "rpl_injector.h"
+#include "transaction.h"
/*
injector::transaction - member definitions
@@ -35,8 +36,7 @@ injector::transaction::transaction(MYSQL
m_start_pos.m_file_name= my_strdup(log_info.log_file_name, MYF(0));
m_start_pos.m_file_pos= log_info.pos;
- m_thd->lex->start_transaction_opt= 0; /* for begin_trans() */
- begin_trans(m_thd);
+ trans_begin(m_thd);
thd->set_current_stmt_binlog_row_based();
}
@@ -82,8 +82,8 @@ int injector::transaction::commit()
is committed by committing the statement transaction
explicitly.
*/
- ha_autocommit_or_rollback(m_thd, 0);
- end_trans(m_thd, COMMIT);
+ trans_commit_stmt(m_thd);
+ trans_commit(m_thd);
DBUG_RETURN(0);
}
=== modified file 'sql/rpl_injector.h'
--- a/sql/rpl_injector.h 2008-05-29 15:44:11 +0000
+++ b/sql/rpl_injector.h 2008-08-10 14:49:52 +0000
@@ -25,9 +25,8 @@
/* Forward declarations */
class handler;
class MYSQL_BIN_LOG;
-struct st_table;
+struct TABLE;
-typedef st_table TABLE;
/*
Injector to inject rows into the MySQL server.
=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc 2008-06-28 11:00:59 +0000
+++ b/sql/rpl_rli.cc 2008-08-08 01:33:43 +0000
@@ -20,6 +20,7 @@
#include <my_dir.h> // For MY_STAT
#include "sql_repl.h" // For check_binlog_magic
#include "rpl_utility.h"
+#include "transaction.h"
static int count_relay_log_space(Relay_log_info* rli);
@@ -1162,8 +1163,8 @@ void Relay_log_info::cleanup_context(THD
*/
if (error)
{
- ha_autocommit_or_rollback(thd, 1); // if a "statement transaction"
- end_trans(thd, ROLLBACK); // if a "real transaction"
+ trans_rollback_stmt(thd); // if a "statement transaction"
+ trans_rollback(thd); // if a "real transaction"
}
m_table_map.clear_tables();
slave_close_thread_tables(thd);
=== modified file 'sql/rpl_tblmap.cc'
--- a/sql/rpl_tblmap.cc 2008-08-20 16:21:14 +0000
+++ b/sql/rpl_tblmap.cc 2008-09-04 18:30:34 +0000
@@ -53,7 +53,7 @@ table_mapping::~table_mapping()
free_root(&m_mem_root, MYF(0));
}
-TABLE* table_mapping::get_table(ulong table_id)
+TABLE *table_mapping::get_table(ulong table_id)
{
DBUG_ENTER("table_mapping::get_table(ulong)");
DBUG_PRINT("enter", ("table_id: %lu", table_id));
=== modified file 'sql/rpl_tblmap.h'
--- a/sql/rpl_tblmap.h 2008-08-20 14:06:31 +0000
+++ b/sql/rpl_tblmap.h 2008-09-04 18:30:34 +0000
@@ -18,8 +18,7 @@
/* Forward declarations */
#ifndef MYSQL_CLIENT
-struct st_table;
-typedef st_table TABLE;
+struct TABLE;
#else
class Table_map_log_event;
typedef Table_map_log_event TABLE;
=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc 2008-09-04 13:46:04 +0000
+++ b/sql/set_var.cc 2008-09-05 14:16:07 +0000
@@ -61,6 +61,7 @@
#include <my_dir.h>
#include "events.h"
+#include "transaction.h"
/* WITH_NDBCLUSTER_STORAGE_ENGINE */
#ifdef WITH_NDBCLUSTER_STORAGE_ENGINE
@@ -3181,7 +3182,7 @@ static bool set_option_autocommit(THD *t
*/
if (var->save_result.ulong_value != 0 &&
(thd->options & OPTION_NOT_AUTOCOMMIT) &&
- ha_commit(thd))
+ trans_commit(thd))
return 1;
if (var->save_result.ulong_value != 0)
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2008-07-21 03:55:09 +0000
+++ b/sql/slave.cc 2008-08-08 01:39:23 +0000
@@ -34,6 +34,7 @@
#include "sql_repl.h"
#include "rpl_filter.h"
#include "repl_failsafe.h"
+#include "transaction.h"
#include <thr_alarm.h>
#include <my_dir.h>
#include <sql_common.h>
@@ -1240,7 +1241,7 @@ bool show_master_info(THD* thd, Master_i
field_list.push_back(new Item_return_int("Last_SQL_Errno", 4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Last_SQL_Error", 20));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -1953,7 +1954,7 @@ static int exec_relay_log_event(THD* thd
else
{
exec_res= 0;
- end_trans(thd, ROLLBACK);
+ trans_rollback(thd);
/* chance for concurrent connection to get more locks */
safe_sleep(thd, min(rli->trans_retries, MAX_SLAVE_RETRY_PAUSE),
(CHECK_KILLED_FUNC)sql_slave_killed, (void*)rli);
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2008-08-20 10:29:58 +0000
+++ b/sql/sp_head.cc 2008-09-04 18:30:34 +0000
@@ -2010,6 +2010,16 @@ sp_head::execute_procedure(THD *thd, Lis
err_status= TRUE;
break;
}
+
+ Send_field *out_param_info= new (thd->mem_root) Send_field();
+ nctx->get_item(i)->make_field(out_param_info);
+ out_param_info->db_name= m_db.str;
+ out_param_info->table_name= m_name.str;
+ out_param_info->org_table_name= m_name.str;
+ out_param_info->col_name= spvar->name.str;
+ out_param_info->org_col_name= spvar->name.str;
+
+ srp->set_out_param_info(out_param_info);
}
}
@@ -2418,7 +2428,7 @@ sp_head::show_create_routine(THD *thd, i
fields.push_back(new Item_empty_string("Database Collation",
MY_CS_NAME_SIZE));
- if (protocol->send_fields(&fields,
+ if (protocol->send_result_set_metadata(&fields,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
DBUG_RETURN(TRUE);
@@ -2603,7 +2613,7 @@ sp_head::show_routine_code(THD *thd)
// 1024 is for not to confuse old clients
field_list.push_back(new Item_empty_string("Instruction",
max(buffer.length(), 1024)));
- if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
DBUG_RETURN(1);
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2008-08-07 03:05:33 +0000
+++ b/sql/sql_acl.cc 2008-08-12 16:46:23 +0000
@@ -4626,7 +4626,7 @@ bool mysql_show_grants(THD *thd,LEX_USER
strxmov(buff,"Grants for ",lex_user->user.str,"@",
lex_user->host.str,NullS);
field_list.push_back(field);
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
{
pthread_mutex_unlock(&acl_cache->lock);
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-08-26 10:20:41 +0000
+++ b/sql/sql_base.cc 2008-09-04 18:30:34 +0000
@@ -21,6 +21,7 @@
#include "sp_head.h"
#include "sp.h"
#include "sql_trigger.h"
+#include "transaction.h"
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -1359,7 +1360,7 @@ void close_thread_tables(THD *thd,
if (!(thd->state_flags & Open_tables_state::BACKUPS_AVAIL))
{
thd->main_da.can_overwrite_status= TRUE;
- ha_autocommit_or_rollback(thd, thd->is_error());
+ thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->main_da.can_overwrite_status= FALSE;
/*
@@ -2612,7 +2613,7 @@ bool open_table(THD *thd, TABLE_LIST *ta
VIEW not really opened, only frm were read.
Set 1 as a flag here
*/
- table_list->view= (st_lex*)1;
+ table_list->view= (LEX*)1;
}
else
{
=== modified file 'sql/sql_cache.h'
--- a/sql/sql_cache.h 2008-07-17 19:55:18 +0000
+++ b/sql/sql_cache.h 2008-08-10 14:49:52 +0000
@@ -65,7 +65,7 @@ struct Query_cache_query;
struct Query_cache_result;
class Query_cache;
struct Query_cache_tls;
-struct st_lex;
+struct LEX;
/**
This class represents a node in the linked chain of queries
@@ -413,7 +413,7 @@ protected:
*/
TABLE_COUNTER_TYPE is_cacheable(THD *thd, size_t query_len,
const char *query,
- struct st_lex *lex, TABLE_LIST *tables_used,
+ LEX *lex, TABLE_LIST *tables_used,
uint8 *tables_type);
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
TABLE_LIST *tables_used,
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-09-04 13:46:04 +0000
+++ b/sql/sql_class.cc 2008-09-05 14:16:07 +0000
@@ -42,6 +42,7 @@
#include "sp_rcontext.h"
#include "sp_cache.h"
+#include "transaction.h"
/*
The following is used to initialise Table_ident with a internal
@@ -848,7 +849,8 @@ void THD::cleanup(void)
}
#endif
{
- ha_rollback(this);
+ transaction.xid_state.xa_state= XA_NOTR;
+ trans_rollback(this);
xid_cache_delete(&transaction.xid_state);
}
locked_tables_list.unlock_locked_tables(this);
@@ -1409,7 +1411,7 @@ int THD::send_explain_fields(select_resu
}
item->maybe_null= 1;
field_list.push_back(new Item_empty_string("Extra", 255, cs));
- return (result->send_fields(field_list,
+ return (result->send_result_set_metadata(field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
}
@@ -1555,10 +1557,10 @@ sql_exchange::sql_exchange(char *name, b
cs= NULL;
}
-bool select_send::send_fields(List<Item> &list, uint flags)
+bool select_send::send_result_set_metadata(List<Item> &list, uint flags)
{
bool res;
- if (!(res= thd->protocol->send_fields(&list, flags)))
+ if (!(res= thd->protocol->send_result_set_metadata(&list, flags)))
is_result_set_started= 1;
return res;
}
@@ -1601,10 +1603,13 @@ void select_send::cleanup()
bool select_send::send_data(List<Item> &items)
{
+ Protocol *protocol= thd->protocol;
+ DBUG_ENTER("select_send::send_data");
+
if (unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
- return 0;
+ DBUG_RETURN(FALSE);
}
/*
@@ -1614,31 +1619,18 @@ bool select_send::send_data(List<Item> &
*/
ha_release_temporary_latches(thd);
- List_iterator_fast<Item> li(items);
- Protocol *protocol= thd->protocol;
- char buff[MAX_FIELD_WIDTH];
- String buffer(buff, sizeof(buff), &my_charset_bin);
- DBUG_ENTER("select_send::send_data");
-
protocol->prepare_for_resend();
- Item *item;
- while ((item=li++))
- {
- if (item->send(protocol, &buffer) || thd->is_error())
- {
- protocol->free(); // Free used buffer
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- break;
- }
- }
- if (thd->is_error())
+ if (protocol->send_result_set_row(&items))
{
protocol->remove_last_row();
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
+
thd->sent_row_count++;
+
if (thd->vio_ok())
DBUG_RETURN(protocol->write());
+
DBUG_RETURN(0);
}
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-09-04 13:46:04 +0000
+++ b/sql/sql_class.h 2008-09-05 14:16:07 +0000
@@ -2458,7 +2458,7 @@ public:
*/
virtual uint field_count(List<Item> &fields) const
{ return fields.elements; }
- virtual bool send_fields(List<Item> &list, uint flags)=0;
+ virtual bool send_result_set_metadata(List<Item> &list, uint flags)=0;
virtual bool send_data(List<Item> &items)=0;
virtual bool initialize_tables (JOIN *join=0) { return 0; }
virtual void send_error(uint errcode,const char *err);
@@ -2497,7 +2497,7 @@ class select_result_interceptor: public
public:
select_result_interceptor() {} /* Remove gcc warning */
uint field_count(List<Item> &fields) const { return 0; }
- bool send_fields(List<Item> &fields, uint flag) { return FALSE; }
+ bool send_result_set_metadata(List<Item> &fields, uint flag) { return FALSE; }
};
@@ -2510,7 +2510,7 @@ class select_send :public select_result
bool is_result_set_started;
public:
select_send() :is_result_set_started(FALSE) {}
- bool send_fields(List<Item> &list, uint flags);
+ bool send_result_set_metadata(List<Item> &list, uint flags);
bool send_data(List<Item> &items);
bool send_eof();
virtual bool check_simple_select() const { return FALSE; }
=== modified file 'sql/sql_cursor.cc'
--- a/sql/sql_cursor.cc 2008-08-20 10:29:58 +0000
+++ b/sql/sql_cursor.cc 2008-09-04 18:30:34 +0000
@@ -88,7 +88,7 @@ class Materialized_cursor: public Server
public:
Materialized_cursor(select_result *result, TABLE *table);
- int fill_item_list(THD *thd, List<Item> &send_fields);
+ int fill_item_list(THD *thd, List<Item> &send_result_set_metadata);
virtual bool is_open() const { return table != 0; }
virtual int open(JOIN *join __attribute__((unused)));
virtual void fetch(ulong num_rows);
@@ -113,7 +113,7 @@ public:
Materialized_cursor *materialized_cursor;
Select_materialize(select_result *result_arg)
:result(result_arg), materialized_cursor(0) {}
- virtual bool send_fields(List<Item> &list, uint flags);
+ virtual bool send_result_set_metadata(List<Item> &list, uint flags);
};
@@ -362,12 +362,12 @@ Sensitive_cursor::open(JOIN *join_arg)
join->change_result(result);
/*
Send fields description to the client; server_status is sent
- in 'EOF' packet, which follows send_fields().
- We don't simply use SEND_EOF flag of send_fields because we also
+ in 'EOF' packet, which follows send_result_set_metadata().
+ We don't simply use SEND_EOF flag of send_result_set_metadata because we also
want to flush the network buffer, which is done only in a standalone
send_eof().
*/
- result->send_fields(*join->fields, Protocol::SEND_NUM_ROWS);
+ result->send_result_set_metadata(*join->fields, Protocol::SEND_NUM_ROWS);
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
result->send_eof();
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
@@ -551,14 +551,14 @@ Materialized_cursor::Materialized_cursor
Preserve the original metadata that would be sent to the client.
@param thd Thread identifier.
- @param send_fields List of fields that would be sent.
+ @param send_result_set_metadata List of fields that would be sent.
*/
-int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_fields)
+int Materialized_cursor::fill_item_list(THD *thd, List<Item> &send_result_set_metadata)
{
Query_arena backup_arena;
int rc;
- List_iterator_fast<Item> it_org(send_fields);
+ List_iterator_fast<Item> it_org(send_result_set_metadata);
List_iterator_fast<Item> it_dst(item_list);
Item *item_org;
Item *item_dst;
@@ -568,7 +568,7 @@ int Materialized_cursor::fill_item_list(
if ((rc= table->fill_item_list(&item_list)))
goto end;
- DBUG_ASSERT(send_fields.elements == item_list.elements);
+ DBUG_ASSERT(send_result_set_metadata.elements == item_list.elements);
/*
Unless we preserve the original metadata, it will be lost,
@@ -607,17 +607,17 @@ int Materialized_cursor::open(JOIN *join
{
/*
Now send the result set metadata to the client. We need to
- do it here, as in Select_materialize::send_fields the items
- for column types are not yet created (send_fields requires
+ do it here, as in Select_materialize::send_result_set_metadata the items
+ for column types are not yet created (send_result_set_metadata requires
a list of items). The new types may differ from the original
ones sent at prepare if some of them were altered by MySQL
HEAP tables mechanism -- used when create_tmp_field_from_item
may alter the original column type.
- We can't simply supply SEND_EOF flag to send_fields, because
- send_fields doesn't flush the network buffer.
+ We can't simply supply SEND_EOF flag to send_result_set_metadata, because
+ send_result_set_metadata doesn't flush the network buffer.
*/
- rc= result->send_fields(item_list, Protocol::SEND_NUM_ROWS);
+ rc= result->send_result_set_metadata(item_list, Protocol::SEND_NUM_ROWS);
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
result->send_eof();
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
@@ -700,7 +700,7 @@ Materialized_cursor::~Materialized_curso
Select_materialize
****************************************************************************/
-bool Select_materialize::send_fields(List<Item> &list, uint flags)
+bool Select_materialize::send_result_set_metadata(List<Item> &list, uint flags)
{
DBUG_ASSERT(table == 0);
if (create_result_table(unit->thd, unit->get_unit_column_types(),
=== modified file 'sql/sql_do.cc'
--- a/sql/sql_do.cc 2008-02-19 12:45:21 +0000
+++ b/sql/sql_do.cc 2008-08-08 01:33:43 +0000
@@ -17,6 +17,7 @@
/* Execute DO statement */
#include "mysql_priv.h"
+#include "transaction.h"
bool mysql_do(THD *thd, List<Item> &values)
{
@@ -36,7 +37,7 @@ bool mysql_do(THD *thd, List<Item> &valu
will clear the error and the rollback in the end of
dispatch_command() won't work.
*/
- ha_autocommit_or_rollback(thd, thd->is_error());
+ trans_rollback_stmt(thd);
thd->clear_error(); // DO always is OK
}
my_ok(thd);
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2008-07-29 22:03:57 +0000
+++ b/sql/sql_error.cc 2008-08-12 16:46:23 +0000
@@ -216,7 +216,7 @@ bool mysqld_show_warnings(THD *thd, ulon
field_list.push_back(new Item_return_int("Code",4, MYSQL_TYPE_LONG));
field_list.push_back(new Item_empty_string("Message",MYSQL_ERRMSG_SIZE));
- if (thd->protocol->send_fields(&field_list,
+ if (thd->protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc 2008-06-20 13:11:20 +0000
+++ b/sql/sql_handler.cc 2008-08-07 17:52:43 +0000
@@ -539,7 +539,7 @@ retry:
tables->db, tables->alias, &it, 0))
goto err;
- protocol->send_fields(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
+ protocol->send_result_set_metadata(&list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
/*
In ::external_lock InnoDB resets the fields which tell it that
@@ -661,18 +661,11 @@ retry:
continue;
if (num_rows >= offset_limit_cnt)
{
- Item *item;
protocol->prepare_for_resend();
- it.rewind();
- while ((item=it++))
- {
- if (item->send(thd->protocol, &buffer))
- {
- protocol->free(); // Free used
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
- goto err;
- }
- }
+
+ if (protocol->send_result_set_row(&list))
+ goto err;
+
protocol->write();
}
num_rows++;
=== modified file 'sql/sql_help.cc'
--- a/sql/sql_help.cc 2008-07-17 18:26:55 +0000
+++ b/sql/sql_help.cc 2008-08-07 17:52:43 +0000
@@ -431,7 +431,7 @@ int send_answer_1(Protocol *protocol, St
field_list.push_back(new Item_empty_string("description",1000));
field_list.push_back(new Item_empty_string("example",1000));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(1);
@@ -463,7 +463,7 @@ int send_answer_1(Protocol *protocol, St
+- -+
RETURN VALUES
- result of protocol->send_fields
+ result of protocol->send_result_set_metadata
*/
int send_header_2(Protocol *protocol, bool for_category)
@@ -474,7 +474,7 @@ int send_header_2(Protocol *protocol, bo
field_list.push_back(new Item_empty_string("source_category_name",64));
field_list.push_back(new Item_empty_string("name",64));
field_list.push_back(new Item_empty_string("is_it_category",1));
- DBUG_RETURN(protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ DBUG_RETURN(protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF));
}
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2008-09-11 18:36:05 +0000
+++ b/sql/sql_insert.cc 2008-09-16 17:58:49 +0000
@@ -62,6 +62,7 @@
#include "slave.h"
#include "rpl_mi.h"
#include "sql_audit.h"
+#include "transaction.h"
#ifndef EMBEDDED_LIBRARY
static bool delayed_get_table(THD *thd, TABLE_LIST *table_list);
@@ -2504,7 +2505,7 @@ pthread_handler_t handle_delayed_insert(
*/
di->table->file->ha_release_auto_increment();
mysql_unlock_tables(thd, lock);
- ha_autocommit_or_rollback(thd, 0);
+ trans_commit_stmt(thd);
di->group_count=0;
mysql_audit_release(thd);
pthread_mutex_lock(&di->mutex);
@@ -2525,7 +2526,7 @@ err:
first call to ha_*_row() instead. Remove code that are used to
cover for the case outlined above.
*/
- ha_autocommit_or_rollback(thd, 1);
+ trans_rollback_stmt(thd);
#ifndef __WIN__
end:
@@ -3765,8 +3766,8 @@ bool select_create::send_eof()
*/
if (!table->s->tmp_table)
{
- ha_autocommit_or_rollback(thd, 0);
- end_active_trans(thd);
+ trans_commit_stmt(thd);
+ trans_commit_implicit(thd);
}
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2008-07-15 16:29:51 +0000
+++ b/sql/sql_lex.cc 2008-08-10 14:49:52 +0000
@@ -2110,7 +2110,7 @@ void st_select_lex::print_limit(THD *thd
to implement the clean up.
*/
-void st_lex::cleanup_lex_after_parse_error(THD *thd)
+void LEX::cleanup_lex_after_parse_error(THD *thd)
{
/*
Delete sphead for the side effect of restoring of the original
@@ -2200,7 +2200,7 @@ void Query_tables_list::destroy_query_ta
Initialize LEX object.
SYNOPSIS
- st_lex::st_lex()
+ LEX::LEX()
NOTE
LEX object initialized with this constructor can be used as part of
@@ -2210,7 +2210,7 @@ void Query_tables_list::destroy_query_ta
for this.
*/
-st_lex::st_lex()
+LEX::LEX()
:result(0),
sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0)
{
@@ -2227,7 +2227,7 @@ st_lex::st_lex()
Check whether the merging algorithm can be used on this VIEW
SYNOPSIS
- st_lex::can_be_merged()
+ LEX::can_be_merged()
DESCRIPTION
We can apply merge algorithm if it is single SELECT view with
@@ -2241,7 +2241,7 @@ st_lex::st_lex()
TRUE - merge algorithm can be used
*/
-bool st_lex::can_be_merged()
+bool LEX::can_be_merged()
{
// TODO: do not forget implement case when select_lex.table_list.elements==0
@@ -2278,19 +2278,19 @@ bool st_lex::can_be_merged()
check if command can use VIEW with MERGE algorithm (for top VIEWs)
SYNOPSIS
- st_lex::can_use_merged()
+ LEX::can_use_merged()
DESCRIPTION
Only listed here commands can use merge algorithm in top level
SELECT_LEX (for subqueries will be used merge algorithm if
- st_lex::can_not_use_merged() is not TRUE).
+ LEX::can_not_use_merged() is not TRUE).
RETURN
FALSE - command can't use merged VIEWs
TRUE - VIEWs with MERGE algorithms can be used
*/
-bool st_lex::can_use_merged()
+bool LEX::can_use_merged()
{
switch (sql_command)
{
@@ -2315,18 +2315,18 @@ bool st_lex::can_use_merged()
Check if command can't use merged views in any part of command
SYNOPSIS
- st_lex::can_not_use_merged()
+ LEX::can_not_use_merged()
DESCRIPTION
Temporary table algorithm will be used on all SELECT levels for queries
- listed here (see also st_lex::can_use_merged()).
+ listed here (see also LEX::can_use_merged()).
RETURN
FALSE - command can't use merged VIEWs
TRUE - VIEWs with MERGE algorithms can be used
*/
-bool st_lex::can_not_use_merged()
+bool LEX::can_not_use_merged()
{
switch (sql_command)
{
@@ -2355,7 +2355,7 @@ bool st_lex::can_not_use_merged()
FALSE no, we need data
*/
-bool st_lex::only_view_structure()
+bool LEX::only_view_structure()
{
switch (sql_command) {
case SQLCOM_SHOW_CREATE:
@@ -2384,7 +2384,7 @@ bool st_lex::only_view_structure()
*/
-bool st_lex::need_correct_ident()
+bool LEX::need_correct_ident()
{
switch(sql_command)
{
@@ -2414,7 +2414,7 @@ bool st_lex::need_correct_ident()
VIEW_CHECK_CASCADED CHECK OPTION CASCADED
*/
-uint8 st_lex::get_effective_with_check(TABLE_LIST *view)
+uint8 LEX::get_effective_with_check(TABLE_LIST *view)
{
if (view->select_lex->master_unit() == &unit &&
which_check_option_applicable())
@@ -2443,7 +2443,7 @@ uint8 st_lex::get_effective_with_check(T
*/
bool
-st_lex::copy_db_to(char **p_db, size_t *p_db_length) const
+LEX::copy_db_to(char **p_db, size_t *p_db_length) const
{
if (sphead)
{
@@ -2515,7 +2515,7 @@ void st_select_lex_unit::set_limit(st_se
clause.
*/
-void st_lex::set_trg_event_type_for_tables()
+void LEX::set_trg_event_type_for_tables()
{
uint8 new_trg_event_map= 0;
@@ -2658,7 +2658,7 @@ void st_lex::set_trg_event_type_for_tabl
In this case link_to_local is set.
*/
-TABLE_LIST *st_lex::unlink_first_table(bool *link_to_local)
+TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
{
TABLE_LIST *first;
if ((first= query_tables))
@@ -2698,7 +2698,7 @@ TABLE_LIST *st_lex::unlink_first_table(b
table list
SYNOPSYS
- st_lex::first_lists_tables_same()
+ LEX::first_lists_tables_same()
NOTES
In many cases (for example, usual INSERT/DELETE/...) the first table of
@@ -2709,7 +2709,7 @@ TABLE_LIST *st_lex::unlink_first_table(b
the global list first.
*/
-void st_lex::first_lists_tables_same()
+void LEX::first_lists_tables_same()
{
TABLE_LIST *first_table= (TABLE_LIST*) select_lex.table_list.first;
if (query_tables != first_table && first_table != 0)
@@ -2745,7 +2745,7 @@ void st_lex::first_lists_tables_same()
global list
*/
-void st_lex::link_first_table_back(TABLE_LIST *first,
+void LEX::link_first_table_back(TABLE_LIST *first,
bool link_to_local)
{
if (first)
@@ -2772,7 +2772,7 @@ void st_lex::link_first_table_back(TABLE
cleanup lex for case when we open table by table for processing
SYNOPSIS
- st_lex::cleanup_after_one_table_open()
+ LEX::cleanup_after_one_table_open()
NOTE
This method is mostly responsible for cleaning up of selects lists and
@@ -2780,7 +2780,7 @@ void st_lex::link_first_table_back(TABLE
to call Query_tables_list::reset_query_tables_list(FALSE).
*/
-void st_lex::cleanup_after_one_table_open()
+void LEX::cleanup_after_one_table_open()
{
/*
thd->lex->derived_tables & additional units may be set if we open
@@ -2815,7 +2815,7 @@ void st_lex::cleanup_after_one_table_ope
backup Pointer to Query_tables_list instance to be used for backup
*/
-void st_lex::reset_n_backup_query_tables_list(Query_tables_list *backup)
+void LEX::reset_n_backup_query_tables_list(Query_tables_list *backup)
{
backup->set_query_tables_list(this);
/*
@@ -2834,7 +2834,7 @@ void st_lex::reset_n_backup_query_tables
backup Pointer to Query_tables_list instance used for backup
*/
-void st_lex::restore_backup_query_tables_list(Query_tables_list *backup)
+void LEX::restore_backup_query_tables_list(Query_tables_list *backup)
{
this->destroy_query_tables_list();
this->set_query_tables_list(backup);
@@ -2845,14 +2845,14 @@ void st_lex::restore_backup_query_tables
Checks for usage of routines and/or tables in a parsed statement
SYNOPSIS
- st_lex:table_or_sp_used()
+ LEX:table_or_sp_used()
RETURN
FALSE No routines and tables used
TRUE Either or both routines and tables are used.
*/
-bool st_lex::table_or_sp_used()
+bool LEX::table_or_sp_used()
{
DBUG_ENTER("table_or_sp_used");
@@ -3013,7 +3013,7 @@ bool st_select_lex::add_index_hint (THD
@retval FALSE No, not a management partition command
*/
-bool st_lex::is_partition_management() const
+bool LEX::is_partition_management() const
{
return (sql_command == SQLCOM_ALTER_TABLE &&
(alter_info.flags == ALTER_ADD_PARTITION ||
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2008-08-20 10:29:58 +0000
+++ b/sql/sql_lex.h 2008-09-04 18:30:34 +0000
@@ -390,7 +390,7 @@ public:
Base class for st_select_lex (SELECT_LEX) &
st_select_lex_unit (SELECT_LEX_UNIT)
*/
-struct st_lex;
+struct LEX;
class st_select_lex;
class st_select_lex_unit;
class st_select_lex_node {
@@ -460,7 +460,7 @@ public:
virtual void set_lock_for_tables(thr_lock_type lock_type) {}
friend class st_select_lex_unit;
- friend bool mysql_new_select(struct st_lex *lex, bool move_down);
+ friend bool mysql_new_select(LEX *lex, bool move_down);
friend bool mysql_make_view(THD *thd, File_parser *parser,
TABLE_LIST *table, uint flags);
private:
@@ -585,7 +585,7 @@ public:
/* Saved values of the WHERE and HAVING clauses*/
Item::cond_result cond_value, having_value;
/* point on lex in which it was created, used in view subquery detection */
- st_lex *parent_lex;
+ LEX *parent_lex;
enum olap_type olap;
/* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */
SQL_LIST table_list;
@@ -953,7 +953,7 @@ extern const LEX_STRING null_lex_str;
stored functions/triggers to this list in order to pre-open and lock
them.
- Also used by st_lex::reset_n_backup/restore_backup_query_tables_list()
+ Also used by LEX::reset_n_backup/restore_backup_query_tables_list()
methods to save and restore this information.
*/
@@ -1513,7 +1513,7 @@ public:
/* The state of the lex parsing. This is saved in the THD struct */
-typedef struct st_lex : public Query_tables_list
+struct LEX: public Query_tables_list
{
SELECT_LEX_UNIT unit; /* most upper unit */
SELECT_LEX select_lex; /* first SELECT_LEX */
@@ -1757,9 +1757,9 @@ typedef struct st_lex : public Query_tab
bool escape_used;
bool is_lex_started; /* If lex_start() did run. For debugging. */
- st_lex();
+ LEX();
- virtual ~st_lex()
+ virtual ~LEX()
{
destroy_query_tables_list();
plugin_unlock_list(NULL, (plugin_ref *)plugins.buffer, plugins.elements);
@@ -1801,7 +1801,7 @@ typedef struct st_lex : public Query_tab
Is this update command where 'WHITH CHECK OPTION' clause is important
SYNOPSIS
- st_lex::which_check_option_applicable()
+ LEX::which_check_option_applicable()
RETURN
TRUE have to take 'WHITH CHECK OPTION' clause into account
@@ -1873,7 +1873,7 @@ typedef struct st_lex : public Query_tab
}
return FALSE;
}
-} LEX;
+};
/**
@@ -1928,7 +1928,7 @@ public:
};
-struct st_lex_local: public st_lex
+struct st_lex_local: public LEX
{
static void *operator new(size_t size) throw()
{
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-09-04 13:46:04 +0000
+++ b/sql/sql_parse.cc 2008-09-05 14:16:07 +0000
@@ -29,6 +29,7 @@
#include "sql_trigger.h"
#include <ddl_blocker.h>
#include "sql_audit.h"
+#include "transaction.h"
#ifdef BACKUP_TEST
#include "backup/backup_test.h"
@@ -97,65 +98,6 @@ const char *xa_state_names[]={
extern DDL_blocker_class *DDL_blocker;
-bool end_active_trans(THD *thd)
-{
- int error=0;
- DBUG_ENTER("end_active_trans");
- if (unlikely(thd->in_sub_stmt))
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- DBUG_RETURN(1);
- }
- if (thd->transaction.xid_state.xa_state != XA_NOTR)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- DBUG_RETURN(1);
- }
- if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
- OPTION_TABLE_LOCK))
- {
- DBUG_PRINT("info",("options: 0x%llx", thd->options));
- /* Safety if one did "drop table" on locked tables */
- if (!thd->locked_tables_mode)
- thd->options&= ~OPTION_TABLE_LOCK;
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- if (ha_commit(thd))
- error=1;
-#ifdef WITH_MARIA_STORAGE_ENGINE
- ha_maria::implicit_commit(thd, TRUE);
-#endif
- }
- thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.modified_non_trans_table= FALSE;
- DBUG_RETURN(error);
-}
-
-
-bool begin_trans(THD *thd)
-{
- int error=0;
- if (unlikely(thd->in_sub_stmt))
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- return 1;
- }
-
- thd->locked_tables_list.unlock_locked_tables(thd);
-
- if (end_active_trans(thd))
- error= -1;
- else
- {
- LEX *lex= thd->lex;
- thd->options|= OPTION_BEGIN;
- thd->server_status|= SERVER_STATUS_IN_TRANS;
- if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
- error= ha_start_consistent_snapshot(thd);
- }
- return error;
-}
-
#ifdef HAVE_REPLICATION
/**
Returns true if all tables should be ignored.
@@ -216,9 +158,9 @@ static bool opt_implicit_commit(THD *thd
if (!skip)
{
/* Commit or rollback the statement transaction. */
- ha_autocommit_or_rollback(thd, thd->is_error());
+ thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
/* Commit the normal transaction if one is active. */
- res= end_active_trans(thd);
+ res= trans_commit_implicit(thd);
}
DBUG_RETURN(res);
@@ -643,81 +585,6 @@ void cleanup_items(Item *item)
DBUG_VOID_RETURN;
}
-/**
- Ends the current transaction and (maybe) begin the next.
-
- @param thd Current thread
- @param completion Completion type
-
- @retval
- 0 OK
-*/
-
-int end_trans(THD *thd, enum enum_mysql_completiontype completion)
-{
- bool do_release= 0;
- int res= 0;
- DBUG_ENTER("end_trans");
-
- if (unlikely(thd->in_sub_stmt))
- {
- my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
- DBUG_RETURN(1);
- }
- if (thd->transaction.xid_state.xa_state != XA_NOTR)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- DBUG_RETURN(1);
- }
- thd->lex->start_transaction_opt= 0; /* for begin_trans() */
- switch (completion) {
- case COMMIT:
- /*
- We don't use end_active_trans() here to ensure that this works
- even if there is a problem with the OPTION_AUTO_COMMIT flag
- (Which of course should never happen...)
- */
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- res= ha_commit(thd);
- thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.modified_non_trans_table= FALSE;
- break;
- case COMMIT_RELEASE:
- do_release= 1; /* fall through */
- case COMMIT_AND_CHAIN:
- res= end_active_trans(thd);
- if (!res && completion == COMMIT_AND_CHAIN)
- res= begin_trans(thd);
- break;
- case ROLLBACK_RELEASE:
- do_release= 1; /* fall through */
- case ROLLBACK:
- case ROLLBACK_AND_CHAIN:
- {
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- if (ha_rollback(thd))
- res= -1;
- thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.modified_non_trans_table= FALSE;
- if (!res && (completion == ROLLBACK_AND_CHAIN))
- res= begin_trans(thd);
- break;
- }
- default:
- res= -1;
- my_error(ER_UNKNOWN_COM_ERROR, MYF(0));
- DBUG_RETURN(-1);
- }
-
- if (res < 0)
- my_error(thd->killed_errno(), MYF(0));
- else if ((res == 0) && do_release)
- thd->killed= THD::KILL_CONNECTION;
-
- DBUG_RETURN(res);
-}
-
#ifndef EMBEDDED_LIBRARY
/**
@@ -1340,14 +1207,14 @@ bool dispatch_command(enum enum_server_c
bool not_used;
status_var_increment(thd->status_var.com_stat[SQLCOM_FLUSH]);
ulong options= (ulong) (uchar) packet[0];
- if (end_active_trans(thd))
+ if (trans_commit_implicit(thd))
break;
if (check_global_access(thd,RELOAD_ACL))
break;
general_log_print(thd, command, NullS);
if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, ¬_used))
break;
- if (end_active_trans(thd))
+ if (trans_commit_implicit(thd))
break;
my_ok(thd);
break;
@@ -1497,7 +1364,7 @@ bool dispatch_command(enum enum_server_c
/* If commit fails, we should be able to reset the OK status. */
thd->main_da.can_overwrite_status= TRUE;
- ha_autocommit_or_rollback(thd, thd->is_error());
+ thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
thd->main_da.can_overwrite_status= FALSE;
thd->transaction.stmt.reset();
@@ -3432,7 +3299,7 @@ ddl_blocker_err:
thd->locked_tables_list.unlock_locked_tables(thd);
if (thd->options & OPTION_TABLE_LOCK)
{
- end_active_trans(thd);
+ trans_commit_implicit(thd);
thd->options&= ~(OPTION_TABLE_LOCK);
}
if (thd->global_read_lock)
@@ -3486,7 +3353,7 @@ ddl_blocker_err:
goto error;
thd->locked_tables_list.unlock_locked_tables(thd);
/* we must end the trasaction first, regardless of anything */
- if (end_active_trans(thd))
+ if (trans_commit_implicit(thd))
goto error;
alloc_mdl_locks(all_tables, thd->locked_tables_list.locked_tables_root());
@@ -3509,8 +3376,8 @@ ddl_blocker_err:
can free its locks if LOCK TABLES locked some tables before finding
that it can't lock a table in its list
*/
- ha_autocommit_or_rollback(thd, 1);
- end_active_trans(thd);
+ trans_rollback_stmt(thd);
+ trans_commit_implicit(thd);
thd->options&= ~(OPTION_TABLE_LOCK);
}
else
@@ -4003,129 +3870,52 @@ ddl_blocker_err:
break;
case SQLCOM_BEGIN:
- if (thd->transaction.xid_state.xa_state != XA_NOTR)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- break;
- }
DEBUG_SYNC(thd, "before_begin_trans");
- if (begin_trans(thd))
+ if (trans_begin(thd, lex->start_transaction_opt))
goto error;
my_ok(thd);
break;
case SQLCOM_COMMIT:
DBUG_ASSERT(thd->lock == NULL ||
thd->locked_tables_mode == LTM_LOCK_TABLES);
- if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE :
- lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
+ if (trans_commit(thd))
+ goto error;
+ /* Begin transaction with the same isolation level. */
+ if (lex->tx_chain && trans_begin(thd))
goto error;
+ /* Disconnect the current client connection. */
+ if (lex->tx_release)
+ thd->killed= THD::KILL_CONNECTION;
DEBUG_SYNC(thd, "after_commit");
my_ok(thd);
break;
case SQLCOM_ROLLBACK:
DBUG_ASSERT(thd->lock == NULL ||
thd->locked_tables_mode == LTM_LOCK_TABLES);
- if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE :
- lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
+ if (trans_rollback(thd))
+ goto error;
+ /* Begin transaction with the same isolation level. */
+ if (lex->tx_chain && trans_begin(thd))
goto error;
+ /* Disconnect the current client connection. */
+ if (lex->tx_release)
+ thd->killed= THD::KILL_CONNECTION;
my_ok(thd);
break;
case SQLCOM_RELEASE_SAVEPOINT:
- {
- SAVEPOINT *sv;
- for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
- {
- if (my_strnncoll(system_charset_info,
- (uchar *)lex->ident.str, lex->ident.length,
- (uchar *)sv->name, sv->length) == 0)
- break;
- }
- if (sv)
- {
- if (ha_release_savepoint(thd, sv))
- res= TRUE; // cannot happen
- else
- my_ok(thd);
- thd->transaction.savepoints=sv->prev;
- }
- else
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
+ if (trans_release_savepoint(thd, lex->ident))
+ goto error;
+ my_ok(thd);
break;
- }
case SQLCOM_ROLLBACK_TO_SAVEPOINT:
- {
- SAVEPOINT *sv;
- for (sv=thd->transaction.savepoints; sv; sv=sv->prev)
- {
- if (my_strnncoll(system_charset_info,
- (uchar *)lex->ident.str, lex->ident.length,
- (uchar *)sv->name, sv->length) == 0)
- break;
- }
- if (sv)
- {
- if (ha_rollback_to_savepoint(thd, sv))
- res= TRUE; // cannot happen
- else
- {
- if (((thd->options & OPTION_KEEP_LOG) ||
- thd->transaction.all.modified_non_trans_table) &&
- !thd->slave_thread)
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_WARNING_NOT_COMPLETE_ROLLBACK,
- ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
- my_ok(thd);
- }
- thd->transaction.savepoints=sv;
- }
- else
- my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
+ if (trans_rollback_to_savepoint(thd, lex->ident))
+ goto error;
+ my_ok(thd);
break;
- }
case SQLCOM_SAVEPOINT:
- if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
- thd->in_sub_stmt) || !opt_using_transactions)
- my_ok(thd);
- else
- {
- SAVEPOINT **sv, *newsv;
- for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev)
- {
- if (my_strnncoll(system_charset_info,
- (uchar *)lex->ident.str, lex->ident.length,
- (uchar *)(*sv)->name, (*sv)->length) == 0)
- break;
- }
- if (*sv) /* old savepoint of the same name exists */
- {
- newsv=*sv;
- ha_release_savepoint(thd, *sv); // it cannot fail
- *sv=(*sv)->prev;
- }
- else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
- savepoint_alloc_size)) == 0)
- {
- my_error(ER_OUT_OF_RESOURCES, MYF(0));
- break;
- }
- newsv->name=strmake_root(&thd->transaction.mem_root,
- lex->ident.str, lex->ident.length);
- newsv->length=lex->ident.length;
- /*
- if we'll get an error here, don't add new savepoint to the list.
- we'll lose a little bit of memory in transaction mem_root, but it'll
- be free'd when transaction ends anyway
- */
- if (ha_savepoint(thd, newsv))
- res= TRUE;
- else
- {
- newsv->prev=thd->transaction.savepoints;
- thd->transaction.savepoints=newsv;
- my_ok(thd);
- }
- }
+ if (trans_savepoint(thd, lex->ident))
+ goto error;
+ my_ok(thd);
break;
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
@@ -4467,7 +4257,7 @@ create_sp_error:
lex->sql_command == SQLCOM_DROP_PROCEDURE, 0))
goto error;
- if (end_active_trans(thd))
+ if (trans_commit_implicit(thd))
goto error;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (sp_automatic_privileges && !opt_noacl &&
@@ -4597,173 +4387,29 @@ create_sp_error:
break;
}
case SQLCOM_XA_START:
- if (thd->transaction.xid_state.xa_state == XA_IDLE &&
- thd->lex->xa_opt == XA_RESUME)
- {
- if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
- {
- my_error(ER_XAER_NOTA, MYF(0));
- break;
- }
- thd->transaction.xid_state.xa_state=XA_ACTIVE;
- my_ok(thd);
- break;
- }
- if (thd->lex->xa_opt != XA_NONE)
- { // JOIN is not supported yet. TODO
- my_error(ER_XAER_INVAL, MYF(0));
- break;
- }
- if (thd->transaction.xid_state.xa_state != XA_NOTR)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- break;
- }
- if (thd->locked_tables_mode || thd->active_transaction())
- {
- my_error(ER_XAER_OUTSIDE, MYF(0));
- break;
- }
- if (xid_cache_search(thd->lex->xid))
- {
- my_error(ER_XAER_DUPID, MYF(0));
- break;
- }
- DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
- thd->transaction.xid_state.xa_state=XA_ACTIVE;
- thd->transaction.xid_state.xid.set(thd->lex->xid);
- xid_cache_insert(&thd->transaction.xid_state);
- thd->transaction.all.modified_non_trans_table= FALSE;
- thd->options= ((thd->options & ~(OPTION_KEEP_LOG)) | OPTION_BEGIN);
- thd->server_status|= SERVER_STATUS_IN_TRANS;
+ if (trans_xa_start(thd))
+ goto error;
my_ok(thd);
break;
case SQLCOM_XA_END:
- /* fake it */
- if (thd->lex->xa_opt != XA_NONE)
- { // SUSPEND and FOR MIGRATE are not supported yet. TODO
- my_error(ER_XAER_INVAL, MYF(0));
- break;
- }
- if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- break;
- }
- if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
- {
- my_error(ER_XAER_NOTA, MYF(0));
- break;
- }
- thd->transaction.xid_state.xa_state=XA_IDLE;
+ if (trans_xa_end(thd))
+ goto error;
my_ok(thd);
break;
case SQLCOM_XA_PREPARE:
- if (thd->transaction.xid_state.xa_state != XA_IDLE)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- break;
- }
- if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
- {
- my_error(ER_XAER_NOTA, MYF(0));
- break;
- }
- if (ha_prepare(thd))
- {
- my_error(ER_XA_RBROLLBACK, MYF(0));
- xid_cache_delete(&thd->transaction.xid_state);
- thd->transaction.xid_state.xa_state=XA_NOTR;
- break;
- }
- thd->transaction.xid_state.xa_state=XA_PREPARED;
+ if (trans_xa_prepare(thd))
+ goto error;
my_ok(thd);
break;
case SQLCOM_XA_COMMIT:
- if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
- {
- XID_STATE *xs=xid_cache_search(thd->lex->xid);
- if (!xs || xs->in_thd)
- my_error(ER_XAER_NOTA, MYF(0));
- else
- {
- ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
- xid_cache_delete(xs);
- my_ok(thd);
- }
- break;
- }
- if (thd->transaction.xid_state.xa_state == XA_IDLE &&
- thd->lex->xa_opt == XA_ONE_PHASE)
- {
- int r;
- if ((r= ha_commit(thd)))
- my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
- else
- my_ok(thd);
- }
- else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
- thd->lex->xa_opt == XA_NONE)
- {
- if (wait_if_global_read_lock(thd, 0, 0))
- {
- ha_rollback(thd);
- my_error(ER_XAER_RMERR, MYF(0));
- }
- else
- {
- if (ha_commit_one_phase(thd, 1))
- my_error(ER_XAER_RMERR, MYF(0));
- else
- my_ok(thd);
- start_waiting_global_read_lock(thd);
- }
- }
- else
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- break;
- }
- thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.modified_non_trans_table= FALSE;
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- xid_cache_delete(&thd->transaction.xid_state);
- thd->transaction.xid_state.xa_state=XA_NOTR;
+ if (trans_xa_commit(thd))
+ goto error;
+ my_ok(thd);
break;
case SQLCOM_XA_ROLLBACK:
- if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
- {
- XID_STATE *xs=xid_cache_search(thd->lex->xid);
- if (!xs || xs->in_thd)
- my_error(ER_XAER_NOTA, MYF(0));
- else
- {
- ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
- xid_cache_delete(xs);
- my_ok(thd);
- }
- break;
- }
- if (thd->transaction.xid_state.xa_state != XA_IDLE &&
- thd->transaction.xid_state.xa_state != XA_PREPARED)
- {
- my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xid_state.xa_state]);
- break;
- }
- if (ha_rollback(thd))
- my_error(ER_XAER_RMERR, MYF(0));
- else
- my_ok(thd);
- thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
- thd->transaction.all.modified_non_trans_table= FALSE;
- thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- xid_cache_delete(&thd->transaction.xid_state);
- thd->transaction.xid_state.xa_state=XA_NOTR;
+ if (trans_xa_rollback(thd))
+ goto error;
+ my_ok(thd);
break;
case SQLCOM_XA_RECOVER:
res= mysql_xa_recover(thd);
=== modified file 'sql/sql_partition.cc'
--- a/sql/sql_partition.cc 2008-08-11 19:37:53 +0000
+++ b/sql/sql_partition.cc 2008-09-04 18:30:34 +0000
@@ -37,6 +37,7 @@
#include <errno.h>
#include <m_ctype.h>
#include "my_md5.h"
+#include "transaction.h"
#ifdef WITH_PARTITION_STORAGE_ENGINE
#include "ha_partition.h"
@@ -3966,8 +3967,8 @@ static int fast_end_partition(THD *thd,
if (!is_empty)
query_cache_invalidate3(thd, table_list, 0);
- error= ha_autocommit_or_rollback(thd, 0);
- if (end_active_trans(thd))
+ error= trans_commit_stmt(thd);
+ if (trans_commit_implicit(thd))
error= 1;
if (error)
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2008-07-15 16:29:51 +0000
+++ b/sql/sql_prepare.cc 2008-08-07 17:52:43 +0000
@@ -105,7 +105,7 @@ class Select_fetch_protocol_binary: publ
Protocol_binary protocol;
public:
Select_fetch_protocol_binary(THD *thd);
- virtual bool send_fields(List<Item> &list, uint flags);
+ virtual bool send_result_set_metadata(List<Item> &list, uint flags);
virtual bool send_data(List<Item> &items);
virtual bool send_eof();
#ifdef EMBEDDED_LIBRARY
@@ -258,7 +258,7 @@ static bool send_prep_stmt(Prepared_stat
error= my_net_write(net, buff, sizeof(buff));
if (stmt->param_count && ! error)
{
- error= thd->protocol_text.send_fields((List<Item> *)
+ error= thd->protocol_text.send_result_set_metadata((List<Item> *)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
@@ -1373,7 +1373,7 @@ static int mysql_test_select(Prepared_st
unit->prepare call above.
*/
if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
- lex->result->send_fields(fields, Protocol::SEND_EOF) ||
+ lex->result->send_result_set_metadata(fields, Protocol::SEND_EOF) ||
thd->protocol->flush())
goto error;
DBUG_RETURN(2);
@@ -2774,19 +2774,19 @@ Select_fetch_protocol_binary::Select_fet
:protocol(thd_arg)
{}
-bool Select_fetch_protocol_binary::send_fields(List<Item> &list, uint flags)
+bool Select_fetch_protocol_binary::send_result_set_metadata(List<Item> &list, uint flags)
{
bool rc;
Protocol *save_protocol= thd->protocol;
/*
- Protocol::send_fields caches the information about column types:
+ Protocol::send_result_set_metadata caches the information about column types:
this information is later used to send data. Therefore, the same
dedicated Protocol object must be used for all operations with
a cursor.
*/
thd->protocol= &protocol;
- rc= select_send::send_fields(list, flags);
+ rc= select_send::send_result_set_metadata(list, flags);
thd->protocol= save_protocol;
return rc;
@@ -3597,6 +3597,9 @@ bool Prepared_statement::execute(String
if (state == Query_arena::PREPARED)
state= Query_arena::EXECUTED;
+ if (this->lex->sql_command == SQLCOM_CALL)
+ protocol->send_out_parameters(&this->lex->param_list);
+
/*
Log COM_EXECUTE to the general log. Note, that in case of SQL
prepared statements this causes two records to be output:
=== modified file 'sql/sql_profile.cc'
--- a/sql/sql_profile.cc 2008-06-25 16:28:57 +0000
+++ b/sql/sql_profile.cc 2008-08-07 17:52:43 +0000
@@ -412,7 +412,7 @@ bool PROFILING::show_profiles()
MYSQL_TYPE_DOUBLE));
field_list.push_back(new Item_empty_string("Query", 40));
- if (thd->protocol->send_fields(&field_list,
+ if (thd->protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
=== modified file 'sql/sql_repl.cc'
--- a/sql/sql_repl.cc 2008-08-22 06:48:55 +0000
+++ b/sql/sql_repl.cc 2008-09-04 18:30:34 +0000
@@ -1448,7 +1448,7 @@ bool mysql_show_binlog_events(THD* thd)
DBUG_ENTER("mysql_show_binlog_events");
Log_event::init_show_field_list(&field_list);
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -1598,7 +1598,7 @@ bool show_binlog_info(THD* thd)
field_list.push_back(new Item_empty_string("Binlog_Do_DB",255));
field_list.push_back(new Item_empty_string("Binlog_Ignore_DB",255));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
@@ -1653,7 +1653,7 @@ bool show_binlogs(THD* thd)
field_list.push_back(new Item_empty_string("Log_name", 255));
field_list.push_back(new Item_return_int("File_size", 20,
MYSQL_TYPE_LONGLONG));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc 2008-08-28 11:17:29 +0000
+++ b/sql/sql_select.cc 2008-09-04 18:30:34 +0000
@@ -2289,7 +2289,7 @@ JOIN::exec()
(zero_result_cause?zero_result_cause:"No tables used"));
else
{
- result->send_fields(*columns_list,
+ result->send_result_set_metadata(*columns_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
/*
We have to test for 'conds' here as the WHERE may not be constant
@@ -2681,7 +2681,7 @@ JOIN::exec()
}
if (curr_join->group_list || curr_join->order)
{
- DBUG_PRINT("info",("Sorting for send_fields"));
+ DBUG_PRINT("info",("Sorting for send_result_set_metadata"));
thd_proc_info(thd, "Sorting result");
/* If we have already done the group, add HAVING to sorted table */
if (curr_join->tmp_having && ! curr_join->group_list &&
@@ -2821,7 +2821,7 @@ JOIN::exec()
{
thd_proc_info(thd, "Sending data");
DBUG_PRINT("info", ("%s", thd->proc_info));
- result->send_fields((procedure ? curr_join->procedure_fields_list :
+ result->send_result_set_metadata((procedure ? curr_join->procedure_fields_list :
*curr_fields_list),
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
error= do_select(curr_join, curr_fields_list, NULL, procedure);
@@ -9021,7 +9021,7 @@ return_zero_rows(JOIN *join, select_resu
if (having && having->val_int() == 0)
send_row=0;
}
- if (!(result->send_fields(fields,
+ if (!(result->send_result_set_metadata(fields,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)))
{
if (send_row)
@@ -11641,7 +11641,7 @@ void setup_tmp_table_column_bitmaps(TABL
Create a temp table according to a field list.
Given field pointers are changed to point at tmp_table for
- send_fields. The table object is self contained: it's
+ send_result_set_metadata. The table object is self contained: it's
allocated in its own memory root, as well as Field objects
created for table columns.
This function will replace Item_sum items in 'fields' list with
@@ -17832,7 +17832,7 @@ int test_if_item_cache_changed(List<Cach
Only FIELD_ITEM:s and FUNC_ITEM:s needs to be saved between groups.
Change old item_field to use a new field with points at saved fieldvalue
- This function is only called before use of send_fields.
+ This function is only called before use of send_result_set_metadata.
@param thd THD pointer
@param param temporary table parameters
@@ -18063,7 +18063,7 @@ bool JOIN::alloc_func_list()
Initialize 'sum_funcs' array with all Item_sum objects.
@param field_list All items
- @param send_fields Items in select list
+ @param send_result_set_metadata Items in select list
@param before_group_by Set to 1 if this is called before GROUP BY handling
@param recompute Set to TRUE if sum_funcs must be recomputed
@@ -18073,7 +18073,7 @@ bool JOIN::alloc_func_list()
1 error
*/
-bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
+bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_result_set_metadata,
bool before_group_by, bool recompute)
{
List_iterator_fast<Item> it(field_list);
@@ -18095,7 +18095,7 @@ bool JOIN::make_sum_func_list(List<Item>
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
{
rollup.state= ROLLUP::STATE_READY;
- if (rollup_make_fields(field_list, send_fields, &func))
+ if (rollup_make_fields(field_list, send_result_set_metadata, &func))
DBUG_RETURN(TRUE); // Should never happen
}
else if (rollup.state == ROLLUP::STATE_NONE)
=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h 2008-08-16 15:22:47 +0000
+++ b/sql/sql_select.h 2008-09-04 18:30:34 +0000
@@ -174,7 +174,6 @@ class SJ_TMP_TABLE;
typedef enum_nested_loop_state
(*Next_select_func)(JOIN *, struct st_join_table *, bool);
-typedef int (*Read_record_func)(struct st_join_table *tab);
Next_select_func setup_end_select_func(JOIN *join);
@@ -210,7 +209,7 @@ typedef struct st_join_table {
*/
uint packed_info;
- Read_record_func read_first_record;
+ READ_RECORD::Setup_func read_first_record;
Next_select_func next_select;
READ_RECORD read_record;
/*
@@ -218,8 +217,8 @@ typedef struct st_join_table {
if it is executed by an alternative full table scan when the left operand of
the subquery predicate is evaluated to NULL.
*/
- Read_record_func save_read_first_record;/* to save read_first_record */
- int (*save_read_record) (READ_RECORD *);/* to save read_record.read_record */
+ READ_RECORD::Setup_func save_read_first_record;/* to save read_first_record */
+ READ_RECORD::Read_func save_read_record;/* to save read_record.read_record */
double worst_seeks;
key_map const_keys; /**< Keys with constant part */
key_map checked_keys; /**< Keys checked in find_best */
@@ -648,7 +647,7 @@ public:
bool alloc_func_list();
bool flatten_subqueries();
bool setup_subquery_materialization();
- bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
+ bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_result_set_metadata,
bool before_group_by, bool recompute= FALSE);
inline void set_items_ref_array(Item **ptr)
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2008-09-11 18:36:05 +0000
+++ b/sql/sql_show.cc 2008-09-16 17:58:49 +0000
@@ -216,7 +216,7 @@ bool mysqld_show_authors(THD *thd)
field_list.push_back(new Item_empty_string("Location",40));
field_list.push_back(new Item_empty_string("Comment",80));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -250,7 +250,7 @@ bool mysqld_show_contributors(THD *thd)
field_list.push_back(new Item_empty_string("Location",40));
field_list.push_back(new Item_empty_string("Comment",80));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -326,7 +326,7 @@ bool mysqld_show_privileges(THD *thd)
field_list.push_back(new Item_empty_string("Context",15));
field_list.push_back(new Item_empty_string("Comment",NAME_CHAR_LEN));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -563,7 +563,7 @@ mysqld_show_create(THD *thd, TABLE_LIST
max(buffer.length(),1024)));
}
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
@@ -641,7 +641,7 @@ bool mysqld_show_create_db(THD *thd, cha
field_list.push_back(new Item_empty_string("Database",NAME_CHAR_LEN));
field_list.push_back(new Item_empty_string("Create Database",1024));
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -691,7 +691,7 @@ mysqld_list_fields(THD *thd, TABLE_LIST
}
restore_record(table, s->default_values); // Get empty record
table->use_all_columns();
- if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
+ if (thd->protocol->send_result_set_metadata(&field_list, Protocol::SEND_DEFAULTS))
DBUG_VOID_RETURN;
my_eof(thd);
DBUG_VOID_RETURN;
@@ -1657,7 +1657,7 @@ void mysqld_list_processes(THD *thd,cons
field->maybe_null=1;
field_list.push_back(field=new Item_empty_string("Info",max_query_length));
field->maybe_null=1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_VOID_RETURN;
@@ -3145,7 +3145,7 @@ static int fill_schema_table_from_frm(TH
OPEN_VIEW_NO_PARSE,
thd->open_options, &tbl, &table_list, thd->mem_root))
goto err_share;
- table_list.view= (st_lex*) share->is_view;
+ table_list.view= (LEX*) share->is_view;
res= schema_table->process_table(thd, &table_list, table,
res, db_name, table_name);
goto err_share;
@@ -3154,7 +3154,7 @@ static int fill_schema_table_from_frm(TH
{
tbl.s= share;
table_list.table= &tbl;
- table_list.view= (st_lex*) share->is_view;
+ table_list.view= (LEX*) share->is_view;
res= schema_table->process_table(thd, &table_list, table,
res, db_name, table_name);
}
@@ -7215,7 +7215,7 @@ static bool show_create_trigger_impl(THD
fields.push_back(new Item_empty_string("Database Collation",
MY_CS_NAME_SIZE));
- if (p->send_fields(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ if (p->send_result_set_metadata(&fields, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
return TRUE;
/* Send data. */
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2008-09-04 08:47:10 +0000
+++ b/sql/sql_table.cc 2008-09-04 20:00:04 +0000
@@ -22,6 +22,7 @@
#include "sp_head.h"
#include "sql_trigger.h"
#include "sql_show.h"
+#include "transaction.h"
#ifdef __WIN__
#include <io.h>
@@ -4165,7 +4166,7 @@ static bool mysql_admin_table(THD* thd,
item->maybe_null = 1;
field_list.push_back(item = new Item_empty_string("Msg_text", 255, cs));
item->maybe_null = 1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
@@ -4257,8 +4258,8 @@ static bool mysql_admin_table(THD* thd,
DBUG_PRINT("admin", ("calling prepare_func"));
switch ((*prepare_func)(thd, table, check_opt)) {
case 1: // error, message written to net
- ha_autocommit_or_rollback(thd, 1);
- end_trans(thd, ROLLBACK);
+ trans_rollback_stmt(thd);
+ trans_rollback(thd);
close_thread_tables(thd);
DBUG_PRINT("admin", ("simple error, admin next table"));
continue;
@@ -4316,8 +4317,8 @@ static bool mysql_admin_table(THD* thd,
length= my_snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
table_name);
protocol->store(buff, length, system_charset_info);
- ha_autocommit_or_rollback(thd, 0);
- end_trans(thd, COMMIT);
+ trans_commit_stmt(thd);
+ trans_commit(thd);
close_thread_tables(thd);
lex->reset_query_tables_list(FALSE);
table->table=0; // For query cache
@@ -4366,7 +4367,7 @@ static bool mysql_admin_table(THD* thd,
HA_ADMIN_NEEDS_ALTER))
{
DBUG_PRINT("admin", ("recreating table"));
- ha_autocommit_or_rollback(thd, 1);
+ trans_rollback_stmt(thd);
close_thread_tables(thd);
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
result_code= mysql_recreate_table(thd, table);
@@ -4480,13 +4481,13 @@ send_result_message:
reopen the table and do ha_innobase::analyze() on it.
We have to end the row, so analyze could return more rows.
*/
+ trans_commit_stmt(thd);
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
protocol->store(STRING_WITH_LEN(
"Table does not support optimize, doing recreate + analyze instead"),
system_charset_info);
if (protocol->write())
goto err;
- ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
DBUG_PRINT("info", ("HA_ADMIN_TRY_ALTER, trying analyze..."));
TABLE_LIST *save_next_local= table->next_local,
@@ -4503,7 +4504,7 @@ send_result_message:
*/
if (thd->main_da.is_ok())
thd->main_da.reset_diagnostics_area();
- ha_autocommit_or_rollback(thd, 0);
+ trans_commit_stmt(thd);
close_thread_tables(thd);
if (!result_code) // recreation went ok
{
@@ -4597,8 +4598,8 @@ send_result_message:
query_cache_invalidate3(thd, table->table, 0);
}
}
- ha_autocommit_or_rollback(thd, 0);
- end_trans(thd, COMMIT);
+ trans_commit_stmt(thd);
+ trans_commit_implicit(thd);
close_thread_tables(thd);
table->table=0; // For query cache
if (protocol->write())
@@ -4609,8 +4610,8 @@ send_result_message:
DBUG_RETURN(FALSE);
err:
- ha_autocommit_or_rollback(thd, 1);
- end_trans(thd, ROLLBACK);
+ trans_rollback_stmt(thd);
+ trans_rollback(thd);
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
@@ -5102,15 +5103,15 @@ mysql_discard_or_import_tablespace(THD *
query_cache_invalidate3(thd, table_list, 0);
/* The ALTER TABLE is always in its own transaction */
- error = ha_autocommit_or_rollback(thd, 0);
- if (end_active_trans(thd))
+ error= trans_commit_stmt(thd);
+ if (trans_commit_implicit(thd))
error=1;
if (error)
goto err;
write_bin_log(thd, FALSE, thd->query, thd->query_length);
err:
- ha_autocommit_or_rollback(thd, error);
+ trans_rollback_stmt(thd);
thd->tablespace_op=FALSE;
if (error == 0)
@@ -5867,8 +5868,8 @@ mysql_fast_or_online_alter_table(THD *th
wait_if_global_read_lock(), which could create a deadlock if called
with LOCK_open.
*/
- error= ha_autocommit_or_rollback(thd, 0);
- if (ha_commit(thd))
+ error= trans_commit_stmt(thd);
+ if (trans_commit_implicit(thd))
error= 1;
if (error)
@@ -7001,8 +7002,8 @@ view_err:
}
else
{
- error= ha_autocommit_or_rollback(thd, 0);
- if (end_active_trans(thd))
+ error= trans_commit_stmt(thd);
+ if (trans_commit_implicit(thd))
error= 1;
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
@@ -7446,9 +7447,9 @@ err:
Ensure that the new table is saved properly to disk so that we
can do a rename
*/
- if (ha_autocommit_or_rollback(thd, 0))
+ if (trans_commit_stmt(thd))
error=1;
- if (end_active_trans(thd))
+ if (trans_commit_implicit(thd))
error=1;
thd->variables.sql_mode= save_sql_mode;
@@ -7513,7 +7514,7 @@ bool mysql_checksum_table(THD *thd, TABL
field_list.push_back(item= new Item_int("Checksum", (longlong) 1,
MY_INT64_NUM_DECIMAL_DIGITS));
item->maybe_null= 1;
- if (protocol->send_fields(&field_list,
+ if (protocol->send_result_set_metadata(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
DBUG_RETURN(TRUE);
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2008-08-22 11:16:08 +0000
+++ b/sql/sql_yacc.yy 2008-09-04 18:30:34 +0000
@@ -575,7 +575,7 @@ bool setup_select_in_parentheses(LEX *le
struct sp_cond_type *spcondtype;
struct { int vars, conds, hndlrs, curs; } spblock;
sp_name *spname;
- struct st_lex *lex;
+ LEX *lex;
sp_head *sphead;
struct p_elem_val *p_elem_value;
enum index_hint_type index_hint;
=== modified file 'sql/structs.h'
--- a/sql/structs.h 2008-07-10 16:02:38 +0000
+++ b/sql/structs.h 2008-09-04 18:30:34 +0000
@@ -16,8 +16,9 @@
/* The old structures from unireg */
-struct st_table;
+struct TABLE;
class Field;
+class THD;
typedef struct st_date_time_format {
uchar positions[8];
@@ -100,7 +101,7 @@ typedef struct st_key {
union {
int bdb_return_if_eq;
} handler;
- struct st_table *table;
+ TABLE *table;
LEX_STRING comment;
} KEY;
@@ -115,30 +116,6 @@ typedef struct st_reginfo { /* Extra in
} REGINFO;
-struct st_read_record; /* For referense later */
-class SQL_SELECT;
-class THD;
-class handler;
-struct st_join_table;
-
-typedef struct st_read_record { /* Parameter to read_record */
- struct st_table *table; /* Head-form */
- handler *file;
- struct st_table **forms; /* head and ref forms */
- int (*read_record)(struct st_read_record *);
- THD *thd;
- SQL_SELECT *select;
- uint cache_records;
- uint ref_length,struct_length,reclength,rec_cache_size,error_offset;
- uint index;
- uchar *ref_pos; /* pointer to form->refpos */
- uchar *record;
- uchar *rec_buf; /* to read field values after filesort */
- uchar *cache,*cache_pos,*cache_end,*read_positions;
- IO_CACHE *io_cache;
- bool print_error, ignore_not_found_rows;
-} READ_RECORD;
-
/*
Originally MySQL used MYSQL_TIME structure inside server only, but since
=== modified file 'sql/table.cc'
--- a/sql/table.cc 2008-08-07 03:05:33 +0000
+++ b/sql/table.cc 2008-08-12 16:46:23 +0000
@@ -3019,7 +3019,7 @@ table_check_intact(TABLE *table, const u
Create Item_field for each column in the table.
SYNPOSIS
- st_table::fill_item_list()
+ TABLE::fill_item_list()
item_list a pointer to an empty list used to store items
DESCRIPTION
@@ -3032,7 +3032,7 @@ table_check_intact(TABLE *table, const u
1 out of memory
*/
-bool st_table::fill_item_list(List<Item> *item_list) const
+bool TABLE::fill_item_list(List<Item> *item_list) const
{
/*
All Item_field's created using a direct pointer to a field
@@ -3052,7 +3052,7 @@ bool st_table::fill_item_list(List<Item>
Fields of this table.
SYNPOSIS
- st_table::fill_item_list()
+ TABLE::fill_item_list()
item_list a non-empty list with Item_fields
DESCRIPTION
@@ -3062,7 +3062,7 @@ bool st_table::fill_item_list(List<Item>
is the same as the number of columns in the table.
*/
-void st_table::reset_item_list(List<Item> *item_list) const
+void TABLE::reset_item_list(List<Item> *item_list) const
{
List_iterator_fast<Item> it(*item_list);
for (Field **ptr= field; *ptr; ptr++)
@@ -3988,7 +3988,7 @@ const char *Natural_join_column::db_name
return table_ref->view_db.str;
/*
- Test that TABLE_LIST::db is the same as st_table_share::db to
+ Test that TABLE_LIST::db is the same as TABLE_SHARE::db to
ensure consistency. An exception are I_S schema tables, which
are inconsistent in this respect.
*/
@@ -4207,7 +4207,7 @@ const char *Field_iterator_table_ref::db
return natural_join_it.column_ref()->db_name();
/*
- Test that TABLE_LIST::db is the same as st_table_share::db to
+ Test that TABLE_LIST::db is the same as TABLE_SHARE::db to
ensure consistency. An exception are I_S schema tables, which
are inconsistent in this respect.
*/
@@ -4379,7 +4379,7 @@ Field_iterator_table_ref::get_natural_co
/* Reset all columns bitmaps */
-void st_table::clear_column_bitmaps()
+void TABLE::clear_column_bitmaps()
{
/*
Reset column read/write usage. It's identical to:
@@ -4400,9 +4400,9 @@ void st_table::clear_column_bitmaps()
key fields.
*/
-void st_table::prepare_for_position()
+void TABLE::prepare_for_position()
{
- DBUG_ENTER("st_table::prepare_for_position");
+ DBUG_ENTER("TABLE::prepare_for_position");
if ((file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
s->primary_key < MAX_KEY)
@@ -4421,14 +4421,14 @@ void st_table::prepare_for_position()
NOTE:
This changes the bitmap to use the tmp bitmap
After this, you can't access any other columns in the table until
- bitmaps are reset, for example with st_table::clear_column_bitmaps()
- or st_table::restore_column_maps_after_mark_index()
+ bitmaps are reset, for example with TABLE::clear_column_bitmaps()
+ or TABLE::restore_column_maps_after_mark_index()
*/
-void st_table::mark_columns_used_by_index(uint index)
+void TABLE::mark_columns_used_by_index(uint index)
{
MY_BITMAP *bitmap= &tmp_set;
- DBUG_ENTER("st_table::mark_columns_used_by_index");
+ DBUG_ENTER("TABLE::mark_columns_used_by_index");
(void) file->extra(HA_EXTRA_KEYREAD);
bitmap_clear_all(bitmap);
@@ -4449,9 +4449,9 @@ void st_table::mark_columns_used_by_inde
when calling mark_columns_used_by_index
*/
-void st_table::restore_column_maps_after_mark_index()
+void TABLE::restore_column_maps_after_mark_index()
{
- DBUG_ENTER("st_table::restore_column_maps_after_mark_index");
+ DBUG_ENTER("TABLE::restore_column_maps_after_mark_index");
key_read= 0;
(void) file->extra(HA_EXTRA_NO_KEYREAD);
@@ -4465,7 +4465,7 @@ void st_table::restore_column_maps_after
mark columns used by key, but don't reset other fields
*/
-void st_table::mark_columns_used_by_index_no_reset(uint index,
+void TABLE::mark_columns_used_by_index_no_reset(uint index,
MY_BITMAP *bitmap)
{
KEY_PART_INFO *key_part= key_info[index].key_part;
@@ -4484,7 +4484,7 @@ void st_table::mark_columns_used_by_inde
always set and sometimes read.
*/
-void st_table::mark_auto_increment_column()
+void TABLE::mark_auto_increment_column()
{
DBUG_ASSERT(found_next_number_field);
/*
@@ -4517,7 +4517,7 @@ void st_table::mark_auto_increment_colum
retrieve the row again.
*/
-void st_table::mark_columns_needed_for_delete()
+void TABLE::mark_columns_needed_for_delete()
{
if (triggers)
triggers->mark_fields_used(TRG_EVENT_DELETE);
@@ -4570,7 +4570,7 @@ void st_table::mark_columns_needed_for_d
retrieve the row again.
*/
-void st_table::mark_columns_needed_for_update()
+void TABLE::mark_columns_needed_for_update()
{
DBUG_ENTER("mark_columns_needed_for_update");
if (triggers)
@@ -4616,7 +4616,7 @@ void st_table::mark_columns_needed_for_u
as changed.
*/
-void st_table::mark_columns_needed_for_insert()
+void TABLE::mark_columns_needed_for_insert()
{
if (triggers)
{
@@ -4692,9 +4692,9 @@ Item_subselect *TABLE_LIST::containing_s
DESCRIPTION
The parser collects the index hints for each table in a "tagged list"
(TABLE_LIST::index_hints). Using the information in this tagged list
- this function sets the members st_table::keys_in_use_for_query,
- st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
- st_table::force_index and st_table::covering_keys.
+ this function sets the members TABLE::keys_in_use_for_query,
+ TABLE::keys_in_use_for_group_by, TABLE::keys_in_use_for_order_by,
+ TABLE::force_index and TABLE::covering_keys.
Current implementation of the runtime does not allow mixing FORCE INDEX
and USE INDEX, so this is checked here. Then the FORCE INDEX list
=== modified file 'sql/table.h'
--- a/sql/table.h 2008-09-11 18:36:05 +0000
+++ b/sql/table.h 2008-09-16 17:58:49 +0000
@@ -245,9 +245,9 @@ struct TABLE_share;
instance of table share per one table in the database.
*/
-typedef struct st_table_share
+struct TABLE_SHARE
{
- st_table_share() {} /* Remove gcc warning */
+ TABLE_SHARE() {} /* Remove gcc warning */
/** Category of this table. */
TABLE_CATEGORY table_category;
@@ -259,8 +259,7 @@ typedef struct st_table_share
TYPELIB fieldnames; /* Pointer to fieldnames */
TYPELIB *intervals; /* pointer to interval info */
pthread_mutex_t LOCK_ha_data; /* To protect access to ha_data */
- struct st_table_share *next, /* Link to unused shares */
- **prev;
+ TABLE_SHARE *next, **prev; /* Link to unused shares */
/*
Doubly-linked (back-linked) lists of used and unused TABLE objects
@@ -550,7 +549,7 @@ typedef struct st_table_share
return (tmp_table == SYSTEM_TMP_TABLE || is_view) ? 0 : table_map_id;
}
-} TABLE_SHARE;
+};
extern ulong refresh_version;
@@ -563,8 +562,9 @@ enum index_hint_type
INDEX_HINT_FORCE
};
-struct st_table {
- st_table() {} /* Remove gcc warning */
+struct TABLE
+{
+ TABLE() {} /* Remove gcc warning */
TABLE_SHARE *s;
handler *file;
@@ -575,11 +575,11 @@ private:
Declared as private to avoid direct manipulation with those objects.
One should use methods of I_P_List template instead.
*/
- struct st_table *share_next, **share_prev;
+ TABLE *share_next, **share_prev;
friend struct TABLE_share;
public:
- struct st_table *next, *prev;
+ TABLE *next, *prev;
THD *in_use; /* Which thread uses this */
Field **field; /* Pointer to fields */
@@ -716,9 +716,7 @@ public:
my_bool force_index;
my_bool distinct,const_table,no_rows;
my_bool key_read, no_keyread;
- my_bool locked_by_logger;
my_bool no_replicate;
- my_bool locked_by_name;
my_bool fulltext_searched;
my_bool no_cache;
/* To signal that the table is associated with a HANDLER statement */
@@ -729,7 +727,6 @@ public:
Used only in the MODE_NO_AUTO_VALUE_ON_ZERO mode.
*/
my_bool auto_increment_field_not_null;
- my_bool insert_or_update; /* Can be used by the handler */
my_bool alias_name_used; /* true if table_name is alias */
my_bool get_fields_in_item_tree; /* Signal to fix_field */
@@ -911,7 +908,6 @@ typedef struct st_schema_table
/** The threshold size a blob field buffer before it is freed */
#define MAX_TDC_BLOB_SIZE 65536
-struct st_lex;
class select_union;
class TMP_TABLE_PARAM;
@@ -991,6 +987,7 @@ public:
;
*/
+struct LEX;
class Index_hint;
struct TABLE_LIST
{
@@ -1106,7 +1103,7 @@ struct TABLE_LIST
TMP_TABLE_PARAM *schema_table_param;
/* link to select_lex where this table was used */
st_select_lex *select_lex;
- st_lex *view; /* link on VIEW lex for merging */
+ LEX *view; /* link on VIEW lex for merging */
Field_translator *field_translation; /* array of VIEW fields */
/* pointer to element after last one in translation table above */
Field_translator *field_translation_end;
@@ -1335,9 +1332,9 @@ struct TABLE_LIST
Item_subselect *containing_subselect();
/*
- Compiles the tagged hints list and fills up st_table::keys_in_use_for_query,
- st_table::keys_in_use_for_group_by, st_table::keys_in_use_for_order_by,
- st_table::force_index and st_table::covering_keys.
+ Compiles the tagged hints list and fills up TABLE::keys_in_use_for_query,
+ TABLE::keys_in_use_for_group_by, TABLE::keys_in_use_for_order_by,
+ TABLE::force_index and TABLE::covering_keys.
*/
bool process_index_hints(TABLE *table);
=== added file 'sql/transaction.cc'
--- a/sql/transaction.cc 1970-01-01 00:00:00 +0000
+++ b/sql/transaction.cc 2008-08-12 22:30:55 +0000
@@ -0,0 +1,584 @@
+/* Copyright (C) 2008 Sun/MySQL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#ifdef USE_PRAGMA_IMPLEMENTATION
+#pragma implementation // gcc: Class implementation
+#endif
+
+#include "transaction.h"
+#include "mysql_priv.h"
+
+#ifdef WITH_MARIA_STORAGE_ENGINE
+#include "../storage/maria/ha_maria.h"
+#endif
+
+/* Conditions under which the transaction state must not change. */
+static bool trans_check(THD *thd)
+{
+ enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+ DBUG_ENTER("trans_check");
+
+ if (unlikely(thd->in_sub_stmt))
+ my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
+ if (xa_state != XA_NOTR)
+ my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+ else
+ DBUG_RETURN(FALSE);
+
+ DBUG_RETURN(TRUE);
+}
+
+
+/**
+ Begin a new transaction.
+
+ @note Beginning a transaction implicitly commits any current
+ transaction and releases existing locks.
+
+ @param thd Current thread
+ @param flags Transaction flags
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_begin(THD *thd, uint flags)
+{
+ int res= FALSE;
+ DBUG_ENTER("trans_begin");
+
+ if (trans_check(thd))
+ DBUG_RETURN(TRUE);
+
+ thd->locked_tables_list.unlock_locked_tables(thd);
+
+ if (trans_commit_implicit(thd))
+ DBUG_RETURN(TRUE);
+
+ thd->options|= OPTION_BEGIN;
+ thd->server_status|= SERVER_STATUS_IN_TRANS;
+
+ if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
+ res= ha_start_consistent_snapshot(thd);
+
+ DBUG_RETURN(test(res));
+}
+
+
+/**
+ Commit the current transaction, making its changes permanent.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_commit(THD *thd)
+{
+ int res;
+ DBUG_ENTER("trans_commit");
+
+ if (trans_check(thd))
+ DBUG_RETURN(TRUE);
+
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ res= ha_commit_trans(thd, TRUE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+ thd->transaction.all.modified_non_trans_table= FALSE;
+ thd->lex->start_transaction_opt= 0;
+
+ DBUG_RETURN(test(res));
+}
+
+
+/**
+ Implicitly commit the current transaction.
+
+ @note A implicit commit does not releases existing table locks.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_commit_implicit(THD *thd)
+{
+ bool res= FALSE;
+ DBUG_ENTER("trans_commit_implicit");
+
+ if (trans_check(thd))
+ DBUG_RETURN(TRUE);
+
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
+ OPTION_TABLE_LOCK))
+ {
+ /* Safety if one did "drop table" on locked tables */
+ if (!thd->locked_tables_mode)
+ thd->options&= ~OPTION_TABLE_LOCK;
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ res= test(ha_commit_trans(thd, TRUE));
+#ifdef WITH_MARIA_STORAGE_ENGINE
+ ha_maria::implicit_commit(thd, TRUE);
+#endif
+ }
+
+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+ thd->transaction.all.modified_non_trans_table= FALSE;
+
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Rollback the current transaction, canceling its changes.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_rollback(THD *thd)
+{
+ int res;
+ DBUG_ENTER("trans_rollback");
+
+ if (trans_check(thd))
+ DBUG_RETURN(TRUE);
+
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ res= ha_rollback_trans(thd, TRUE);
+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+ thd->transaction.all.modified_non_trans_table= FALSE;
+ thd->lex->start_transaction_opt= 0;
+
+ DBUG_RETURN(test(res));
+}
+
+
+/**
+ Commit the single statement transaction.
+
+ @note Note that if the autocommit is on, then the following call
+ inside InnoDB will commit or rollback the whole transaction
+ (= the statement). The autocommit mechanism built into InnoDB
+ is based on counting locks, but if the user has used LOCK
+ TABLES then that mechanism does not know to do the commit.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_commit_stmt(THD *thd)
+{
+ DBUG_ENTER("trans_commit_stmt");
+ int res= FALSE;
+ if (thd->transaction.stmt.ha_list)
+ res= ha_commit_trans(thd, FALSE);
+ DBUG_RETURN(test(res));
+}
+
+
+/**
+ Rollback the single statement transaction.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+bool trans_rollback_stmt(THD *thd)
+{
+ DBUG_ENTER("trans_rollback_stmt");
+
+ if (thd->transaction.stmt.ha_list)
+ {
+ thd->transaction_rollback_request= FALSE;
+ ha_rollback_trans(thd, FALSE);
+ if (thd->transaction_rollback_request && !thd->in_sub_stmt)
+ ha_rollback_trans(thd, TRUE);
+ }
+
+ DBUG_RETURN(FALSE);
+}
+
+/* Find a named savepoint in the current transaction. */
+static SAVEPOINT **
+find_savepoint(THD *thd, LEX_STRING name)
+{
+ SAVEPOINT **sv= &thd->transaction.savepoints;
+
+ while (*sv)
+ {
+ if (my_strnncoll(system_charset_info, (uchar *) name.str, name.length,
+ (uchar *) (*sv)->name, (*sv)->length) == 0)
+ break;
+ sv= &(*sv)->prev;
+ }
+
+ return sv;
+}
+
+
+/**
+ Set a named transaction savepoint.
+
+ @param thd Current thread
+ @param name Savepoint name
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_savepoint(THD *thd, LEX_STRING name)
+{
+ SAVEPOINT **sv, *newsv;
+ DBUG_ENTER("trans_savepoint");
+
+ if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
+ thd->in_sub_stmt) || !opt_using_transactions)
+ DBUG_RETURN(FALSE);
+
+ sv= find_savepoint(thd, name);
+
+ if (*sv) /* old savepoint of the same name exists */
+ {
+ newsv= *sv;
+ ha_release_savepoint(thd, *sv);
+ *sv= (*sv)->prev;
+ }
+ else if ((newsv= (SAVEPOINT *) alloc_root(&thd->transaction.mem_root,
+ savepoint_alloc_size)) == NULL)
+ {
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
+ newsv->name= strmake_root(&thd->transaction.mem_root, name.str, name.length);
+ newsv->length= name.length;
+
+ /*
+ if we'll get an error here, don't add new savepoint to the list.
+ we'll lose a little bit of memory in transaction mem_root, but it'll
+ be free'd when transaction ends anyway
+ */
+ if (ha_savepoint(thd, newsv))
+ DBUG_RETURN(TRUE);
+
+ newsv->prev= thd->transaction.savepoints;
+ thd->transaction.savepoints= newsv;
+
+ DBUG_RETURN(FALSE);
+}
+
+
+/**
+ Rollback a transaction to the named savepoint.
+
+ @note Modifications that the current transaction made to
+ rows after the savepoint was set are undone in the
+ rollback.
+
+ @note Savepoints that were set at a later time than the
+ named savepoint are deleted.
+
+ @param thd Current thread
+ @param name Savepoint name
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name)
+{
+ int res= FALSE;
+ SAVEPOINT *sv= *find_savepoint(thd, name);
+ DBUG_ENTER("trans_rollback_to_savepoint");
+
+ if (sv == NULL)
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (ha_rollback_to_savepoint(thd, sv))
+ res= TRUE;
+ else if (((thd->options & OPTION_KEEP_LOG) ||
+ thd->transaction.all.modified_non_trans_table) &&
+ !thd->slave_thread)
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
+
+ thd->transaction.savepoints= sv;
+
+ DBUG_RETURN(test(res));
+}
+
+
+/**
+ Remove the named savepoint from the set of savepoints of
+ the current transaction.
+
+ @note No commit or rollback occurs. It is an error if the
+ savepoint does not exist.
+
+ @param thd Current thread
+ @param name Savepoint name
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_release_savepoint(THD *thd, LEX_STRING name)
+{
+ int res= FALSE;
+ SAVEPOINT *sv= *find_savepoint(thd, name);
+ DBUG_ENTER("trans_release_savepoint");
+
+ if (sv == NULL)
+ {
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", name.str);
+ DBUG_RETURN(TRUE);
+ }
+
+ if (ha_release_savepoint(thd, sv))
+ res= TRUE;
+
+ thd->transaction.savepoints= sv->prev;
+
+ DBUG_RETURN(test(res));
+}
+
+
+/**
+ Starts an XA transaction with the given xid value.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_xa_start(THD *thd)
+{
+ enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+ DBUG_ENTER("trans_xa_start");
+
+ if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
+ {
+ bool not_equal= !thd->transaction.xid_state.xid.eq(thd->lex->xid);
+ if (not_equal)
+ my_error(ER_XAER_NOTA, MYF(0));
+ else
+ thd->transaction.xid_state.xa_state= XA_ACTIVE;
+ DBUG_RETURN(not_equal);
+ }
+
+ /* TODO: JOIN is not supported yet. */
+ if (thd->lex->xa_opt != XA_NONE)
+ my_error(ER_XAER_INVAL, MYF(0));
+ else if (xa_state != XA_NOTR)
+ my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+ else if (thd->locked_tables_mode || thd->active_transaction())
+ my_error(ER_XAER_OUTSIDE, MYF(0));
+ else if (xid_cache_search(thd->lex->xid))
+ my_error(ER_XAER_DUPID, MYF(0));
+ else if (!trans_begin(thd))
+ {
+ DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
+ thd->transaction.xid_state.xa_state= XA_ACTIVE;
+ thd->transaction.xid_state.xid.set(thd->lex->xid);
+ xid_cache_insert(&thd->transaction.xid_state);
+ DBUG_RETURN(FALSE);
+ }
+
+ DBUG_RETURN(TRUE);
+}
+
+
+/**
+ Put a XA transaction in the IDLE state.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_xa_end(THD *thd)
+{
+ DBUG_ENTER("trans_xa_end");
+
+ /* TODO: SUSPEND and FOR MIGRATE are not supported yet. */
+ if (thd->lex->xa_opt != XA_NONE)
+ my_error(ER_XAER_INVAL, MYF(0));
+ else if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ my_error(ER_XAER_NOTA, MYF(0));
+ else
+ thd->transaction.xid_state.xa_state= XA_IDLE;
+
+ DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_IDLE);
+}
+
+
+/**
+ Put a XA transaction in the PREPARED state.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_xa_prepare(THD *thd)
+{
+ DBUG_ENTER("trans_xa_prepare");
+
+ if (thd->transaction.xid_state.xa_state != XA_IDLE)
+ my_error(ER_XAER_RMFAIL, MYF(0),
+ xa_state_names[thd->transaction.xid_state.xa_state]);
+ else if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ my_error(ER_XAER_NOTA, MYF(0));
+ else if (ha_prepare(thd))
+ {
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state= XA_NOTR;
+ my_error(ER_XA_RBROLLBACK, MYF(0));
+ }
+ else
+ thd->transaction.xid_state.xa_state= XA_PREPARED;
+
+ DBUG_RETURN(thd->transaction.xid_state.xa_state != XA_PREPARED);
+}
+
+
+/**
+ Commit and terminate the a XA transaction.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_xa_commit(THD *thd)
+{
+ bool res= TRUE;
+ enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+ DBUG_ENTER("trans_xa_commit");
+
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ {
+ XID_STATE *xs= xid_cache_search(thd->lex->xid);
+ bool not_found= !xs || xs->in_thd;
+ if (not_found)
+ my_error(ER_XAER_NOTA, MYF(0));
+ else
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
+ xid_cache_delete(xs);
+ }
+ DBUG_RETURN(not_found);
+ }
+
+ if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE)
+ {
+ int r= ha_commit_trans(thd, TRUE);
+ if ((res= test(r)))
+ my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0));
+ }
+ else if (xa_state == XA_PREPARED && thd->lex->xa_opt == XA_NONE)
+ {
+ if (wait_if_global_read_lock(thd, 0, 0))
+ {
+ ha_rollback_trans(thd, TRUE);
+ my_error(ER_XAER_RMERR, MYF(0));
+ }
+ else
+ {
+ res= test(ha_commit_one_phase(thd, 1));
+ if (res)
+ my_error(ER_XAER_RMERR, MYF(0));
+ start_waiting_global_read_lock(thd);
+ }
+ }
+ else
+ my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+
+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+ thd->transaction.all.modified_non_trans_table= FALSE;
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state= XA_NOTR;
+
+ DBUG_RETURN(res);
+}
+
+
+/**
+ Roll back and terminate a XA transaction.
+
+ @param thd Current thread
+
+ @retval FALSE Success
+ @retval TRUE Failure
+*/
+
+bool trans_xa_rollback(THD *thd)
+{
+ bool res= TRUE;
+ enum xa_states xa_state= thd->transaction.xid_state.xa_state;
+ DBUG_ENTER("trans_xa_rollback");
+
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
+ {
+ XID_STATE *xs= xid_cache_search(thd->lex->xid);
+ bool not_found= !xs || xs->in_thd;
+ if (not_found)
+ my_error(ER_XAER_NOTA, MYF(0));
+ else
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
+ xid_cache_delete(xs);
+ }
+ DBUG_RETURN(not_found);
+ }
+
+ if (xa_state != XA_IDLE && xa_state != XA_PREPARED)
+ {
+ my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]);
+ DBUG_RETURN(TRUE);
+ }
+
+ if ((res= test(ha_rollback_trans(thd, TRUE))))
+ my_error(ER_XAER_RMERR, MYF(0));
+
+ thd->options&= ~(OPTION_BEGIN | OPTION_KEEP_LOG);
+ thd->transaction.all.modified_non_trans_table= FALSE;
+ thd->server_status&= ~SERVER_STATUS_IN_TRANS;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state= XA_NOTR;
+
+ DBUG_RETURN(res);
+}
=== added file 'sql/transaction.h'
--- a/sql/transaction.h 1970-01-01 00:00:00 +0000
+++ b/sql/transaction.h 2008-08-12 22:30:55 +0000
@@ -0,0 +1,46 @@
+/* Copyright (C) 2008 Sun/MySQL
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+#ifndef TRANSACTION_H
+#define TRANSACTION_H
+
+#include <my_global.h>
+#include <m_string.h>
+
+class THD;
+
+bool trans_begin(THD *thd, uint flags= 0);
+bool trans_commit(THD *thd);
+bool trans_commit_implicit(THD *thd);
+bool trans_rollback(THD *thd);
+
+bool trans_commit_stmt(THD *thd);
+bool trans_rollback_stmt(THD *thd);
+
+bool trans_savepoint(THD *thd, LEX_STRING name);
+bool trans_rollback_to_savepoint(THD *thd, LEX_STRING name);
+bool trans_release_savepoint(THD *thd, LEX_STRING name);
+
+bool trans_xa_start(THD *thd);
+bool trans_xa_end(THD *thd);
+bool trans_xa_prepare(THD *thd);
+bool trans_xa_commit(THD *thd);
+bool trans_xa_rollback(THD *thd);
+
+#endif /* TRANSACTION_H */
=== modified file 'storage/falcon/BDB.cpp'
--- a/storage/falcon/BDB.cpp 2008-09-04 14:49:10 +0000
+++ b/storage/falcon/BDB.cpp 2008-09-18 16:41:34 +0000
@@ -135,7 +135,7 @@ void Bdb::release()
if (cache->panicShutdown)
{
Thread *thread = Thread::getThread("Cache::fetchPage");
-
+
if (thread->pageMarks == 0)
throw SQLError(RUNTIME_ERROR, "Emergency shut is underway");
}
=== modified file 'storage/falcon/InfoTable.h'
--- a/storage/falcon/InfoTable.h 2008-08-07 12:58:45 +0000
+++ b/storage/falcon/InfoTable.h 2008-09-16 17:58:49 +0000
@@ -25,7 +25,7 @@ typedef long long INT64;
class THD;
struct charset_info_st;
struct TABLE_LIST;
-struct st_table;
+struct TABLE;
class InfoTable
{
@@ -57,7 +57,7 @@ public:
virtual void setNotNull(int column);
int error;
- st_table *table;
+ TABLE *table;
THD *mySqlThread;
charset_info_st *charSetInfo;
};
=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp 2008-09-11 16:28:29 +0000
+++ b/storage/falcon/ha_falcon.cpp 2008-09-16 17:58:49 +0000
@@ -414,7 +414,7 @@ typedef longlong dec2;
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-StorageInterface::StorageInterface(handlerton *hton, st_table_share *table_arg)
+StorageInterface::StorageInterface(handlerton *hton, TABLE_SHARE *table_arg)
: handler(hton, table_arg)
{
ref_length = sizeof(lastRecord);
@@ -1051,7 +1051,7 @@ int StorageInterface::delete_all_rows()
DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
int ret = 0;
- struct st_table_share *tableShare = table_share;
+ TABLE_SHARE *tableShare = table_share;
const char *tableName = tableShare->normalized_path.str;
if (!storageShare)
=== modified file 'storage/falcon/ha_falcon.h'
--- a/storage/falcon/ha_falcon.h 2008-09-09 23:15:17 +0000
+++ b/storage/falcon/ha_falcon.h 2008-09-16 17:58:49 +0000
@@ -28,14 +28,14 @@ static const int TRANSACTION_WRITE_COMMI
static const int TRANSACTION_CONSISTENT_READ = 8; // Dirty reads and non-repeatable reads are prevented; phantom reads can occur.
static const int TRANSACTION_SERIALIZABLE = 16; // Dirty reads, non-repeatable reads and phantom reads are prevented.
-struct st_table_share;
+struct TABLE_SHARE;
class StorageIndexDesc;
struct StorageBlob;
class StorageInterface : public handler
{
public:
- StorageInterface(handlerton *, st_table_share *table_arg);
+ StorageInterface(handlerton *, TABLE_SHARE *table_arg);
~StorageInterface(void);
virtual int open(const char *name, int mode, uint test_if_locked);
@@ -180,7 +180,7 @@ public:
const char* errorText;
THR_LOCK_DATA lockData; // MySQL lock
THD *mySqlThread;
- st_table_share *share;
+ TABLE_SHARE *share;
uint recordLength;
int lastRecord;
int nextRecord;
=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc 2008-08-21 23:38:19 +0000
+++ b/storage/innobase/handler/ha_innodb.cc 2008-09-04 18:30:34 +0000
@@ -3650,7 +3650,7 @@ calc_row_difference(
upd_t* uvect, /* in/out: update vector */
uchar* old_row, /* in: old row in MySQL format */
uchar* new_row, /* in: new row in MySQL format */
- struct st_table* table, /* in: table in MySQL data
+ TABLE* table, /* in: table in MySQL data
dictionary */
uchar* upd_buff, /* in: buffer to use */
ulint buff_len, /* in: buffer length */
=== modified file 'storage/maria/ha_maria.cc'
--- a/storage/maria/ha_maria.cc 2008-08-25 18:34:43 +0000
+++ b/storage/maria/ha_maria.cc 2008-09-04 18:30:34 +0000
@@ -2319,8 +2319,8 @@ int ha_maria::start_stmt(THD *thd, thr_l
This can be considered a hack. When Maria loses HA_NO_TRANSACTIONS it will
be participant in the connection's transaction and so the implicit commits
- (ha_commit()) (like in end_active_trans()) will do the implicit commit
- without need to call this function which can then be removed.
+ (ha_commit_trans()) (like in trans_commit_implicit()) will do the implicit
+ commit without need to call this function which can then be removed.
@param thd THD object
@param new_trn if a new transaction should be created; a new
=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c 2008-08-22 11:16:08 +0000
+++ b/tests/mysql_client_test.c 2008-09-15 20:37:25 +0000
@@ -1500,6 +1500,544 @@ static void test_prepare_simple()
myquery(rc);
}
+/************************************************************************/
+
+#define FILE_PATH_SIZE 4096
+#define CMD_BUFFER_SIZE 8192
+
+char mct_log_file_path[FILE_PATH_SIZE];
+FILE *mct_log_file;
+
+void mct_start_logging(const char *test_case_name)
+{
+ const char *tmp_dir= getenv("MYSQL_TMP_DIR");
+
+ if (!tmp_dir)
+ {
+ printf("Warning: MYSQL_TMP_DIR is not set. Logging is disabled.\n");
+ return;
+ }
+
+ /*
+ Path is: <tmp_dir>/<test_case_name>.out.log
+ 10 is length of '/' + '.out.log' + \0
+ */
+
+ if (strlen(tmp_dir) + strlen(test_case_name) + 10 > FILE_PATH_SIZE)
+ {
+ printf("Warning: MYSQL_TMP_DIR is too long. Logging is disabled.\n");
+ return;
+ }
+
+ my_snprintf(mct_log_file_path, FILE_PATH_SIZE,
+ "%s/%s.out.log",
+ (const char *) tmp_dir,
+ (const char *) test_case_name);
+
+ mct_log_file= my_fopen(mct_log_file_path, O_WRONLY | O_BINARY, MYF(MY_WME));
+
+ if (!mct_log_file)
+ {
+ printf("Warning: can not open log file (%s): %s. Logging is disabled.\n",
+ (const char *) mct_log_file_path,
+ (const char *) strerror(errno));
+ return;
+ }
+}
+
+void mct_log(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ vprintf(format, args);
+ va_end(args);
+
+ if (mct_log_file)
+ {
+ va_list args;
+ va_start(args, format);
+ vfprintf(mct_log_file, format, args);
+ va_end(args);
+ }
+}
+
+int mct_check_result(const char *result_file_name)
+{
+ char diff_cmd[CMD_BUFFER_SIZE];
+
+ const char *test_dir= getenv("MYSQL_TEST_DIR");
+ char result_file_path[FILE_PATH_SIZE];
+
+ if (!mct_log_file)
+ {
+ printf("Warning: logging was disabled. Result checking is impossible.\n");
+ return 0;
+ }
+
+ if (!test_dir)
+ {
+ printf("Warning: MYSQL_TEST_DIR is not set. "
+ "Result checking is impossible.\n");
+ return 0;
+ }
+
+ /*
+ Path is: <test_dir>/<result_file_name>
+ 2 is length of '/' + \0
+ */
+
+ if (strlen(test_dir) + strlen(result_file_name) + 2 > FILE_PATH_SIZE)
+ {
+ printf("Warning: MYSQL_TEST_DIR is too long. "
+ "Result checking is impossible.\n");
+ return 0;
+ }
+
+ my_snprintf(result_file_path, FILE_PATH_SIZE,
+ "%s/%s",
+ (const char *) test_dir,
+ (const char *) result_file_name);
+
+ my_fclose(mct_log_file, MYF(0));
+ mct_log_file= NULL;
+
+ my_snprintf(diff_cmd, CMD_BUFFER_SIZE, "diff -u '%s' '%s'",
+ (const char *) result_file_path,
+ (const char *) mct_log_file_path);
+
+ puts("");
+ fflush(stdout);
+ fflush(stderr);
+
+ return system(diff_cmd);
+}
+
+#define WL4435_NUM_PARAMS 10
+#define WL4435_STRING_SIZE 30
+
+static void test_wl4435()
+{
+ MYSQL_STMT *stmt;
+ int rc;
+ char query[MAX_TEST_QUERY_LENGTH];
+
+ char str_data[20][WL4435_STRING_SIZE];
+ double dbl_data[20];
+ char dec_data[20][WL4435_STRING_SIZE];
+ int int_data[20];
+ ulong str_length= WL4435_STRING_SIZE;
+ my_bool is_null;
+ MYSQL_BIND ps_params[WL4435_NUM_PARAMS];
+
+ int exec_counter;
+
+ myheader("test_wl4435");
+ mct_start_logging("test_wl4435");
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP PROCEDURE IF EXISTS p2");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1(a1 INT, a2 CHAR(32), "
+ " a3 DOUBLE(4, 2), a4 DECIMAL(3, 1))");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "CREATE TABLE t2(b0 INT, b1 INT, b2 CHAR(32), "
+ " b3 DOUBLE(4, 2), b4 DECIMAL(3, 1))");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "INSERT INTO t1 VALUES"
+ "(1, '11', 12.34, 56.7), "
+ "(2, '12', 56.78, 90.1), "
+ "(3, '13', 23.45, 67.8)");
+ myquery(rc);
+
+ rc= mysql_query(mysql, "INSERT INTO t2 VALUES"
+ "(100, 10, '110', 70.70, 10.1), "
+ "(200, 20, '120', 80.80, 20.2), "
+ "(300, 30, '130', 90.90, 30.3)");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "CREATE PROCEDURE p1("
+ " IN v0 INT, "
+ " OUT v_str_1 CHAR(32), "
+ " OUT v_dbl_1 DOUBLE(4, 2), "
+ " OUT v_dec_1 DECIMAL(6, 3), "
+ " OUT v_int_1 INT, "
+ " IN v1 INT, "
+ " INOUT v_str_2 CHAR(64), "
+ " INOUT v_dbl_2 DOUBLE(5, 3), "
+ " INOUT v_dec_2 DECIMAL(7, 4), "
+ " INOUT v_int_2 INT)"
+ "BEGIN "
+ " SET v0 = -1; "
+ " SET v1 = -1; "
+ " SET v_str_1 = 'test_1'; "
+ " SET v_dbl_1 = 12.34; "
+ " SET v_dec_1 = 567.891; "
+ " SET v_int_1 = 2345; "
+ " SET v_str_2 = 'test_2'; "
+ " SET v_dbl_2 = 67.891; "
+ " SET v_dec_2 = 234.6789; "
+ " SET v_int_2 = 6789; "
+ " SELECT * FROM t1; "
+ " SELECT * FROM t2; "
+ "END");
+ myquery(rc);
+
+ rc= mysql_query(mysql,
+ "CREATE PROCEDURE p2("
+ " IN i1 VARCHAR(255) CHARACTER SET koi8r, "
+ " OUT o1 VARCHAR(255) CHARACTER SET cp1251, "
+ " OUT o2 VARBINARY(255)) "
+ "BEGIN "
+ " SET o1 = i1; "
+ " SET o2 = i1; "
+ "END");
+ myquery(rc);
+
+ strmov(query, "CALL p1(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ /* Init PS-parameters. */
+
+ bzero((char *) ps_params, sizeof (ps_params));
+
+ /* - v0 -- INT */
+
+ ps_params[0].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[0].buffer= (char *) &int_data[0];
+ ps_params[0].length= 0;
+ ps_params[0].is_null= 0;
+
+ /* - v_str_1 -- CHAR(32) */
+
+ ps_params[1].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[1].buffer= (char *) str_data[0];
+ ps_params[1].buffer_length= WL4435_STRING_SIZE;
+ ps_params[1].length= &str_length;
+ ps_params[1].is_null= 0;
+
+ /* - v_dbl_1 -- DOUBLE */
+
+ ps_params[2].buffer_type= MYSQL_TYPE_DOUBLE;
+ ps_params[2].buffer= (char *) &dbl_data[0];
+ ps_params[2].length= 0;
+ ps_params[2].is_null= 0;
+
+ /* - v_dec_1 -- DECIMAL */
+
+ ps_params[3].buffer_type= MYSQL_TYPE_NEWDECIMAL;
+ ps_params[3].buffer= (char *) dec_data[0];
+ ps_params[3].buffer_length= WL4435_STRING_SIZE;
+ ps_params[3].length= 0;
+ ps_params[3].is_null= 0;
+
+ /* - v_int_1 -- INT */
+
+ ps_params[4].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[4].buffer= (char *) &int_data[0];
+ ps_params[4].length= 0;
+ ps_params[4].is_null= 0;
+
+ /* - v1 -- INT */
+
+ ps_params[5].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[5].buffer= (char *) &int_data[0];
+ ps_params[5].length= 0;
+ ps_params[5].is_null= 0;
+
+ /* - v_str_2 -- CHAR(32) */
+
+ ps_params[6].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[6].buffer= (char *) str_data[0];
+ ps_params[6].buffer_length= WL4435_STRING_SIZE;
+ ps_params[6].length= &str_length;
+ ps_params[6].is_null= 0;
+
+ /* - v_dbl_2 -- DOUBLE */
+
+ ps_params[7].buffer_type= MYSQL_TYPE_DOUBLE;
+ ps_params[7].buffer= (char *) &dbl_data[0];
+ ps_params[7].length= 0;
+ ps_params[7].is_null= 0;
+
+ /* - v_dec_2 -- DECIMAL */
+
+ ps_params[8].buffer_type= MYSQL_TYPE_DECIMAL;
+ ps_params[8].buffer= (char *) dec_data[0];
+ ps_params[8].buffer_length= WL4435_STRING_SIZE;
+ ps_params[8].length= 0;
+ ps_params[8].is_null= 0;
+
+ /* - v_int_2 -- INT */
+
+ ps_params[9].buffer_type= MYSQL_TYPE_LONG;
+ ps_params[9].buffer= (char *) &int_data[0];
+ ps_params[9].length= 0;
+ ps_params[9].is_null= 0;
+
+ /* Bind parameters. */
+
+ rc= mysql_stmt_bind_param(stmt, ps_params);
+
+ /* Execute! */
+
+ for (exec_counter= 0; exec_counter < 3; ++exec_counter)
+ {
+ int i;
+ int num_fields;
+ MYSQL_BIND *rs_bind;
+
+ mct_log("\nexec_counter: %d\n", (int) exec_counter);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ while (1)
+ {
+ MYSQL_FIELD *fields;
+
+ MYSQL_RES *rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_num_fields(rs_metadata);
+ fields= mysql_fetch_fields(rs_metadata);
+
+ rs_bind= (MYSQL_BIND *) malloc(sizeof (MYSQL_BIND) * num_fields);
+ bzero(rs_bind, sizeof (MYSQL_BIND) * num_fields);
+
+ mct_log("num_fields: %d\n", (int) num_fields);
+
+ for (i = 0; i < num_fields; ++i)
+ {
+ mct_log(" - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
+ "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
+ "type: %d; decimals: %d\n",
+ (int) i,
+ (const char *) fields[i].name,
+ (const char *) fields[i].org_name,
+ (const char *) fields[i].table,
+ (const char *) fields[i].org_table,
+ (const char *) fields[i].db,
+ (const char *) fields[i].catalog,
+ (int) fields[i].length,
+ (int) fields[i].max_length,
+ (int) fields[i].type,
+ (int) fields[i].decimals);
+
+ rs_bind[i].buffer_type= fields[i].type;
+ rs_bind[i].is_null= &is_null;
+
+ switch (fields[i].type)
+ {
+ case MYSQL_TYPE_LONG:
+ rs_bind[i].buffer= (char *) &(int_data[i]);
+ rs_bind[i].buffer_length= sizeof (int_data);
+ break;
+
+ case MYSQL_TYPE_STRING:
+ rs_bind[i].buffer= (char *) str_data[i];
+ rs_bind[i].buffer_length= WL4435_STRING_SIZE;
+ rs_bind[i].length= &str_length;
+ break;
+
+ case MYSQL_TYPE_DOUBLE:
+ rs_bind[i].buffer= (char *) &dbl_data[i];
+ rs_bind[i].buffer_length= sizeof (dbl_data);
+ break;
+
+ case MYSQL_TYPE_NEWDECIMAL:
+ rs_bind[i].buffer= (char *) dec_data[i];
+ rs_bind[i].buffer_length= WL4435_STRING_SIZE;
+ rs_bind[i].length= &str_length;
+ break;
+
+ default:
+ fprintf(stderr, "ERROR: unexpected type: %d.\n", fields[i].type);
+ exit(1);
+ }
+ }
+
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+ check_execute(stmt, rc);
+
+ mct_log("Data:\n");
+
+ while (1)
+ {
+ int rc= mysql_stmt_fetch(stmt);
+
+ if (rc == 1 || rc == MYSQL_NO_DATA)
+ break;
+
+ mct_log(" ");
+
+ for (i = 0; i < num_fields; ++i)
+ {
+ switch (rs_bind[i].buffer_type)
+ {
+ case MYSQL_TYPE_LONG:
+ mct_log(" int: %ld;",
+ (long) *((int *) rs_bind[i].buffer));
+ break;
+
+ case MYSQL_TYPE_STRING:
+ mct_log(" str: '%s';",
+ (char *) rs_bind[i].buffer);
+ break;
+
+ case MYSQL_TYPE_DOUBLE:
+ mct_log(" dbl: %lf;",
+ (double) *((double *) rs_bind[i].buffer));
+ break;
+
+ case MYSQL_TYPE_NEWDECIMAL:
+ mct_log(" dec: '%s';",
+ (char *) rs_bind[i].buffer);
+ break;
+
+ default:
+ printf(" unexpected type (%d)\n",
+ rs_bind[i].buffer_type);
+ }
+ }
+ mct_log("\n");
+ }
+
+ mct_log("EOF\n");
+
+ rc= mysql_stmt_next_result(stmt);
+ mct_log("mysql_stmt_next_result(): %d; field_count: %d\n",
+ (int) rc, (int) mysql->field_count);
+
+ free(rs_bind);
+ mysql_free_result(rs_metadata);
+
+ if (rc > 0)
+ {
+ printf("Error: %s (errno: %d)\n",
+ mysql_error(mysql), mysql_errno(mysql));
+ DIE(rc > 0);
+ }
+
+ if (rc)
+ break;
+
+ if (!mysql->field_count)
+ {
+ /* This is the last OK-packet. No more resultsets. */
+ break;
+ }
+ }
+
+ }
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_commit(mysql);
+ myquery(rc);
+
+ rc= mct_check_result("r/test_wl4435.result");
+ mytest_r(rc);
+
+ /* i18n part of test case. */
+
+ {
+ const char *str_koi8r= "\xee\xd5\x2c\x20\xda\xc1\x20\xd2\xd9\xc2\xc1\xcc\xcb\xd5";
+ const char *str_cp1251= "\xcd\xf3\x2c\x20\xe7\xe0\x20\xf0\xfb\xe1\xe0\xeb\xea\xf3";
+ char o1_buffer[255];
+ ulong o1_length;
+ char o2_buffer[255];
+ ulong o2_length;
+
+ MYSQL_BIND rs_bind[2];
+
+ strmov(query, "CALL p2(?, ?, ?)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ /* Init PS-parameters. */
+
+ bzero((char *) ps_params, sizeof (ps_params));
+
+ ps_params[0].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[0].buffer= (char *) str_koi8r;
+ ps_params[0].buffer_length= strlen(str_koi8r);
+
+ ps_params[1].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[1].buffer= o1_buffer;
+ ps_params[1].buffer_length= 0;
+
+ ps_params[2].buffer_type= MYSQL_TYPE_STRING;
+ ps_params[2].buffer= o2_buffer;
+ ps_params[2].buffer_length= 0;
+
+ /* Bind parameters. */
+
+ rc= mysql_stmt_bind_param(stmt, ps_params);
+ check_execute(stmt, rc);
+
+ /* Prevent converting to character_set_results. */
+
+ rc= mysql_query(mysql, "SET NAMES binary");
+ myquery(rc);
+
+ /* Execute statement. */
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ /* Bind result. */
+
+ bzero(rs_bind, sizeof (rs_bind));
+
+ rs_bind[0].buffer_type= MYSQL_TYPE_STRING;
+ rs_bind[0].buffer= o1_buffer;
+ rs_bind[0].buffer_length= sizeof (o1_buffer);
+ rs_bind[0].length= &o1_length;
+
+ rs_bind[1].buffer_type= MYSQL_TYPE_BLOB;
+ rs_bind[1].buffer= o2_buffer;
+ rs_bind[1].buffer_length= sizeof (o2_buffer);
+ rs_bind[1].length= &o2_length;
+
+ rc= mysql_stmt_bind_result(stmt, rs_bind);
+ check_execute(stmt, rc);
+
+ /* Fetch result. */
+
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ /* Check result. */
+
+ DIE_UNLESS(o1_length == strlen(str_cp1251));
+ DIE_UNLESS(o2_length == strlen(str_koi8r));
+ DIE_UNLESS(!memcmp(o1_buffer, str_cp1251, o1_length));
+ DIE_UNLESS(!memcmp(o2_buffer, str_koi8r, o2_length));
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ rc= mysql_stmt_next_result(stmt);
+ DIE_UNLESS(rc == 0 && mysql->field_count == 0);
+
+ mysql_stmt_close(stmt);
+
+ rc= mysql_commit(mysql);
+ myquery(rc);
+ }
+}
/* Test simple prepare field results */
@@ -14495,9 +15033,8 @@ static void test_bug12001()
/* Create connection that supports multi statements */
if (!mysql_real_connect(mysql_local, opt_host, opt_user,
- opt_password, current_db, opt_port,
- opt_unix_socket, CLIENT_MULTI_STATEMENTS |
- CLIENT_MULTI_RESULTS))
+ opt_password, current_db, opt_port,
+ opt_unix_socket, CLIENT_MULTI_STATEMENTS))
{
fprintf(stdout, "\n mysql_real_connect() failed");
exit(1);
@@ -15869,7 +16406,7 @@ static void test_bug15752()
if (! mysql_real_connect(&mysql_local, opt_host, opt_user,
opt_password, current_db, opt_port,
opt_unix_socket,
- CLIENT_MULTI_STATEMENTS|CLIENT_MULTI_RESULTS))
+ CLIENT_MULTI_STATEMENTS))
{
printf("Unable connect to MySQL server: %s\n", mysql_error(&mysql_local));
DIE_UNLESS(0);
@@ -17831,6 +18368,7 @@ static void test_bug36004()
query_int_variable(mysql, "@@warning_count", &warning_count);
DIE_UNLESS(warning_count == 0);
+ mysql_stmt_close(stmt);
DBUG_VOID_RETURN;
}
@@ -18230,6 +18768,7 @@ static struct my_tests_st my_tests[]= {
{ "test_wl4166_4", test_wl4166_4 },
{ "test_bug36004", test_bug36004 },
{ "test_wl4284_1", test_wl4284_1 },
+ { "test_wl4435", test_wl4435 },
{ "test_bug38486", test_bug38486 },
{ 0, 0 }
};
| Thread |
|---|
| • bzr commit into mysql-6.0-falcon branch (hky:2828) | Hakan Kuecuekyilmaz | 20 Sep |