summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <jan@hundin.mysql.fi>2004-12-09 11:20:50 +0200
committerunknown <jan@hundin.mysql.fi>2004-12-09 11:20:50 +0200
commit101fdd4eda0ad9af09939cafb042fda4812bcd1e (patch)
tree465f1cf5128d68051a4742439bf4f69d5975b276 /sql
parent89e77b65cd6999d1b6567f1744fbd35659d9d7b7 (diff)
parent0f99fe728e9d32d8b6bf098775d1ef86235f8a47 (diff)
downloadmariadb-git-101fdd4eda0ad9af09939cafb042fda4812bcd1e.tar.gz
Content merge.
innobase/include/lock0lock.h: Auto merged innobase/row/row0mysql.c: Auto merged sql/ha_innodb.cc: Auto merged sql/ha_innodb.h: Auto merged sql/lock.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_yacc.yy: Auto merged sql/handler.h: content merge.
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_innodb.cc96
-rw-r--r--sql/ha_innodb.h1
-rw-r--r--sql/handler.h1
-rw-r--r--sql/lock.cc62
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/sql_lex.h1
-rw-r--r--sql/sql_parse.cc21
-rw-r--r--sql/sql_yacc.yy13
8 files changed, 191 insertions, 5 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index 0c7fc23ee49..6b7f5e05ee2 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -1346,7 +1346,8 @@ innobase_commit(
3. innobase_query_caching_of_table_permitted(),
4. innobase_savepoint(),
5. ::init_table_handle_for_HANDLER(),
- 6. innobase_start_trx_and_assign_read_view()
+ 6. innobase_start_trx_and_assign_read_view(),
+ 7. ::transactional_table_lock()
and it is only set to 0 in a commit or a rollback. If it is 0 we know
there cannot be resources to be freed and we could return immediately.
@@ -5109,8 +5110,9 @@ ha_innobase::start_stmt(
select_lock_type value. The value of
stored_select_lock_type was decided in:
1) ::store_lock(),
- 2) ::external_lock(), and
- 3) ::init_table_handle_for_HANDLER(). */
+ 2) ::external_lock(),
+ 3) ::init_table_handle_for_HANDLER(), and
+ 4) :.transactional_table_lock(). */
prebuilt->select_lock_type =
prebuilt->stored_select_lock_type;
@@ -5301,6 +5303,94 @@ ha_innobase::external_lock(
DBUG_RETURN(0);
}
+/**********************************************************************
+With this function MySQL request a transactional lock to a table when
+user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
+
+int
+ha_innobase::transactional_table_lock(
+/*==================================*/
+ /* out: 0 */
+ THD* thd, /* in: handle to the user thread */
+ int lock_type) /* in: lock type */
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+ trx_t* trx;
+
+ DBUG_ENTER("ha_innobase::transactional_table_lock");
+ DBUG_PRINT("enter",("lock_type: %d", lock_type));
+
+ /* We do not know if MySQL can call this function before calling
+ external_lock(). To be safe, update the thd of the current table
+ handle. */
+
+ update_thd(thd);
+
+ if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB error:\n"
+"MySQL is trying to use a table handle but the .ibd file for\n"
+"table %s does not exist.\n"
+"Have you deleted the .ibd file from the database directory under\n"
+"the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
+"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
+"how you can resolve the problem.\n",
+ prebuilt->table->name);
+ DBUG_RETURN(HA_ERR_CRASHED);
+ }
+
+ trx = prebuilt->trx;
+
+ prebuilt->sql_stat_start = TRUE;
+ prebuilt->hint_need_to_fetch_extra_cols = 0;
+
+ prebuilt->read_just_key = 0;
+ prebuilt->keep_other_fields_on_keyread = FALSE;
+
+ if (lock_type == F_WRLCK) {
+ prebuilt->select_lock_type = LOCK_X;
+ prebuilt->stored_select_lock_type = LOCK_X;
+ } else if (lock_type == F_RDLCK) {
+ prebuilt->select_lock_type = LOCK_X;
+ prebuilt->stored_select_lock_type = LOCK_X;
+ } else {
+ ut_print_timestamp(stderr);
+ fprintf(stderr, " InnoDB error:\n"
+"MySQL is trying to set transactional table lock with corrupted lock type\n"
+"to table %s, lock type %d does not exist.\n",
+ prebuilt->table->name, lock_type);
+ DBUG_RETURN(HA_ERR_CRASHED);
+ }
+
+ /* MySQL is setting a new transactional table lock */
+
+ /* Set the MySQL flag to mark that there is an active transaction */
+ thd->transaction.all.innodb_active_trans = 1;
+
+ if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
+ ulint error = DB_SUCCESS;
+
+ error = row_lock_table_for_mysql(prebuilt,NULL,
+ LOCK_TABLE_TRANSACTIONAL);
+
+ if (error != DB_SUCCESS) {
+ error = convert_error_code_to_mysql(error, user_thd);
+ DBUG_RETURN(error);
+ }
+
+ if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
+
+ /* Store the current undo_no of the transaction
+ so that we know where to roll back if we have
+ to roll back the next SQL statement */
+
+ trx_mark_sql_stat_end(trx);
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+
/****************************************************************************
Here we export InnoDB status variables to MySQL. */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index b3b8d1a29e8..214e905a327 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -150,6 +150,7 @@ class ha_innobase: public handler
int discard_or_import_tablespace(my_bool discard);
int extra(enum ha_extra_function operation);
int external_lock(THD *thd, int lock_type);
+ int transactional_table_lock(THD *thd, int lock_type);
int start_stmt(THD *thd);
void position(byte *record);
diff --git a/sql/handler.h b/sql/handler.h
index c9adaefa888..4c6bd1c986b 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -452,6 +452,7 @@ public:
{ return extra(operation); }
virtual int reset() { return extra(HA_EXTRA_RESET); }
virtual int external_lock(THD *thd, int lock_type) { return 0; }
+ virtual int transactional_table_lock(THD *thd, int lock_type) {return 0;}
virtual void unlock_row() {}
virtual int start_stmt(THD *thd) {return 0;}
/*
diff --git a/sql/lock.cc b/sql/lock.cc
index 8a3619b57dd..1d511fec415 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -695,6 +695,9 @@ static void print_lock_error(int error)
case HA_ERR_READ_ONLY_TRANSACTION:
textno=ER_READ_ONLY_TRANSACTION;
break;
+ case HA_ERR_LOCK_DEADLOCK:
+ textno=ER_LOCK_DEADLOCK;
+ break;
default:
textno=ER_CANT_LOCK;
break;
@@ -927,3 +930,62 @@ bool make_global_read_lock_block_commit(THD *thd)
thd->exit_cond(old_message);
DBUG_RETURN(error);
}
+
+/*
+ Take transactional table lock for all tables in the list
+
+ SYNOPSIS
+ transactional_lock_tables
+ thd Thread THD
+ tables list of tables
+ counter number of tables in the list
+
+ NOTES
+
+ RETURN
+ 0 - OK
+ -1 - error
+
+*/
+int transactional_lock_tables(THD *thd, TABLE_LIST *tables, uint counter)
+{
+ uint i;
+ int lock_type,error=0;
+ TABLE_LIST *table;
+ TABLE **start,**ptr;
+
+ DBUG_ENTER("transactional_lock_tables");
+
+ if (!(ptr=start=(TABLE**) sql_alloc(sizeof(TABLE*) * counter)))
+ return -1;
+
+ for (table= tables; table; table= table->next_global)
+ {
+ if (!table->placeholder() && !table->schema_table)
+ *(ptr++)= table->table;
+ }
+
+ for (i=1 ; i <= counter ; i++, start++)
+ {
+ DBUG_ASSERT((*start)->reginfo.lock_type >= TL_READ);
+ lock_type=F_WRLCK; /* Lock exclusive */
+
+ if ((*start)->db_stat & HA_READ_ONLY ||
+ ((*start)->reginfo.lock_type >= TL_READ &&
+ (*start)->reginfo.lock_type <= TL_READ_NO_INSERT))
+ lock_type=F_RDLCK;
+
+ if ((error=(*start)->file->transactional_table_lock(thd, lock_type)))
+ {
+ print_lock_error(error);
+ DBUG_RETURN(-1);
+ }
+ else
+ {
+ (*start)->db_stat &= ~ HA_BLOCK_LOCK;
+ (*start)->current_lock= lock_type;
+ }
+ }
+
+ DBUG_RETURN(0);
+}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 91d15dc1125..963ba484cea 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -828,6 +828,7 @@ int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
bool open_and_lock_tables(THD *thd,TABLE_LIST *tables);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
+int transactional_lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
bool rm_temporary_table(enum db_type base, char *path);
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 1c0e3e2e02e..7a4ef0b98e5 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -87,6 +87,7 @@ enum enum_sql_command {
SQLCOM_PREPARE, SQLCOM_EXECUTE, SQLCOM_DEALLOCATE_PREPARE,
SQLCOM_CREATE_VIEW, SQLCOM_DROP_VIEW,
SQLCOM_CREATE_TRIGGER, SQLCOM_DROP_TRIGGER,
+ SQLCOM_LOCK_TABLES_TRANSACTIONAL,
/* This should be the last !!! */
SQLCOM_END
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 3d4252a2b17..50c346619ee 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3257,6 +3257,27 @@ create_error:
thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
thd->in_lock_tables=0;
break;
+ case SQLCOM_LOCK_TABLES_TRANSACTIONAL:
+ {
+ uint counter = 0;
+
+ if (check_db_used(thd, all_tables))
+ goto error;
+ if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0))
+ goto error;
+
+ thd->in_lock_tables=1;
+ thd->options|= OPTION_TABLE_LOCK;
+
+ if (open_tables(thd, all_tables, &counter) == 0 &&
+ transactional_lock_tables(thd, all_tables, counter) == 0)
+ send_ok(thd);
+ else
+ thd->options&= ~(ulong) (OPTION_TABLE_LOCK);
+
+ thd->in_lock_tables=0;
+ break;
+ }
case SQLCOM_CREATE_DB:
{
char *alias;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 8b3cdda5d9e..45f0236d0e8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7387,8 +7387,8 @@ lock:
{
Lex->sql_command=SQLCOM_LOCK_TABLES;
}
- table_lock_list
- {}
+ table_lock_list lock_engine_opt
+ {}
;
table_or_tables:
@@ -7414,6 +7414,15 @@ lock_option:
| READ_SYM LOCAL_SYM { $$= TL_READ; }
;
+lock_engine_opt:
+ /* empty */
+ | WHERE
+ {
+ Lex->sql_command=SQLCOM_LOCK_TABLES_TRANSACTIONAL;
+ }
+ ENGINE_SYM opt_equal storage_engines
+ ;
+
unlock:
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
;