diff options
author | unknown <jan@hundin.mysql.fi> | 2004-12-09 11:20:50 +0200 |
---|---|---|
committer | unknown <jan@hundin.mysql.fi> | 2004-12-09 11:20:50 +0200 |
commit | 101fdd4eda0ad9af09939cafb042fda4812bcd1e (patch) | |
tree | 465f1cf5128d68051a4742439bf4f69d5975b276 /sql | |
parent | 89e77b65cd6999d1b6567f1744fbd35659d9d7b7 (diff) | |
parent | 0f99fe728e9d32d8b6bf098775d1ef86235f8a47 (diff) | |
download | mariadb-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.cc | 96 | ||||
-rw-r--r-- | sql/ha_innodb.h | 1 | ||||
-rw-r--r-- | sql/handler.h | 1 | ||||
-rw-r--r-- | sql/lock.cc | 62 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_parse.cc | 21 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 13 |
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; } ; |