summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2005-07-19 22:22:12 +0400
committerunknown <konstantin@mysql.com>2005-07-19 22:22:12 +0400
commitcd4bce0244f588798060a6f04c004edfcc8c2b94 (patch)
tree830ecb8cde21d2fbd50c5ef14bdbfa2d7a79b607 /sql
parent185520584dff8f5f23ac719754e4ea2ca499b7ad (diff)
parentde6f5ae5abd127923ce71c0d785e66fdf2ce249f (diff)
downloadmariadb-git-cd4bce0244f588798060a6f04c004edfcc8c2b94.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/kostja/mysql/mysql-5.0-10760-new sql/handler.cc: Auto merged sql/mysqld.cc: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/examples/ha_archive.cc12
-rw-r--r--sql/examples/ha_archive.h9
-rw-r--r--sql/examples/ha_example.cc22
-rw-r--r--sql/examples/ha_example.h4
-rw-r--r--sql/examples/ha_tina.cc31
-rw-r--r--sql/examples/ha_tina.h14
-rw-r--r--sql/ha_berkeley.cc14
-rw-r--r--sql/ha_berkeley.h7
-rw-r--r--sql/ha_blackhole.cc28
-rw-r--r--sql/ha_blackhole.h4
-rw-r--r--sql/ha_federated.cc31
-rw-r--r--sql/ha_federated.h6
-rw-r--r--sql/ha_heap.cc24
-rw-r--r--sql/ha_heap.h3
-rw-r--r--sql/ha_innodb.cc27
-rw-r--r--sql/ha_innodb.h14
-rw-r--r--sql/ha_myisam.cc34
-rw-r--r--sql/ha_myisam.h8
-rw-r--r--sql/ha_myisammrg.cc24
-rw-r--r--sql/ha_myisammrg.h2
-rw-r--r--sql/ha_ndbcluster.cc5
-rw-r--r--sql/handler.cc16
-rw-r--r--sql/handler.h9
-rw-r--r--sql/lock.cc19
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/set_var.cc4
-rw-r--r--sql/sql_class.cc20
-rw-r--r--sql/sql_class.h24
-rw-r--r--sql/sql_prepare.cc17
-rw-r--r--sql/sql_select.cc20
-rw-r--r--sql/sql_select.h2
31 files changed, 374 insertions, 90 deletions
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index c362985f565..e5c35ae019d 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -149,7 +149,8 @@ static handlerton archive_hton = {
0, /* prepare */
0, /* recover */
0, /* commit_by_xid */
- 0 /* rollback_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
};
@@ -208,6 +209,15 @@ bool archive_db_end()
return FALSE;
}
+ha_archive::ha_archive(TABLE *table_arg)
+ :handler(&archive_hton, table_arg), delayed_insert(0), bulk_insert(0)
+{
+ /* Set our original buffer from pre-allocated memory */
+ buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
+
+ /* The size of the offset value we will use for position() */
+ ref_length = sizeof(z_off_t);
+}
/*
This method reads the header of a datafile and returns whether or not it was successful.
diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h
index 3932b62980c..41835c5fb6f 100644
--- a/sql/examples/ha_archive.h
+++ b/sql/examples/ha_archive.h
@@ -58,14 +58,7 @@ class ha_archive: public handler
bool bulk_insert; /* If we are performing a bulk insert */
public:
- ha_archive(TABLE *table): handler(table), delayed_insert(0), bulk_insert(0)
- {
- /* Set our original buffer from pre-allocated memory */
- buffer.set((char *)byte_buffer, IO_SIZE, system_charset_info);
-
- /* The size of the offset value we will use for position() */
- ref_length = sizeof(z_off_t);
- }
+ ha_archive(TABLE *table_arg);
~ha_archive()
{
}
diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc
index 9da297ccd1f..2818c176cd3 100644
--- a/sql/examples/ha_example.cc
+++ b/sql/examples/ha_example.cc
@@ -72,6 +72,24 @@
#ifdef HAVE_EXAMPLE_DB
#include "ha_example.h"
+
+static handlerton example_hton= {
+ "CSV",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
+};
+
/* Variables for example share methods */
static HASH example_open_tables; // Hash used to track open tables
pthread_mutex_t example_mutex; // This is the mutex we use to init the hash
@@ -179,6 +197,10 @@ static int free_share(EXAMPLE_SHARE *share)
}
+ha_example::ha_example(TABLE *table_arg)
+ :handler(&example_hton, table_arg)
+{}
+
/*
If frm_error() is called then we will use this to to find out what file extentions
exist for the storage engine. This is also used by the default rename_table and
diff --git a/sql/examples/ha_example.h b/sql/examples/ha_example.h
index ae72e5bb275..37f38fe5210 100644
--- a/sql/examples/ha_example.h
+++ b/sql/examples/ha_example.h
@@ -45,9 +45,7 @@ class ha_example: public handler
EXAMPLE_SHARE *share; /* Shared lock info */
public:
- ha_example(TABLE *table): handler(table)
- {
- }
+ ha_example(TABLE *table_arg);
~ha_example()
{
}
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index a030960d08a..9c774c1f75c 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -54,6 +54,23 @@ pthread_mutex_t tina_mutex;
static HASH tina_open_tables;
static int tina_init= 0;
+static handlerton tina_hton= {
+ "CSV",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
+};
+
/*****************************************************************************
** TINA tables
*****************************************************************************/
@@ -228,6 +245,20 @@ byte * find_eoln(byte *data, off_t begin, off_t end)
return 0;
}
+
+ha_tina::ha_tina(TABLE *table_arg)
+ :handler(&tina_hton, table_arg),
+ /*
+ These definitions are found in hanler.h
+ These are not probably completely right.
+ */
+ current_position(0), next_position(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH)
+{
+ /* Set our original buffers from pre-allocated memory */
+ buffer.set(byte_buffer, IO_SIZE, system_charset_info);
+ chain= chain_buffer;
+}
+
/*
Encode a buffer into the quoted format.
*/
diff --git a/sql/examples/ha_tina.h b/sql/examples/ha_tina.h
index 22193c01013..5679d77a4dc 100644
--- a/sql/examples/ha_tina.h
+++ b/sql/examples/ha_tina.h
@@ -49,18 +49,8 @@ class ha_tina: public handler
byte chain_alloced;
uint32 chain_size;
- public:
- ha_tina(TABLE *table): handler(table),
- /*
- These definitions are found in hanler.h
- Theses are not probably completely right.
- */
- current_position(0), next_position(0), chain_alloced(0), chain_size(DEFAULT_CHAIN_LENGTH)
- {
- /* Set our original buffers from pre-allocated memory */
- buffer.set(byte_buffer, IO_SIZE, system_charset_info);
- chain = chain_buffer;
- }
+public:
+ ha_tina(TABLE *table_arg);
~ha_tina()
{
if (chain_alloced)
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 568fb727e63..26e743d4a71 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -120,7 +120,8 @@ static handlerton berkeley_hton = {
NULL, /* prepare */
NULL, /* recover */
NULL, /* commit_by_xid */
- NULL /* rollback_by_xid */
+ NULL, /* rollback_by_xid */
+ HTON_CLOSE_CURSORS_AT_COMMIT
};
typedef struct st_berkeley_trx_data {
@@ -372,6 +373,17 @@ void berkeley_cleanup_log_files(void)
/*****************************************************************************
** Berkeley DB tables
*****************************************************************************/
+
+ha_berkeley::ha_berkeley(TABLE *table_arg)
+ :handler(&berkeley_hton, table_arg), alloc_ptr(0), rec_buff(0), file(0),
+ int_table_flags(HA_REC_NOT_IN_SEQ | HA_FAST_KEY_READ |
+ HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED |
+ HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
+ changed_rows(0), last_dup_key((uint) -1), version(0), using_ignore(0)
+{}
+
+
static const char *ha_berkeley_exts[] = {
ha_berkeley_ext,
NullS
diff --git a/sql/ha_berkeley.h b/sql/ha_berkeley.h
index f6376939445..aa92908ecde 100644
--- a/sql/ha_berkeley.h
+++ b/sql/ha_berkeley.h
@@ -85,12 +85,7 @@ class ha_berkeley: public handler
DBT *get_pos(DBT *to, byte *pos);
public:
- ha_berkeley(TABLE *table): handler(table), alloc_ptr(0),rec_buff(0), file(0),
- int_table_flags(HA_REC_NOT_IN_SEQ | HA_FAST_KEY_READ |
- HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_NOT_EXACT_COUNT |
- HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED |
- HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX),
- changed_rows(0),last_dup_key((uint) -1),version(0),using_ignore(0) {}
+ ha_berkeley(TABLE *table_arg);
~ha_berkeley() {}
const char *table_type() const { return "BerkeleyDB"; }
ulong index_flags(uint idx, uint part, bool all_parts) const;
diff --git a/sql/ha_blackhole.cc b/sql/ha_blackhole.cc
index 6abbe983f48..856a053db9e 100644
--- a/sql/ha_blackhole.cc
+++ b/sql/ha_blackhole.cc
@@ -24,6 +24,34 @@
#include "ha_blackhole.h"
+/* Blackhole storage engine handlerton */
+
+static handlerton myisam_hton= {
+ "BLACKHOLE",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
+};
+
+/*****************************************************************************
+** BLACKHOLE tables
+*****************************************************************************/
+
+ha_blackhole::ha_blackhole(TABLE *table_arg)
+ :handler(&blackhole_hton, table_arg)
+{}
+
+
static const char *ha_blackhole_exts[] = {
NullS
};
diff --git a/sql/ha_blackhole.h b/sql/ha_blackhole.h
index 84a386e17f8..2dccabf17cc 100644
--- a/sql/ha_blackhole.h
+++ b/sql/ha_blackhole.h
@@ -28,9 +28,7 @@ class ha_blackhole: public handler
THR_LOCK thr_lock;
public:
- ha_blackhole(TABLE *table): handler(table)
- {
- }
+ ha_blackhole(TABLE *table_arg);
~ha_blackhole()
{
}
diff --git a/sql/ha_federated.cc b/sql/ha_federated.cc
index e0e35c6b866..1d7b8cda8e2 100644
--- a/sql/ha_federated.cc
+++ b/sql/ha_federated.cc
@@ -679,6 +679,37 @@ error:
}
+/* Federated storage engine handlerton */
+
+static handlerton federated_hton= {
+ "FEDERATED",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
+};
+
+
+/*****************************************************************************
+** FEDERATED tables
+*****************************************************************************/
+
+ha_federated::ha_federated(TABLE *table_arg)
+ :handler(&federated_hton, table_arg),
+ mysql(0), stored_result(0), scan_flag(0),
+ ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
+{}
+
+
/*
Convert MySQL result set row to handler internal format
diff --git a/sql/ha_federated.h b/sql/ha_federated.h
index 3e55419f266..58b78ab0dde 100644
--- a/sql/ha_federated.h
+++ b/sql/ha_federated.h
@@ -162,11 +162,7 @@ private:
bool records_in_range);
public:
- ha_federated(TABLE *table): handler(table),
- mysql(0), stored_result(0), scan_flag(0),
- ref_length(sizeof(MYSQL_ROW_OFFSET)), current_position(0)
- {
- }
+ ha_federated(TABLE *table_arg);
~ha_federated()
{
}
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 6e609a94be3..92a5fe0ea09 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -23,9 +23,33 @@
#include <myisampack.h>
#include "ha_heap.h"
+static handlerton heap_hton= {
+ "MEMORY",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
+};
+
/*****************************************************************************
** HEAP tables
*****************************************************************************/
+
+ha_heap::ha_heap(TABLE *table_arg)
+ :handler(&heap_hton, table_arg), file(0), records_changed(0),
+ key_stats_ok(0)
+{}
+
+
static const char *ha_heap_exts[] = {
NullS
};
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 7a97c727049..f7368436456 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -31,8 +31,7 @@ class ha_heap: public handler
uint records_changed;
bool key_stats_ok;
public:
- ha_heap(TABLE *table): handler(table), file(0), records_changed(0),
- key_stats_ok(0) {}
+ ha_heap(TABLE *table);
~ha_heap() {}
const char *table_type() const
{
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 98199a22efe..69451493d4b 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -215,7 +215,14 @@ static handlerton innobase_hton = {
innobase_xa_prepare, /* prepare */
innobase_xa_recover, /* recover */
innobase_commit_by_xid, /* commit_by_xid */
- innobase_rollback_by_xid /* rollback_by_xid */
+ innobase_rollback_by_xid, /* rollback_by_xid */
+ /*
+ For now when one opens a cursor, MySQL does not create an own
+ InnoDB consistent read view for it, and uses the view of the
+ currently active transaction. Therefore, cursors can not
+ survive COMMIT or ROLLBACK statements, which free this view.
+ */
+ HTON_CLOSE_CURSORS_AT_COMMIT
};
/*********************************************************************
@@ -765,6 +772,24 @@ check_trx_exists(
return(trx);
}
+
+/*************************************************************************
+Construct ha_innobase handler. */
+
+ha_innobase::ha_innobase(TABLE *table_arg)
+ :handler(&innobase_hton, table_arg),
+ int_table_flags(HA_REC_NOT_IN_SEQ |
+ HA_NULL_IN_KEY |
+ HA_CAN_INDEX_BLOBS |
+ HA_CAN_SQL_HANDLER |
+ HA_NOT_EXACT_COUNT |
+ HA_PRIMARY_KEY_IN_READ_INDEX |
+ HA_TABLE_SCAN_ON_INDEX),
+ last_dup_key((uint) -1),
+ start_of_scan(0),
+ num_write_row(0)
+{}
+
/*************************************************************************
Updates the user_thd field in a handle and also allocates a new InnoDB
transaction handle if needed, and updates the transaction fields in the
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 90cae3998ed..1584a2182c9 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -81,19 +81,7 @@ class ha_innobase: public handler
/* Init values for the class: */
public:
- ha_innobase(TABLE *table): handler(table),
- int_table_flags(HA_REC_NOT_IN_SEQ |
- HA_NULL_IN_KEY |
- HA_CAN_INDEX_BLOBS |
- HA_CAN_SQL_HANDLER |
- HA_NOT_EXACT_COUNT |
- HA_PRIMARY_KEY_IN_READ_INDEX |
- HA_TABLE_SCAN_ON_INDEX),
- last_dup_key((uint) -1),
- start_of_scan(0),
- num_write_row(0)
- {
- }
+ ha_innobase(TABLE *table_arg);
~ha_innobase() {}
/*
Get the row type from the storage engine. If this method returns
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index e94b697e0bb..fefa05e92b0 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -44,6 +44,29 @@ TYPELIB myisam_recover_typelib= {array_elements(myisam_recover_names)-1,"",
** MyISAM tables
*****************************************************************************/
+/* MyISAM handlerton */
+
+static handlerton myisam_hton= {
+ "MyISAM",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ /*
+ MyISAM doesn't support transactions and doesn't have
+ transaction-dependent context: cursors can survive a commit.
+ */
+ HTON_NO_FLAGS
+};
+
// collect errors printed by mi_check routines
static void mi_check_print_msg(MI_CHECK *param, const char* msg_type,
@@ -123,6 +146,17 @@ void mi_check_print_warning(MI_CHECK *param, const char *fmt,...)
}
+
+ha_myisam::ha_myisam(TABLE *table_arg)
+ :handler(&myisam_hton, table_arg), file(0),
+ int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
+ HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
+ HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
+ HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD),
+ can_enable_indexes(1)
+{}
+
+
static const char *ha_myisam_exts[] = {
".MYI",
".MYD",
diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h
index bbd9721f8e2..ca684463311 100644
--- a/sql/ha_myisam.h
+++ b/sql/ha_myisam.h
@@ -43,13 +43,7 @@ class ha_myisam: public handler
int repair(THD *thd, MI_CHECK &param, bool optimize);
public:
- ha_myisam(TABLE *table): handler(table), file(0),
- int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
- HA_DUPP_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
- HA_FILE_BASED | HA_CAN_GEOMETRY | HA_READ_RND_SAME |
- HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD),
- can_enable_indexes(1)
- {}
+ ha_myisam(TABLE *table_arg);
~ha_myisam() {}
const char *table_type() const { return "MyISAM"; }
const char *index_type(uint key_number);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 5d3f379081c..8c4b4e790b1 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -32,6 +32,30 @@
** MyISAM MERGE tables
*****************************************************************************/
+/* MyISAM MERGE handlerton */
+
+static handlerton myisammrg_hton= {
+ "MRG_MyISAM",
+ 0, /* slot */
+ 0, /* savepoint size. */
+ 0, /* close_connection */
+ 0, /* savepoint */
+ 0, /* rollback to savepoint */
+ 0, /* release savepoint */
+ 0, /* commit */
+ 0, /* rollback */
+ 0, /* prepare */
+ 0, /* recover */
+ 0, /* commit_by_xid */
+ 0, /* rollback_by_xid */
+ HTON_NO_FLAGS
+};
+
+
+ha_myisammrg::ha_myisammrg(TABLE *table_arg)
+ :handler(&myisammrg_hton, table_arg), file(0)
+{}
+
static const char *ha_myisammrg_exts[] = {
".MRG",
NullS
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index 7348096b695..c762b7c286e 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -28,7 +28,7 @@ class ha_myisammrg: public handler
MYRG_INFO *file;
public:
- ha_myisammrg(TABLE *table): handler(table), file(0) {}
+ ha_myisammrg(TABLE *table_arg);
~ha_myisammrg() {}
const char *table_type() const { return "MRG_MyISAM"; }
const char **bas_ext() const;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index d35b8af80aa..81723690b83 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -62,7 +62,8 @@ static handlerton ndbcluster_hton = {
NULL, /* prepare */
NULL, /* recover */
NULL, /* commit_by_xid */
- NULL /* rollback_by_xid */
+ NULL, /* rollback_by_xid */
+ HTON_NO_FLAGS
};
#define NDB_HIDDEN_PRIMARY_KEY_LENGTH 8
@@ -4174,7 +4175,7 @@ ulonglong ha_ndbcluster::get_auto_increment()
*/
ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
- handler(table_arg),
+ handler(&ndbcluster_hton, table_arg),
m_active_trans(NULL),
m_active_cursor(NULL),
m_table(NULL),
diff --git a/sql/handler.cc b/sql/handler.cc
index 9f8fdceb69e..0d0f9a75e52 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -208,15 +208,8 @@ handler *get_new_handler(TABLE *table, enum db_type db_type)
case DB_TYPE_HASH:
return new ha_hash(table);
#endif
-#ifdef HAVE_ISAM
- case DB_TYPE_MRG_ISAM:
- return new ha_isammrg(table);
- case DB_TYPE_ISAM:
- return new ha_isam(table);
-#else
case DB_TYPE_MRG_ISAM:
return new ha_myisammrg(table);
-#endif
#ifdef HAVE_BERKELEY_DB
case DB_TYPE_BERKELEY_DB:
return new ha_berkeley(table);
@@ -634,6 +627,11 @@ int ha_commit_trans(THD *thd, bool all)
DBUG_RETURN(1);
}
DBUG_EXECUTE_IF("crash_commit_before", abort(););
+
+ /* Close all cursors that can not survive COMMIT */
+ if (is_real_trans) /* not a statement commit */
+ thd->stmt_map.close_transient_cursors();
+
if (!trans->no_2pc && trans->nht > 1)
{
for (; *ht && !error; ht++)
@@ -735,6 +733,10 @@ int ha_rollback_trans(THD *thd, bool all)
#ifdef USING_TRANSACTIONS
if (trans->nht)
{
+ /* Close all cursors that can not survive ROLLBACK */
+ if (is_real_trans) /* not a statement commit */
+ thd->stmt_map.close_transient_cursors();
+
for (handlerton **ht=trans->ht; *ht; ht++)
{
int err;
diff --git a/sql/handler.h b/sql/handler.h
index df906e284e7..02b2353b890 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -349,8 +349,13 @@ typedef struct
int (*recover)(XID *xid_list, uint len);
int (*commit_by_xid)(XID *xid);
int (*rollback_by_xid)(XID *xid);
+ uint32 flags; /* global handler flags */
} handlerton;
+/* Possible flags of a handlerton */
+#define HTON_NO_FLAGS 0
+#define HTON_CLOSE_CURSORS_AT_COMMIT 1
+
typedef struct st_thd_trans
{
/* number of entries in the ht[] */
@@ -445,6 +450,7 @@ class handler :public Sql_alloc
virtual int rnd_end() { return 0; }
public:
+ const handlerton *ht; /* storage engine of this handler */
byte *ref; /* Pointer to current row */
byte *dupp_ref; /* Pointer to dupp row */
ulonglong data_file_length; /* Length off data file */
@@ -486,7 +492,8 @@ public:
bool implicit_emptied; /* Can be !=0 only if HEAP */
const COND *pushed_cond;
- handler(TABLE *table_arg) :table(table_arg),
+ handler(const handlerton *ht_arg, TABLE *table_arg) :table(table_arg),
+ ht(ht_arg),
ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0),
delete_length(0), auto_increment_value(0),
records(0), deleted(0), mean_rec_length(0),
diff --git a/sql/lock.cc b/sql/lock.cc
index 7f3fe5ac5da..aa162a23b40 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -103,6 +103,10 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
{
MYSQL_LOCK *sql_lock;
TABLE *write_lock_used;
+ int rc;
+ /* Map the return value of thr_lock to an error from errmsg.txt */
+ const static int thr_lock_errno_to_mysql[]=
+ { 0, 1, ER_LOCK_WAIT_TIMEOUT, ER_LOCK_DEADLOCK };
DBUG_ENTER("mysql_lock_tables");
for (;;)
@@ -135,15 +139,24 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags)
{
my_free((gptr) sql_lock,MYF(0));
sql_lock=0;
- thd->proc_info=0;
break;
}
thd->proc_info="Table lock";
thd->locked=1;
- if (thr_multi_lock(sql_lock->locks,sql_lock->lock_count))
+ rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks,
+ sql_lock->lock_count,
+ thd->lock_id)];
+ if (rc > 1) /* a timeout or a deadlock */
+ {
+ my_error(rc, MYF(0));
+ my_free((gptr) sql_lock,MYF(0));
+ sql_lock= 0;
+ break;
+ }
+ else if (rc == 1) /* aborted */
{
thd->some_tables_deleted=1; // Try again
- sql_lock->lock_count=0; // Locks are alread freed
+ sql_lock->lock_count= 0; // Locks are already freed
}
else if (!thd->some_tables_deleted || (flags & MYSQL_LOCK_IGNORE_FLUSH))
{
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 6ddc9734ad8..30f7c1c6b3d 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4342,7 +4342,8 @@ enum options_mysqld
OPT_ENABLE_LARGE_PAGES,
OPT_TIMED_MUTEXES,
OPT_OLD_STYLE_USER_LIMITS,
- OPT_LOG_SLOW_ADMIN_STATEMENTS
+ OPT_LOG_SLOW_ADMIN_STATEMENTS,
+ OPT_TABLE_LOCK_WAIT_TIMEOUT
};
@@ -5595,6 +5596,11 @@ The minimum value for this variable is 4096.",
"The number of open tables for all threads.", (gptr*) &table_cache_size,
(gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
0, 1, 0},
+ {"table_lock_wait_timeout", OPT_TABLE_LOCK_WAIT_TIMEOUT, "Timeout in "
+ "seconds to wait for a table level lock before returning an error. Used"
+ " only if the connection has active cursors.",
+ (gptr*) &table_lock_wait_timeout, (gptr*) &table_lock_wait_timeout,
+ 0, GET_ULONG, REQUIRED_ARG, 50, 1, 1024 * 1024 * 1024, 0, 1, 0},
{"thread_cache_size", OPT_THREAD_CACHE_SIZE,
"How many threads we should keep in a cache for reuse.",
(gptr*) &thread_cache_size, (gptr*) &thread_cache_size, 0, GET_ULONG,
@@ -7084,4 +7090,6 @@ template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
template class I_List<NAMED_LIST>;
+template class I_List<Statement>;
+template class I_List_iterator<Statement>;
#endif
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 2d7c3364e41..09581aed217 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -375,6 +375,8 @@ sys_var_thd_ulong sys_sync_replication_timeout(
sys_var_bool_ptr sys_sync_frm("sync_frm", &opt_sync_frm);
sys_var_long_ptr sys_table_cache_size("table_cache",
&table_cache_size);
+sys_var_long_ptr sys_table_lock_wait_timeout("table_lock_wait_timeout",
+ &table_lock_wait_timeout);
sys_var_long_ptr sys_thread_cache_size("thread_cache_size",
&thread_cache_size);
sys_var_thd_enum sys_tx_isolation("tx_isolation",
@@ -682,6 +684,7 @@ sys_var *sys_variables[]=
#endif
&sys_sync_frm,
&sys_table_cache_size,
+ &sys_table_lock_wait_timeout,
&sys_table_type,
&sys_thread_cache_size,
&sys_time_format,
@@ -972,6 +975,7 @@ struct show_var_st init_vars[]= {
{"system_time_zone", system_time_zone, SHOW_CHAR},
#endif
{"table_cache", (char*) &table_cache_size, SHOW_LONG},
+ {"table_lock_wait_timeout", (char*) &table_lock_wait_timeout, SHOW_LONG },
{sys_table_type.name, (char*) &sys_table_type, SHOW_SYS},
{sys_thread_cache_size.name,(char*) &sys_thread_cache_size, SHOW_SYS},
#ifdef HAVE_THR_SETCONCURRENCY
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index d0ac1a16f6b..89d5b543dfc 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -173,6 +173,7 @@ Open_tables_state::Open_tables_state()
THD::THD()
:Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0),
Open_tables_state(),
+ lock_id(&main_lock_id),
user_time(0), global_read_lock(0), is_fatal_error(0),
rand_used(0), time_zone_used(0),
last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
@@ -265,6 +266,8 @@ THD::THD()
tablespace_op=FALSE;
ulong tmp=sql_rnd_with_mutex();
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::query_id);
+ thr_lock_info_init(&lock_info); /* safety: will be reset after start */
+ thr_lock_owner_init(&main_lock_id, &lock_info);
}
@@ -406,6 +409,8 @@ THD::~THD()
net_end(&net);
}
#endif
+ stmt_map.destroy(); /* close all prepared statements */
+ DBUG_ASSERT(lock_info.n_cursors == 0);
if (!cleanup_done)
cleanup();
@@ -518,6 +523,7 @@ bool THD::store_globals()
if this is the slave SQL thread.
*/
variables.pseudo_thread_id= thread_id;
+ thr_lock_info_init(&lock_info);
return 0;
}
@@ -1563,6 +1569,12 @@ void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
}
+void Statement::close_cursor()
+{
+ DBUG_ASSERT("Statement::close_cursor()" == "not implemented");
+}
+
+
void THD::end_statement()
{
/* Cleanup SQL processing state to resuse this statement in next query. */
@@ -1683,6 +1695,14 @@ int Statement_map::insert(Statement *statement)
}
+void Statement_map::close_transient_cursors()
+{
+ Statement *stmt;
+ while ((stmt= transient_cursor_list.head()))
+ stmt->close_cursor(); /* deletes itself from the list */
+}
+
+
bool select_dumpvar::send_data(List<Item> &items)
{
List_iterator_fast<Item_func_set_user_var> li(vars);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6c4315b95fa..d6847f5fb35 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -756,7 +756,7 @@ class Cursor;
be used explicitly.
*/
-class Statement: public Query_arena
+class Statement: public ilink, public Query_arena
{
Statement(const Statement &rhs); /* not implemented: */
Statement &operator=(const Statement &rhs); /* non-copyable */
@@ -833,6 +833,8 @@ public:
void restore_backup_statement(Statement *stmt, Statement *backup);
/* return class type */
virtual Type type() const;
+ /* Close the cursor open for this statement, if there is one */
+ virtual void close_cursor();
};
@@ -884,15 +886,25 @@ public:
}
hash_delete(&st_hash, (byte *) statement);
}
+ void add_transient_cursor(Statement *stmt)
+ { transient_cursor_list.append(stmt); }
+ void erase_transient_cursor(Statement *stmt) { stmt->unlink(); }
+ /*
+ Close all cursors of this connection that use tables of a storage
+ engine that has transaction-specific state and therefore can not
+ survive COMMIT or ROLLBACK. Currently all but MyISAM cursors are closed.
+ */
+ void close_transient_cursors();
/* Erase all statements (calls Statement destructor) */
void reset()
{
my_hash_reset(&names_hash);
my_hash_reset(&st_hash);
+ transient_cursor_list.empty();
last_found_statement= 0;
}
- ~Statement_map()
+ void destroy()
{
hash_free(&names_hash);
hash_free(&st_hash);
@@ -900,6 +912,7 @@ public:
private:
HASH st_hash;
HASH names_hash;
+ I_List<Statement> transient_cursor_list;
Statement *last_found_statement;
};
@@ -1017,8 +1030,7 @@ public:
a thread/connection descriptor
*/
-class THD :public ilink,
- public Statement,
+class THD :public Statement,
public Open_tables_state
{
public:
@@ -1044,6 +1056,10 @@ public:
struct rand_struct rand; // used for authentication
struct system_variables variables; // Changeable local variables
struct system_status_var status_var; // Per thread statistic vars
+ THR_LOCK_INFO lock_info; // Locking info of this thread
+ THR_LOCK_OWNER main_lock_id; // To use for conventional queries
+ THR_LOCK_OWNER *lock_id; // If not main_lock_id, points to
+ // the lock_id of a cursor.
pthread_mutex_t LOCK_delete; // Locked before thd is deleted
/* all prepared statements and cursors of this connection */
Statement_map stmt_map;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index aa47b506f73..b0f93463a8e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2020,6 +2020,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
DBUG_VOID_RETURN;
/* If lex->result is set, mysql_execute_command will use it */
stmt->lex->result= &cursor->result;
+ thd->lock_id= &cursor->lock_id;
}
}
#ifndef EMBEDDED_LIBRARY
@@ -2069,6 +2070,9 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
Cursor::open is buried deep in JOIN::exec of the top level join.
*/
cursor->init_from_thd(thd);
+
+ if (cursor->close_at_commit)
+ thd->stmt_map.add_transient_cursor(stmt);
}
else
{
@@ -2078,6 +2082,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
}
thd->set_statement(&stmt_backup);
+ thd->lock_id= &thd->main_lock_id;
thd->current_arena= thd;
DBUG_VOID_RETURN;
@@ -2252,6 +2257,8 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
the previous calls.
*/
free_root(cursor->mem_root, MYF(0));
+ if (cursor->close_at_commit)
+ thd->stmt_map.erase_transient_cursor(stmt);
}
thd->restore_backup_statement(stmt, &stmt_backup);
@@ -2291,14 +2298,6 @@ void mysql_stmt_reset(THD *thd, char *packet)
DBUG_VOID_RETURN;
stmt->close_cursor(); /* will reset statement params */
- cursor= stmt->cursor;
- if (cursor && cursor->is_open())
- {
- thd->change_list= cursor->change_list;
- cursor->close(FALSE);
- cleanup_stmt_and_thd_after_use(stmt, thd);
- free_root(cursor->mem_root, MYF(0));
- }
stmt->state= Query_arena::PREPARED;
@@ -2478,6 +2477,8 @@ void Prepared_statement::close_cursor()
cursor->close(FALSE);
cleanup_stmt_and_thd_after_use(this, thd);
free_root(cursor->mem_root, MYF(0));
+ if (cursor->close_at_commit)
+ thd->stmt_map.erase_transient_cursor(this);
}
/*
Clear parameters from data which could be set by
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b333e369dc4..6147a1b62a5 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1702,10 +1702,12 @@ JOIN::destroy()
Cursor::Cursor(THD *thd)
:Query_arena(&main_mem_root, INITIALIZED),
- join(0), unit(0)
+ join(0), unit(0),
+ close_at_commit(FALSE)
{
/* We will overwrite it at open anyway. */
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+ thr_lock_owner_init(&lock_id, &thd->lock_info);
}
@@ -1739,6 +1741,21 @@ Cursor::init_from_thd(THD *thd)
free_list= thd->free_list;
change_list= thd->change_list;
reset_thd(thd);
+ /* Now we have an active cursor and can cause a deadlock */
+ thd->lock_info.n_cursors++;
+
+ close_at_commit= FALSE; /* reset in case we're reusing the cursor */
+ for (TABLE *table= open_tables; table; table= table->next)
+ {
+ const handlerton *ht= table->file->ht;
+ if (ht)
+ close_at_commit|= (ht->flags & HTON_CLOSE_CURSORS_AT_COMMIT);
+ else
+ {
+ close_at_commit= TRUE; /* handler status is unknown */
+ break;
+ }
+ }
/*
XXX: thd->locked_tables is not changed.
What problems can we have with it if cursor is open?
@@ -1907,6 +1924,7 @@ Cursor::close(bool is_active)
thd->derived_tables= tmp_derived_tables;
thd->lock= tmp_lock;
}
+ thd->lock_info.n_cursors--; /* Decrease the number of active cursors */
join= 0;
unit= 0;
free_items();
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 9285e33be33..7f6d661a4de 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -392,6 +392,8 @@ class Cursor: public Sql_alloc, public Query_arena
public:
Item_change_list change_list;
select_send result;
+ THR_LOCK_OWNER lock_id;
+ my_bool close_at_commit;
/* Temporary implementation as now we replace THD state by value */
/* Save THD state into cursor */