Added support of thd->tx_read_only
Moved timestamp handling from all handler::write() methods in the storage engines to handler::ha_write sql/handler.cc: Added PSI_CALL's
This commit is contained in:
parent
0a70eb33d1
commit
b39e6e3d09
29
TODO
Normal file
29
TODO
Normal file
@ -0,0 +1,29 @@
|
||||
State of MERGE between MariaDB 5.5 and MySQL 5.6.5
|
||||
|
||||
Featured copied/merged
|
||||
- storage/innodb/*
|
||||
- storage/perfschema
|
||||
- sql/share/errmsg-utf8.txt
|
||||
- All CF_XXX states in sql_class.h.
|
||||
- handler error messages.
|
||||
- Removed timestamp handling from all handler::write and handler::update
|
||||
methods.
|
||||
|
||||
Features recoded
|
||||
- Better error messages
|
||||
- Added support of timestamps to ha_write and ha_update.
|
||||
|
||||
Fetures half done:
|
||||
- Support for TRANSACTION READ ONLY | READ WRITE
|
||||
- CF_XXX states added to init_update_queries() but not otherwise used.
|
||||
|
||||
Short time TODO:
|
||||
- Add support for TRANSACTION READ ONLY | READ WRITE in sql_yacc.yy
|
||||
(support for variable tx_read_only)
|
||||
|
||||
- merge hostname.cc / hostname.h
|
||||
- add support for host_error()
|
||||
|
||||
- Enable performance_schema.host_cache in scripts/mysql_system_tables.sql
|
||||
|
||||
- Add full support for timestamp. (remove timestamp handling from ha_write())
|
@ -276,6 +276,15 @@ enum enum_server_command
|
||||
*/
|
||||
#define SERVER_PS_OUT_PARAMS 4096
|
||||
|
||||
/**
|
||||
Set at the same time as SERVER_STATUS_IN_TRANS if the started
|
||||
multi-statement transaction is a read-only transaction. Cleared
|
||||
when the transaction commits or aborts. Since this flag is sent
|
||||
to clients in OK and EOF packets, the flag indicates the
|
||||
transaction status at the end of command execution.
|
||||
*/
|
||||
#define SERVER_STATUS_IN_TRANS_READONLY 8192
|
||||
|
||||
/**
|
||||
Server status flags that must be cleared when starting
|
||||
execution of a new SQL statement.
|
||||
|
@ -12,7 +12,7 @@ INSERT INTO t1 VALUES (1),(2);
|
||||
COMMIT;
|
||||
START TRANSACTION;
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
ERROR 25001: Transaction isolation level can't be changed while a transaction is in progress
|
||||
ERROR 25001: Transaction characteristics can't be changed while a transaction is in progress
|
||||
COMMIT;
|
||||
SET @@autocommit=0;
|
||||
COMMIT;
|
||||
|
@ -28,7 +28,7 @@ COMMIT;
|
||||
# inside a transaction
|
||||
#
|
||||
START TRANSACTION;
|
||||
--error ER_CANT_CHANGE_TX_ISOLATION
|
||||
--error ER_CANT_CHANGE_TX_CHARACTERISTICS
|
||||
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
|
||||
COMMIT;
|
||||
|
||||
|
@ -1455,6 +1455,7 @@ end:
|
||||
else
|
||||
{
|
||||
ulong saved_master_access;
|
||||
bool save_tx_read_only;
|
||||
|
||||
thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
|
||||
|
||||
@ -1466,9 +1467,12 @@ end:
|
||||
|
||||
saved_master_access= thd->security_ctx->master_access;
|
||||
thd->security_ctx->master_access |= SUPER_ACL;
|
||||
save_tx_read_only= thd->tx_read_only;
|
||||
thd->tx_read_only= false;
|
||||
|
||||
ret= Events::drop_event(thd, dbname, name, FALSE);
|
||||
|
||||
thd->tx_read_only= save_tx_read_only;
|
||||
thd->security_ctx->master_access= saved_master_access;
|
||||
}
|
||||
}
|
||||
|
@ -413,6 +413,8 @@ Event_scheduler::start()
|
||||
for writing when the server is running in the read-only mode.
|
||||
*/
|
||||
new_thd->security_ctx->master_access |= SUPER_ACL;
|
||||
new_thd->variables.tx_read_only= false;
|
||||
new_thd->tx_read_only= false;
|
||||
|
||||
scheduler_param_value=
|
||||
(struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0));
|
||||
|
@ -1055,6 +1055,7 @@ Events::load_events_from_db(THD *thd)
|
||||
bool ret= TRUE;
|
||||
uint count= 0;
|
||||
ulong saved_master_access;
|
||||
bool save_tx_read_only;
|
||||
|
||||
DBUG_ENTER("Events::load_events_from_db");
|
||||
DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
|
||||
@ -1067,9 +1068,12 @@ Events::load_events_from_db(THD *thd)
|
||||
|
||||
saved_master_access= thd->security_ctx->master_access;
|
||||
thd->security_ctx->master_access |= SUPER_ACL;
|
||||
save_tx_read_only= thd->tx_read_only;
|
||||
thd->tx_read_only= false;
|
||||
|
||||
ret= db_repository->open_event_table(thd, TL_WRITE, &table);
|
||||
|
||||
thd->tx_read_only= save_tx_read_only;
|
||||
thd->security_ctx->master_access= saved_master_access;
|
||||
|
||||
if (ret)
|
||||
|
123
sql/handler.cc
123
sql/handler.cc
@ -11,8 +11,8 @@
|
||||
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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/** @file handler.cc
|
||||
|
||||
@ -230,7 +230,7 @@ handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RUN_HOOK(transaction, after_rollback, (thd, FALSE));
|
||||
(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
|
||||
|
||||
switch (database_type) {
|
||||
case DB_TYPE_MRG_ISAM:
|
||||
@ -365,6 +365,7 @@ int ha_init_errors(void)
|
||||
SETMSG(HA_ERR_INDEX_CORRUPT, ER_DEFAULT(ER_INDEX_CORRUPT));
|
||||
SETMSG(HA_ERR_TABLE_IN_FK_CHECK, ER_DEFAULT(ER_TABLE_IN_FK_CHECK));
|
||||
SETMSG(HA_ERR_DISK_FULL, ER_DEFAULT(ER_DISK_FULL));
|
||||
SETMSG(HA_FTS_INVALID_DOCID, "Invalid InnoDB FTS Doc ID");
|
||||
|
||||
/* Register the error messages for use with my_error(). */
|
||||
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
|
||||
@ -994,11 +995,14 @@ void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
|
||||
{
|
||||
trans= &thd->transaction.all;
|
||||
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
||||
if (thd->tx_read_only)
|
||||
thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
|
||||
DBUG_PRINT("info", ("setting SERVER_STATUS_IN_TRANS"));
|
||||
}
|
||||
else
|
||||
trans= &thd->transaction.stmt;
|
||||
|
||||
ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
|
||||
ha_info= thd->ha_data[ht_arg->slot].ha_info + (all ? 1 : 0);
|
||||
|
||||
if (ha_info->is_started())
|
||||
DBUG_VOID_RETURN; /* already registered, return */
|
||||
@ -1155,6 +1159,9 @@ int ha_commit_trans(THD *thd, bool all)
|
||||
ER_WARNING_NOT_COMPLETE_ROLLBACK,
|
||||
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)););
|
||||
|
||||
DBUG_PRINT("info",
|
||||
("all: %d thd->in_sub_stmt: %d ha_info: %p is_real_trans: %d",
|
||||
all, thd->in_sub_stmt, ha_info, is_real_trans));
|
||||
/*
|
||||
We must not commit the normal transaction if a statement
|
||||
transaction is pending. Otherwise statement transaction
|
||||
@ -1191,7 +1198,9 @@ int ha_commit_trans(THD *thd, bool all)
|
||||
|
||||
if (!ha_info)
|
||||
{
|
||||
/* Free resources and perform other cleanup even for 'empty' transactions. */
|
||||
/*
|
||||
Free resources and perform other cleanup even for 'empty' transactions.
|
||||
*/
|
||||
if (is_real_trans)
|
||||
thd->transaction.cleanup();
|
||||
DBUG_RETURN(0);
|
||||
@ -1490,7 +1499,7 @@ int ha_rollback_trans(THD *thd, bool all)
|
||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
||||
ER_WARNING_NOT_COMPLETE_ROLLBACK,
|
||||
ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
|
||||
RUN_HOOK(transaction, after_rollback, (thd, FALSE));
|
||||
(void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -2147,6 +2156,16 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
|
||||
ha_delete_table_error_handler.buff);
|
||||
}
|
||||
delete file;
|
||||
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
if (likely(error == 0))
|
||||
{
|
||||
my_bool temp_table= (my_bool)is_prefix(alias, tmp_file_prefix);
|
||||
PSI_CALL(drop_table_share)(temp_table, db, strlen(db),
|
||||
alias, strlen(alias));
|
||||
}
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
@ -2214,6 +2233,30 @@ THD *handler::ha_thd(void) const
|
||||
return (table && table->in_use) ? table->in_use : current_thd;
|
||||
}
|
||||
|
||||
void handler::unbind_psi()
|
||||
{
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
/*
|
||||
Notify the instrumentation that this table is not owned
|
||||
by this thread any more.
|
||||
*/
|
||||
PSI_CALL(unbind_table)(m_psi);
|
||||
#endif
|
||||
}
|
||||
|
||||
void handler::rebind_psi()
|
||||
{
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
/*
|
||||
Notify the instrumentation that this table is now owned
|
||||
by this thread.
|
||||
*/
|
||||
PSI_table_share *share_psi= ha_table_share_psi(table_share);
|
||||
m_psi= PSI_CALL(rebind_table)(share_psi, this, m_psi);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
PSI_table_share *handler::ha_table_share_psi(const TABLE_SHARE *share) const
|
||||
{
|
||||
return share->m_psi;
|
||||
@ -2256,6 +2299,13 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_ASSERT(m_psi == NULL);
|
||||
DBUG_ASSERT(table_share != NULL);
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
PSI_table_share *share_psi= ha_table_share_psi(table_share);
|
||||
m_psi= PSI_CALL(open_table)(share_psi, this);
|
||||
#endif
|
||||
|
||||
if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
|
||||
table->db_stat|=HA_READ_ONLY;
|
||||
(void) extra(HA_EXTRA_NO_READCHECK); // Not needed in SQL
|
||||
@ -2264,7 +2314,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
|
||||
if (!ref && !(ref= (uchar*) alloc_root(&table->mem_root,
|
||||
ALIGN_SIZE(ref_length)*2)))
|
||||
{
|
||||
close();
|
||||
ha_close();
|
||||
error=HA_ERR_OUT_OF_MEM;
|
||||
}
|
||||
else
|
||||
@ -2276,7 +2326,7 @@ int handler::ha_open(TABLE *table_arg, const char *name, int mode,
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
int handler::ha_close()
|
||||
int handler::ha_close(void)
|
||||
{
|
||||
DBUG_ENTER("ha_close");
|
||||
/*
|
||||
@ -2285,6 +2335,11 @@ int handler::ha_close()
|
||||
*/
|
||||
if (table->in_use)
|
||||
status_var_add(table->in_use->status_var.rows_tmp_read, rows_tmp_read);
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
PSI_CALL(close_table)(m_psi);
|
||||
m_psi= NULL; /* instrumentation handle, invalid after close_table() */
|
||||
#endif
|
||||
|
||||
DBUG_RETURN(close());
|
||||
}
|
||||
|
||||
@ -2718,7 +2773,7 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
|
||||
ha_index_init(table->s->next_number_index, 1);
|
||||
if (table->s->next_number_keypart == 0)
|
||||
{ // Autoincrement at key-start
|
||||
error=ha_index_last(table->record[1]);
|
||||
error= ha_index_last(table->record[1]);
|
||||
/*
|
||||
MySQL implicitely assumes such method does locking (as MySQL decides to
|
||||
use nr+increment without checking again with the handler, in
|
||||
@ -3978,10 +4033,19 @@ int ha_create_table(THD *thd, const char *path,
|
||||
const char *name;
|
||||
TABLE_SHARE share;
|
||||
DBUG_ENTER("ha_create_table");
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
my_bool temp_table= (my_bool)is_prefix(table_name, tmp_file_prefix) ||
|
||||
(create_info->options & HA_LEX_CREATE_TMP_TABLE ? TRUE : FALSE);
|
||||
#endif
|
||||
|
||||
init_tmp_table_share(thd, &share, db, 0, table_name, path);
|
||||
if (open_table_def(thd, &share, 0) ||
|
||||
open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
|
||||
if (open_table_def(thd, &share, 0))
|
||||
goto err;
|
||||
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
share.m_psi= PSI_CALL(get_table_share)(temp_table, &share);
|
||||
#endif
|
||||
if (open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
|
||||
TRUE))
|
||||
goto err;
|
||||
|
||||
@ -3996,6 +4060,10 @@ int ha_create_table(THD *thd, const char *path,
|
||||
{
|
||||
strxmov(name_buff, db, ".", table_name, NullS);
|
||||
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
PSI_CALL(drop_table_share)(temp_table, db, strlen(db), table_name,
|
||||
strlen(table_name));
|
||||
#endif
|
||||
}
|
||||
err:
|
||||
free_table_share(&share);
|
||||
@ -4051,6 +4119,15 @@ int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
|
||||
{
|
||||
DBUG_RETURN(3);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PSI_TABLE_INTERFACE
|
||||
/*
|
||||
Table discovery is not instrumented.
|
||||
Once discovered, the table will be opened normally,
|
||||
and instrumented normally.
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, FALSE))
|
||||
{
|
||||
free_table_share(&share);
|
||||
@ -4973,6 +5050,7 @@ static int binlog_log_row(TABLE* table,
|
||||
|
||||
int handler::ha_external_lock(THD *thd, int lock_type)
|
||||
{
|
||||
int error;
|
||||
DBUG_ENTER("handler::ha_external_lock");
|
||||
/*
|
||||
Whether this is lock or unlock, this should be true, and is to verify that
|
||||
@ -5002,11 +5080,14 @@ int handler::ha_external_lock(THD *thd, int lock_type)
|
||||
}
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_external_lock_count);
|
||||
|
||||
/*
|
||||
We cache the table flags if the locking succeeded. Otherwise, we
|
||||
keep them as they were when they were fetched in ha_open().
|
||||
*/
|
||||
int error= external_lock(thd, lock_type);
|
||||
MYSQL_TABLE_LOCK_WAIT(m_psi, PSI_TABLE_EXTERNAL_LOCK, lock_type,
|
||||
{ error= external_lock(thd, lock_type); })
|
||||
|
||||
if (error == 0)
|
||||
cached_table_flags= table_flags();
|
||||
@ -5064,11 +5145,17 @@ int handler::ha_write_row(uchar *buf)
|
||||
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
|
||||
DBUG_ENTER("handler::ha_write_row");
|
||||
|
||||
/* If we have a timestamp column, update it to the current time */
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
mark_trx_read_write();
|
||||
increment_statistics(&SSV::ha_write_count);
|
||||
|
||||
error= write_row(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,
|
||||
{ error= write_row(buf); })
|
||||
|
||||
MYSQL_INSERT_ROW_DONE(error);
|
||||
if (unlikely(error))
|
||||
DBUG_RETURN(error);
|
||||
@ -5090,11 +5177,16 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
|
||||
*/
|
||||
DBUG_ASSERT(new_data == table->record[0]);
|
||||
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
mark_trx_read_write();
|
||||
increment_statistics(&SSV::ha_update_count);
|
||||
|
||||
error= update_row(old_data, new_data);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_UPDATE_ROW, active_index, 0,
|
||||
{ error= update_row(old_data, new_data);})
|
||||
|
||||
MYSQL_UPDATE_ROW_DONE(error);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
@ -5113,7 +5205,8 @@ int handler::ha_delete_row(const uchar *buf)
|
||||
mark_trx_read_write();
|
||||
increment_statistics(&SSV::ha_delete_count);
|
||||
|
||||
error= delete_row(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_DELETE_ROW, active_index, 0,
|
||||
{ error= delete_row(buf);})
|
||||
MYSQL_DELETE_ROW_DONE(error);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
|
@ -326,8 +326,24 @@
|
||||
#define HA_CACHE_TBL_ASKTRANSACT 2
|
||||
#define HA_CACHE_TBL_TRANSACT 4
|
||||
|
||||
/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
|
||||
#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
|
||||
/**
|
||||
Options for the START TRANSACTION statement.
|
||||
|
||||
Note that READ ONLY and READ WRITE are logically mutually exclusive.
|
||||
This is enforced by the parser and depended upon by trans_begin().
|
||||
|
||||
We need two flags instead of one in order to differentiate between
|
||||
situation when no READ WRITE/ONLY clause were given and thus transaction
|
||||
is implicitly READ WRITE and the case when READ WRITE clause was used
|
||||
explicitly.
|
||||
*/
|
||||
|
||||
// WITH CONSISTENT SNAPSHOT option
|
||||
static const uint MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT = 1;
|
||||
// READ ONLY option
|
||||
static const uint MYSQL_START_TRANS_OPT_READ_ONLY = 2;
|
||||
// READ WRITE option
|
||||
static const uint MYSQL_START_TRANS_OPT_READ_WRITE = 4;
|
||||
|
||||
/* Flags for method is_fatal_error */
|
||||
#define HA_CHECK_DUP_KEY 1
|
||||
@ -1840,6 +1856,9 @@ public:
|
||||
*/
|
||||
PSI_table *m_psi;
|
||||
|
||||
virtual void unbind_psi();
|
||||
virtual void rebind_psi();
|
||||
|
||||
handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
|
||||
:table_share(share_arg), table(0),
|
||||
estimation_rows_to_insert(0), ht(ht_arg),
|
||||
|
@ -6453,6 +6453,12 @@ struct my_option my_long_options[]=
|
||||
&global_system_variables.tx_isolation,
|
||||
&global_system_variables.tx_isolation, &tx_isolation_typelib,
|
||||
GET_ENUM, REQUIRED_ARG, ISO_REPEATABLE_READ, 0, 0, 0, 0, 0},
|
||||
{"transaction-read-only", 0,
|
||||
"Default transaction access mode. "
|
||||
"True if transactions are read-only.",
|
||||
&global_system_variables.tx_read_only,
|
||||
&global_system_variables.tx_read_only, 0,
|
||||
GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"user", 'u', "Run mysqld daemon as user.", 0, 0, 0, GET_STR, REQUIRED_ARG,
|
||||
0, 0, 0, 0, 0, 0},
|
||||
{"verbose", 'v', "Used with --help option for detailed help.",
|
||||
@ -6946,7 +6952,7 @@ SHOW_VAR status_vars[]= {
|
||||
{"Handler_commit", (char*) offsetof(STATUS_VAR, ha_commit_count), SHOW_LONG_STATUS},
|
||||
{"Handler_delete", (char*) offsetof(STATUS_VAR, ha_delete_count), SHOW_LONG_STATUS},
|
||||
{"Handler_discover", (char*) offsetof(STATUS_VAR, ha_discover_count), SHOW_LONG_STATUS},
|
||||
|
||||
{"Handler_external_lock", (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS},
|
||||
{"Handler_icp_attempts", (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS},
|
||||
{"Handler_icp_match", (char*) offsetof(STATUS_VAR, ha_icp_match), SHOW_LONG_STATUS},
|
||||
|
||||
|
@ -5981,9 +5981,8 @@ ER_WRONG_PARTITION_NAME
|
||||
eng "Incorrect partition name"
|
||||
ger "Falscher Partitionsname"
|
||||
swe "Felaktigt partitionsnamn"
|
||||
ER_CANT_CHANGE_TX_ISOLATION 25001
|
||||
eng "Transaction isolation level can't be changed while a transaction is in progress"
|
||||
ger "Transaktionsisolationsebene kann während einer laufenden Transaktion nicht geändert werden"
|
||||
ER_CANT_CHANGE_TX_CHARACTERISTICS 25001
|
||||
eng "Transaction characteristics can't be changed while a transaction is in progress"
|
||||
ER_DUP_ENTRY_AUTOINCREMENT_CASE
|
||||
eng "ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '%-.192s' for key '%-.192s'"
|
||||
ger "ALTER TABLE führt zur Neusequenzierung von auto_increment, wodurch der doppelte Eintrag '%-.192s' für Schlüssel '%-.192s' auftritt"
|
||||
|
@ -2907,6 +2907,16 @@ bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
|
||||
|
||||
if (! (flags & MYSQL_OPEN_HAS_MDL_LOCK))
|
||||
{
|
||||
/*
|
||||
Check if we're trying to take a write lock in a read only transaction.
|
||||
*/
|
||||
if (table_list->mdl_request.type >= MDL_SHARED_WRITE &&
|
||||
thd->tx_read_only)
|
||||
{
|
||||
my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
/*
|
||||
We are not under LOCK TABLES and going to acquire write-lock/
|
||||
modify the base table. We need to acquire protection against
|
||||
@ -4706,6 +4716,15 @@ lock_table_names(THD *thd,
|
||||
! (flags & MYSQL_OPEN_SKIP_TEMPORARY) &&
|
||||
find_temporary_table(thd, table))))
|
||||
{
|
||||
/*
|
||||
Write lock on normal tables is not allowed in a read only transaction.
|
||||
*/
|
||||
if (thd->tx_read_only)
|
||||
{
|
||||
my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
|
||||
schema_set.insert(table))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
@ -592,6 +592,12 @@ int thd_tx_isolation(const THD *thd)
|
||||
return (int) thd->tx_isolation;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
int thd_tx_is_read_only(const THD *thd)
|
||||
{
|
||||
return (int) thd->tx_read_only;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void thd_inc_row_count(THD *thd)
|
||||
{
|
||||
@ -1178,6 +1184,7 @@ void THD::init(void)
|
||||
TL_WRITE_LOW_PRIORITY :
|
||||
TL_WRITE);
|
||||
tx_isolation= (enum_tx_isolation) variables.tx_isolation;
|
||||
tx_read_only= variables.tx_read_only;
|
||||
update_charset();
|
||||
reset_current_stmt_binlog_format_row();
|
||||
bzero((char *) &status_var, sizeof(status_var));
|
||||
|
102
sql/sql_class.h
102
sql/sql_class.h
@ -43,7 +43,7 @@
|
||||
#include "violite.h" /* vio_is_connected */
|
||||
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
|
||||
THR_LOCK_INFO */
|
||||
|
||||
#include <mysql/psi/mysql_table.h>
|
||||
|
||||
class Reprepare_observer;
|
||||
class Relay_log_info;
|
||||
@ -537,6 +537,10 @@ typedef struct system_variables
|
||||
*/
|
||||
my_thread_id pseudo_thread_id;
|
||||
|
||||
/**
|
||||
Default transaction access mode. READ ONLY (true) or READ WRITE (false).
|
||||
*/
|
||||
my_bool tx_read_only;
|
||||
my_bool low_priority_updates;
|
||||
my_bool query_cache_wlock_invalidate;
|
||||
my_bool engine_condition_pushdown;
|
||||
@ -619,6 +623,7 @@ typedef struct system_status_var
|
||||
ulong ha_discover_count;
|
||||
ulong ha_savepoint_count;
|
||||
ulong ha_savepoint_rollback_count;
|
||||
ulong ha_external_lock_count;
|
||||
|
||||
#if 0
|
||||
/* KEY_CACHE parts. These are copies of the original */
|
||||
@ -2175,6 +2180,11 @@ public:
|
||||
above.
|
||||
*/
|
||||
enum_tx_isolation tx_isolation;
|
||||
/*
|
||||
Current or next transaction access mode.
|
||||
See comment above regarding tx_isolation.
|
||||
*/
|
||||
bool tx_read_only;
|
||||
enum_check_fields count_cuted_fields;
|
||||
|
||||
DYNAMIC_ARRAY user_var_events; /* For user variables replication */
|
||||
@ -4083,6 +4093,32 @@ public:
|
||||
*/
|
||||
#define CF_CAN_GENERATE_ROW_EVENTS (1U << 9)
|
||||
|
||||
/**
|
||||
Identifies statements which may deal with temporary tables and for which
|
||||
temporary tables should be pre-opened to simplify privilege checks.
|
||||
*/
|
||||
#define CF_PREOPEN_TMP_TABLES (1U << 10)
|
||||
|
||||
/**
|
||||
Identifies statements for which open handlers should be closed in the
|
||||
beginning of the statement.
|
||||
*/
|
||||
#define CF_HA_CLOSE (1U << 11)
|
||||
|
||||
/**
|
||||
Identifies statements that can be explained with EXPLAIN.
|
||||
*/
|
||||
#define CF_CAN_BE_EXPLAINED (1U << 12)
|
||||
|
||||
/** Identifies statements which may generate an optimizer trace */
|
||||
#define CF_OPTIMIZER_TRACE (1U << 14)
|
||||
|
||||
/**
|
||||
Identifies statements that should always be disallowed in
|
||||
read only transactions.
|
||||
*/
|
||||
#define CF_DISALLOW_IN_RO_TRANS (1U << 15)
|
||||
|
||||
/* Bits in server_command_flags */
|
||||
|
||||
/**
|
||||
@ -4144,14 +4180,15 @@ inline int handler::ha_index_read_map(uchar * buf, const uchar * key,
|
||||
key_part_map keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_key_count);
|
||||
int error= index_read_map(buf, key, keypart_map, find_flag);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
|
||||
{ error= index_read_map(buf, key, keypart_map,
|
||||
find_flag); })
|
||||
if (!error)
|
||||
update_index_statistics();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -4167,83 +4204,84 @@ inline int handler::ha_index_read_idx_map(uchar * buf, uint index,
|
||||
key_part_map keypart_map,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==NONE);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_key_count);
|
||||
int error= index_read_idx_map(buf, index, key, keypart_map, find_flag);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, index, 0,
|
||||
{ error= index_read_idx_map(buf, index, key, keypart_map,
|
||||
find_flag); })
|
||||
if (!error)
|
||||
{
|
||||
update_rows_read();
|
||||
index_rows_read[index]++;
|
||||
}
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_index_next(uchar * buf)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_next_count);
|
||||
int error= index_next(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
|
||||
{ error= index_next(buf); })
|
||||
if (!error)
|
||||
update_index_statistics();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_index_prev(uchar * buf)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_prev_count);
|
||||
int error= index_prev(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
|
||||
{ error= index_prev(buf); })
|
||||
if (!error)
|
||||
update_index_statistics();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_index_first(uchar * buf)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_first_count);
|
||||
int error= index_first(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
|
||||
{ error= index_first(buf); })
|
||||
if (!error)
|
||||
update_index_statistics();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_index_last(uchar * buf)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_last_count);
|
||||
int error= index_last(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
|
||||
{ error= index_last(buf); })
|
||||
if (!error)
|
||||
update_index_statistics();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_index_next_same(uchar *buf, const uchar *key,
|
||||
uint keylen)
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(inited==INDEX);
|
||||
MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_read_next_count);
|
||||
int error= index_next_same(buf, key, keylen);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, active_index, 0,
|
||||
{ error= index_next_same(buf, key, keylen); })
|
||||
if (!error)
|
||||
update_index_statistics();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_INDEX_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -4259,8 +4297,9 @@ inline int handler::ha_ft_read(uchar *buf)
|
||||
|
||||
inline int handler::ha_rnd_next(uchar *buf)
|
||||
{
|
||||
MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, TRUE);
|
||||
int error= rnd_next(buf);
|
||||
int error;
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
|
||||
{ error= rnd_next(buf); })
|
||||
if (!error)
|
||||
{
|
||||
update_rows_read();
|
||||
@ -4272,19 +4311,18 @@ inline int handler::ha_rnd_next(uchar *buf)
|
||||
increment_statistics(&SSV::ha_read_rnd_next_count);
|
||||
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_rnd_pos(uchar *buf, uchar *pos)
|
||||
{
|
||||
MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str, FALSE);
|
||||
int error;
|
||||
increment_statistics(&SSV::ha_read_rnd_count);
|
||||
int error= rnd_pos(buf, pos);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_FETCH_ROW, MAX_KEY, 0,
|
||||
{ error= rnd_pos(buf, pos); })
|
||||
if (!error)
|
||||
update_rows_read();
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
MYSQL_READ_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -4308,18 +4346,22 @@ inline int handler::ha_read_first_row(uchar *buf, uint primary_key)
|
||||
|
||||
inline int handler::ha_write_tmp_row(uchar *buf)
|
||||
{
|
||||
int error;
|
||||
MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_tmp_write_count);
|
||||
int error= write_row(buf);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0,
|
||||
{ error= write_row(buf); })
|
||||
MYSQL_INSERT_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
||||
inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data)
|
||||
{
|
||||
int error;
|
||||
MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
|
||||
increment_statistics(&SSV::ha_tmp_update_count);
|
||||
int error= update_row(old_data, new_data);
|
||||
MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_UPDATE_ROW, active_index, 0,
|
||||
{ error= update_row(old_data, new_data);})
|
||||
MYSQL_UPDATE_ROW_DONE(error);
|
||||
return error;
|
||||
}
|
||||
|
@ -553,6 +553,13 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
|
||||
DBUG_ENTER("open_and_lock_for_insert_delayed");
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
/* INSERT DELAYED is not allowed in a read only transaction. */
|
||||
if (thd->tx_read_only)
|
||||
{
|
||||
my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
|
||||
/*
|
||||
In order for the deadlock detector to be able to find any deadlocks
|
||||
caused by the handler thread waiting for GRL or this table, we acquire
|
||||
|
184
sql/sql_parse.cc
184
sql/sql_parse.cc
@ -291,26 +291,54 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||
|
||||
sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;;
|
||||
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;;
|
||||
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | CF_AUTO_COMMIT_TRANS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE |
|
||||
CF_CAN_BE_EXPLAINED;
|
||||
// (1) so that subquery is traced when doing "SET @var = (subquery)"
|
||||
/*
|
||||
@todo SQLCOM_SET_OPTION should have CF_CAN_GENERATE_ROW_EVENTS
|
||||
set, because it may invoke a stored function that generates row
|
||||
events. /Sven
|
||||
*/
|
||||
sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE |
|
||||
CF_AUTO_COMMIT_TRANS |
|
||||
CF_OPTIMIZER_TRACE; // (1)
|
||||
// (1) so that subquery is traced when doing "DO @var := (subquery)"
|
||||
sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE; // (1)
|
||||
|
||||
sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
|
||||
sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE;
|
||||
@ -351,6 +379,11 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
|
||||
sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
|
||||
sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND;
|
||||
/*
|
||||
@todo SQLCOM_BINLOG_BASE64_EVENT should have
|
||||
CF_CAN_GENERATE_ROW_EVENTS set, because this surely generates row
|
||||
events. /Sven
|
||||
*/
|
||||
sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]= CF_STATUS_COMMAND;
|
||||
sql_command_flags[SQLCOM_SHOW_CLIENT_STATS]= CF_STATUS_COMMAND;
|
||||
sql_command_flags[SQLCOM_SHOW_USER_STATS]= CF_STATUS_COMMAND;
|
||||
@ -366,6 +399,12 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA;
|
||||
/*
|
||||
@todo SQLCOM_CREATE_FUNCTION should have CF_AUTO_COMMIT_TRANS
|
||||
set. this currently is binlogged *before* the transaction if
|
||||
executed inside a transaction because it does not have an implicit
|
||||
pre-commit and is written to the statement cache. /Sven
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA;
|
||||
sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS;
|
||||
@ -382,8 +421,13 @@ void init_update_queries(void)
|
||||
last called (or executed) statement is preserved.
|
||||
See mysql_execute_command() for how CF_ROW_COUNT is used.
|
||||
*/
|
||||
/*
|
||||
(1): without it, in "CALL some_proc((subq))", subquery would not be
|
||||
traced.
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CALL]= CF_REEXECUTION_FRAGILE |
|
||||
CF_CAN_GENERATE_ROW_EVENTS;
|
||||
CF_CAN_GENERATE_ROW_EVENTS |
|
||||
CF_OPTIMIZER_TRACE; // (1)
|
||||
sql_command_flags[SQLCOM_EXECUTE]= CF_CAN_GENERATE_ROW_EVENTS;
|
||||
|
||||
/*
|
||||
@ -411,6 +455,104 @@ void init_update_queries(void)
|
||||
sql_command_flags[SQLCOM_CREATE_SERVER]= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS;
|
||||
|
||||
/*
|
||||
The following statements can deal with temporary tables,
|
||||
so temporary tables should be pre-opened for those statements to
|
||||
simplify privilege checking.
|
||||
|
||||
There are other statements that deal with temporary tables and open
|
||||
them, but which are not listed here. The thing is that the order of
|
||||
pre-opening temporary tables for those statements is somewhat custom.
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_TRUNCATE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_LOAD]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_DROP_INDEX]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_UPDATE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_UPDATE_MULTI]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_INSERT_SELECT]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_DELETE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_DELETE_MULTI]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_REPLACE_SELECT]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_SELECT]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_SET_OPTION]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_DO]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_CALL]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_CHECKSUM]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_ANALYZE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_CHECK]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_OPTIMIZE]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_REPAIR]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_PRELOAD_KEYS]|= CF_PREOPEN_TMP_TABLES;
|
||||
sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_PREOPEN_TMP_TABLES;
|
||||
|
||||
/*
|
||||
DDL statements that should start with closing opened handlers.
|
||||
|
||||
We use this flag only for statements for which open HANDLERs
|
||||
have to be closed before emporary tables are pre-opened.
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_TRUNCATE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_REPAIR]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_OPTIMIZE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_ANALYZE]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_CHECK]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_DROP_INDEX]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_PRELOAD_KEYS]|= CF_HA_CLOSE;
|
||||
sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_HA_CLOSE;
|
||||
|
||||
/*
|
||||
Mark statements that always are disallowed in read-only
|
||||
transactions. Note that according to the SQL standard,
|
||||
even temporary table DDL should be disallowed.
|
||||
*/
|
||||
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_RENAME_TABLE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_INDEX]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_DB]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_DB]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_DB]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_VIEW]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_VIEW]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_TRIGGER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_TRIGGER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_EVENT]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_EVENT]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_EVENT]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_USER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_RENAME_USER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_USER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_SERVER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_SERVER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_SERVER]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_FUNCTION]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_CREATE_SPFUNCTION]|=CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_DROP_FUNCTION]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_FUNCTION]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_TRUNCATE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_ALTER_TABLESPACE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_REPAIR]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_OPTIMIZE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_GRANT]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_REVOKE]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_REVOKE_ALL]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_INSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS;
|
||||
}
|
||||
|
||||
bool sqlcom_can_generate_row_events(const THD *thd)
|
||||
@ -2115,6 +2257,19 @@ mysql_execute_command(THD *thd)
|
||||
DEBUG_SYNC(thd,"before_execute_sql_command");
|
||||
#endif
|
||||
|
||||
/*
|
||||
Check if we are in a read-only transaction and we're trying to
|
||||
execute a statement which should always be disallowed in such cases.
|
||||
|
||||
Note that this check is done after any implicit commits.
|
||||
*/
|
||||
if (thd->tx_read_only &&
|
||||
(sql_command_flags[lex->sql_command] & CF_DISALLOW_IN_RO_TRANS))
|
||||
{
|
||||
my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (lex->sql_command) {
|
||||
|
||||
case SQLCOM_SHOW_EVENTS:
|
||||
@ -3766,12 +3921,13 @@ end_with_restore_list:
|
||||
if (tx_chain)
|
||||
{
|
||||
if (trans_begin(thd))
|
||||
goto error;
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset the isolation level if no chaining transaction. */
|
||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
||||
thd->tx_read_only= thd->variables.tx_read_only;
|
||||
}
|
||||
/* Disconnect the current client connection. */
|
||||
if (tx_release)
|
||||
@ -4325,6 +4481,7 @@ create_sp_error:
|
||||
isolation level to the session default.
|
||||
*/
|
||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
||||
thd->tx_read_only= thd->variables.tx_read_only;
|
||||
my_ok(thd);
|
||||
break;
|
||||
case SQLCOM_XA_ROLLBACK:
|
||||
@ -4336,6 +4493,7 @@ create_sp_error:
|
||||
isolation level to the session default.
|
||||
*/
|
||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
||||
thd->tx_read_only= thd->variables.tx_read_only;
|
||||
my_ok(thd);
|
||||
break;
|
||||
case SQLCOM_XA_RECOVER:
|
||||
|
@ -2366,7 +2366,7 @@ static bool check_tx_isolation(sys_var *self, THD *thd, set_var *var)
|
||||
if (var->type == OPT_DEFAULT && thd->in_active_multi_stmt_transaction())
|
||||
{
|
||||
DBUG_ASSERT(thd->in_multi_stmt_transaction_mode());
|
||||
my_error(ER_CANT_CHANGE_TX_ISOLATION, MYF(0));
|
||||
my_error(ER_CANT_CHANGE_TX_CHARACTERISTICS, MYF(0));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
@ -2379,6 +2379,42 @@ static Sys_var_tx_isolation Sys_tx_isolation(
|
||||
tx_isolation_names, DEFAULT(ISO_REPEATABLE_READ),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_isolation));
|
||||
|
||||
|
||||
/**
|
||||
Can't change the tx_read_only state if we are already in a
|
||||
transaction.
|
||||
*/
|
||||
|
||||
static bool check_tx_read_only(sys_var *self, THD *thd, set_var *var)
|
||||
{
|
||||
if (var->type == OPT_DEFAULT && thd->in_active_multi_stmt_transaction())
|
||||
{
|
||||
DBUG_ASSERT(thd->in_multi_stmt_transaction_mode());
|
||||
my_error(ER_CANT_CHANGE_TX_CHARACTERISTICS, MYF(0));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool Sys_var_tx_read_only::session_update(THD *thd, set_var *var)
|
||||
{
|
||||
if (var->type == OPT_SESSION && Sys_var_mybool::session_update(thd, var))
|
||||
return true;
|
||||
if (var->type == OPT_DEFAULT || !thd->in_active_multi_stmt_transaction())
|
||||
{
|
||||
// @see Sys_var_tx_isolation::session_update() above for the rules.
|
||||
thd->tx_read_only= var->save_result.ulonglong_value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static Sys_var_tx_read_only Sys_tx_read_only(
|
||||
"tx_read_only", "Set default transaction access mode to read only.",
|
||||
SESSION_VAR(tx_read_only), NO_CMD_LINE, DEFAULT(0),
|
||||
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_tx_read_only));
|
||||
|
||||
static Sys_var_ulonglong Sys_tmp_table_size(
|
||||
"tmp_table_size",
|
||||
"If an internal in-memory temporary table exceeds this size, MySQL "
|
||||
|
@ -1840,6 +1840,30 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Class representing the tx_read_only system variable for setting
|
||||
default transaction access mode.
|
||||
|
||||
Note that there is a special syntax - SET TRANSACTION READ ONLY
|
||||
(or READ WRITE) that sets the access mode for the next transaction
|
||||
only.
|
||||
*/
|
||||
|
||||
class Sys_var_tx_read_only: public Sys_var_mybool
|
||||
{
|
||||
public:
|
||||
Sys_var_tx_read_only(const char *name_arg, const char *comment, int flag_args,
|
||||
ptrdiff_t off, size_t size, CMD_LINE getopt,
|
||||
my_bool def_val, PolyLock *lock,
|
||||
enum binlog_status_enum binlog_status_arg,
|
||||
on_check_function on_check_func)
|
||||
:Sys_var_mybool(name_arg, comment, flag_args, off, size, getopt,
|
||||
def_val, lock, binlog_status_arg, on_check_func)
|
||||
{}
|
||||
virtual bool session_update(THD *thd, set_var *var);
|
||||
};
|
||||
|
||||
/*
|
||||
Class for replicate_events_marked_for_skip.
|
||||
We need a custom update function that ensures the slave is stopped when
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "transaction.h"
|
||||
#include "rpl_handler.h"
|
||||
#include "debug_sync.h" // DEBUG_SYNC
|
||||
#include "sql_acl.h"
|
||||
|
||||
/* Conditions under which the transaction state must not change. */
|
||||
static bool trans_check(THD *thd)
|
||||
@ -150,9 +151,35 @@ bool trans_begin(THD *thd, uint flags)
|
||||
*/
|
||||
thd->mdl_context.release_transactional_locks();
|
||||
|
||||
// The RO/RW options are mutually exclusive.
|
||||
DBUG_ASSERT(!((flags & MYSQL_START_TRANS_OPT_READ_ONLY) &&
|
||||
(flags & MYSQL_START_TRANS_OPT_READ_WRITE)));
|
||||
if (flags & MYSQL_START_TRANS_OPT_READ_ONLY)
|
||||
thd->tx_read_only= true;
|
||||
else if (flags & MYSQL_START_TRANS_OPT_READ_WRITE)
|
||||
{
|
||||
/*
|
||||
Explicitly starting a RW transaction when the server is in
|
||||
read-only mode, is not allowed unless the user has SUPER priv.
|
||||
Implicitly starting a RW transaction is allowed for backward
|
||||
compatibility.
|
||||
*/
|
||||
const bool user_is_super=
|
||||
test(thd->security_ctx->master_access & SUPER_ACL);
|
||||
if (opt_readonly && !user_is_super)
|
||||
{
|
||||
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
|
||||
DBUG_RETURN(true);
|
||||
}
|
||||
thd->tx_read_only= false;
|
||||
}
|
||||
|
||||
thd->variables.option_bits|= OPTION_BEGIN;
|
||||
thd->server_status|= SERVER_STATUS_IN_TRANS;
|
||||
if (thd->tx_read_only)
|
||||
thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
|
||||
|
||||
/* ha_start_consistent_snapshot() relies on OPTION_BEGIN flag set. */
|
||||
if (flags & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT)
|
||||
res= ha_start_consistent_snapshot(thd);
|
||||
|
||||
@ -234,6 +261,7 @@ bool trans_commit_implicit(THD *thd)
|
||||
to not have any effect on implicit commit.
|
||||
*/
|
||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
||||
thd->tx_read_only= thd->variables.tx_read_only;
|
||||
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
@ -298,7 +326,10 @@ bool trans_commit_stmt(THD *thd)
|
||||
{
|
||||
res= ha_commit_trans(thd, FALSE);
|
||||
if (! thd->in_active_multi_stmt_transaction())
|
||||
{
|
||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
||||
thd->tx_read_only= thd->variables.tx_read_only;
|
||||
}
|
||||
}
|
||||
|
||||
if (res)
|
||||
@ -342,7 +373,10 @@ bool trans_rollback_stmt(THD *thd)
|
||||
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
|
||||
ha_rollback_trans(thd, TRUE);
|
||||
if (! thd->in_active_multi_stmt_transaction())
|
||||
{
|
||||
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
|
||||
thd->tx_read_only= thd->variables.tx_read_only;
|
||||
}
|
||||
}
|
||||
|
||||
RUN_HOOK(transaction, after_rollback, (thd, FALSE));
|
||||
|
@ -889,9 +889,6 @@ int ha_archive::write_row(uchar *buf)
|
||||
if (share->crashed)
|
||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_write_count);
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
mysql_mutex_lock(&share->mutex);
|
||||
|
||||
if (!share->archive_write_open)
|
||||
@ -1315,7 +1312,6 @@ int ha_archive::rnd_next(uchar *buf)
|
||||
}
|
||||
scan_rows--;
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
|
||||
current_position= aztell(&archive);
|
||||
rc= get_row(&archive, buf);
|
||||
|
||||
@ -1351,7 +1347,6 @@ int ha_archive::rnd_pos(uchar * buf, uchar *pos)
|
||||
{
|
||||
int rc;
|
||||
DBUG_ENTER("ha_archive::rnd_pos");
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
|
||||
current_position= (my_off_t)my_get_ptr(pos, ref_length);
|
||||
if (azseek(&archive, current_position, SEEK_SET) == (my_off_t)(-1L))
|
||||
{
|
||||
|
@ -997,11 +997,6 @@ int ha_tina::write_row(uchar * buf)
|
||||
if (share->crashed)
|
||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_write_count);
|
||||
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
size= encode_quote(buf);
|
||||
|
||||
if (!share->tina_write_opened)
|
||||
@ -1062,11 +1057,6 @@ int ha_tina::update_row(const uchar * old_data, uchar * new_data)
|
||||
int rc= -1;
|
||||
DBUG_ENTER("ha_tina::update_row");
|
||||
|
||||
ha_statistic_increment(&SSV::ha_update_count);
|
||||
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
size= encode_quote(new_data);
|
||||
|
||||
/*
|
||||
@ -1109,7 +1099,6 @@ err:
|
||||
int ha_tina::delete_row(const uchar * buf)
|
||||
{
|
||||
DBUG_ENTER("ha_tina::delete_row");
|
||||
ha_statistic_increment(&SSV::ha_delete_count);
|
||||
|
||||
if (chain_append())
|
||||
DBUG_RETURN(-1);
|
||||
@ -1231,8 +1220,6 @@ int ha_tina::rnd_next(uchar *buf)
|
||||
goto end;
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
|
||||
|
||||
current_position= next_position;
|
||||
|
||||
/* don't scan an empty file */
|
||||
@ -1281,7 +1268,6 @@ int ha_tina::rnd_pos(uchar * buf, uchar *pos)
|
||||
DBUG_ENTER("ha_tina::rnd_pos");
|
||||
MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
|
||||
FALSE);
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_count);
|
||||
current_position= my_get_ptr(pos,ref_length);
|
||||
rc= find_current_row(buf);
|
||||
MYSQL_READ_ROW_DONE(rc);
|
||||
|
@ -495,8 +495,6 @@ int ha_example::write_row(uchar *buf)
|
||||
Currently new_data will not have an updated auto_increament record, or
|
||||
and updated timestamp field. You can do these for example by doing:
|
||||
@code
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
if (table->next_number_field && record == table->record[0])
|
||||
update_auto_increment();
|
||||
@endcode
|
||||
|
@ -1848,9 +1848,6 @@ int ha_federated::write_row(uchar *buf)
|
||||
|
||||
values_string.length(0);
|
||||
insert_field_value_string.length(0);
|
||||
ha_statistic_increment(&SSV::ha_write_count);
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
/*
|
||||
start both our field and field values strings
|
||||
@ -2434,7 +2431,6 @@ int ha_federated::index_read_idx_with_result_set(uchar *buf, uint index,
|
||||
*result= 0; // In case of errors
|
||||
index_string.length(0);
|
||||
sql_query.length(0);
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
|
||||
sql_query.append(share->select_query);
|
||||
|
||||
@ -2562,7 +2558,6 @@ int ha_federated::index_next(uchar *buf)
|
||||
{
|
||||
int retval;
|
||||
DBUG_ENTER("ha_federated::index_next");
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
retval= read_next(buf, stored_result);
|
||||
DBUG_RETURN(retval);
|
||||
}
|
||||
@ -2772,8 +2767,6 @@ int ha_federated::rnd_pos(uchar *buf, uchar *pos)
|
||||
int ret_val;
|
||||
DBUG_ENTER("ha_federated::rnd_pos");
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_count);
|
||||
|
||||
/* Get stored result set. */
|
||||
memcpy(&result, pos, sizeof(MYSQL_RES *));
|
||||
DBUG_ASSERT(result);
|
||||
|
@ -1993,8 +1993,6 @@ int ha_federatedx::write_row(uchar *buf)
|
||||
|
||||
values_string.length(0);
|
||||
insert_field_value_string.length(0);
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
/*
|
||||
start both our field and field values strings
|
||||
|
@ -241,8 +241,6 @@ void ha_heap::update_key_stats()
|
||||
int ha_heap::write_row(uchar * buf)
|
||||
{
|
||||
int res;
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
if (table->next_number_field && buf == table->record[0])
|
||||
{
|
||||
if ((res= update_auto_increment()))
|
||||
@ -264,8 +262,6 @@ int ha_heap::write_row(uchar * buf)
|
||||
int ha_heap::update_row(const uchar * old_data, uchar * new_data)
|
||||
{
|
||||
int res;
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
res= heap_update(file,old_data,new_data);
|
||||
if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
|
||||
file->s->records)
|
||||
|
@ -6107,8 +6107,6 @@ ha_innobase::write_row(
|
||||
++trx->will_lock;
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_write_count);
|
||||
|
||||
sql_command = thd_sql_command(user_thd);
|
||||
|
||||
if ((sql_command == SQLCOM_ALTER_TABLE
|
||||
@ -6648,8 +6646,6 @@ ha_innobase::update_row(
|
||||
}
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_update_count);
|
||||
|
||||
if (prebuilt->upd_node) {
|
||||
uvect = prebuilt->upd_node->update;
|
||||
} else {
|
||||
@ -6760,8 +6756,6 @@ ha_innobase::delete_row(
|
||||
++trx->will_lock;
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_delete_count);
|
||||
|
||||
if (!prebuilt->upd_node) {
|
||||
row_get_prebuilt_update_vector(prebuilt);
|
||||
}
|
||||
@ -7023,8 +7017,6 @@ ha_innobase::index_read(
|
||||
|
||||
ut_a(prebuilt->trx == thd_to_trx(user_thd));
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
|
||||
index = prebuilt->index;
|
||||
|
||||
if (UNIV_UNLIKELY(index == NULL) || dict_index_is_corrupted(index)) {
|
||||
@ -7367,8 +7359,6 @@ ha_innobase::index_next(
|
||||
uchar* buf) /*!< in/out: buffer for next row in MySQL
|
||||
format */
|
||||
{
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_NEXT, 0));
|
||||
}
|
||||
|
||||
@ -7383,8 +7373,6 @@ ha_innobase::index_next_same(
|
||||
const uchar* key, /*!< in: key value */
|
||||
uint keylen) /*!< in: key value length */
|
||||
{
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
|
||||
}
|
||||
|
||||
@ -7398,8 +7386,6 @@ ha_innobase::index_prev(
|
||||
/*====================*/
|
||||
uchar* buf) /*!< in/out: buffer for previous row in MySQL format */
|
||||
{
|
||||
ha_statistic_increment(&SSV::ha_read_prev_count);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_PREV, 0));
|
||||
}
|
||||
|
||||
@ -7416,7 +7402,6 @@ ha_innobase::index_first(
|
||||
int error;
|
||||
|
||||
DBUG_ENTER("index_first");
|
||||
ha_statistic_increment(&SSV::ha_read_first_count);
|
||||
|
||||
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
|
||||
|
||||
@ -7442,7 +7427,6 @@ ha_innobase::index_last(
|
||||
int error;
|
||||
|
||||
DBUG_ENTER("index_last");
|
||||
ha_statistic_increment(&SSV::ha_read_last_count);
|
||||
|
||||
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
|
||||
|
||||
@ -7512,7 +7496,6 @@ ha_innobase::rnd_next(
|
||||
int error;
|
||||
|
||||
DBUG_ENTER("rnd_next");
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
|
||||
|
||||
if (start_of_scan) {
|
||||
error = index_first(buf);
|
||||
@ -7546,8 +7529,6 @@ ha_innobase::rnd_pos(
|
||||
DBUG_ENTER("rnd_pos");
|
||||
DBUG_DUMP("key", pos, ref_length);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_count);
|
||||
|
||||
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
|
||||
|
||||
/* Note that we assume the length of the row reference is fixed
|
||||
|
@ -1226,10 +1226,6 @@ int ha_maria::close(void)
|
||||
|
||||
int ha_maria::write_row(uchar * buf)
|
||||
{
|
||||
/* If we have a timestamp column, update it to the current time */
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
/*
|
||||
If we have an auto_increment column and we are writing a changed row
|
||||
or a new row, then update the auto_increment value in the record.
|
||||
@ -2223,8 +2219,6 @@ bool ha_maria::is_crashed() const
|
||||
int ha_maria::update_row(const uchar * old_data, uchar * new_data)
|
||||
{
|
||||
CHECK_UNTIL_WE_FULLY_IMPLEMENTED_VERSIONING("UPDATE in WRITE CONCURRENT");
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
return maria_update(file, old_data, new_data);
|
||||
}
|
||||
|
||||
|
@ -810,10 +810,6 @@ int ha_myisam::close(void)
|
||||
|
||||
int ha_myisam::write_row(uchar *buf)
|
||||
{
|
||||
/* If we have a timestamp column, update it to the current time */
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
|
||||
/*
|
||||
If we have an auto_increment column and we are writing a changed row
|
||||
or a new row, then update the auto_increment value in the record.
|
||||
@ -1634,8 +1630,6 @@ bool ha_myisam::is_crashed() const
|
||||
|
||||
int ha_myisam::update_row(const uchar *old_data, uchar *new_data)
|
||||
{
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
return mi_update(file,old_data,new_data);
|
||||
}
|
||||
|
||||
|
@ -1073,13 +1073,10 @@ int ha_myisammrg::write_row(uchar * buf)
|
||||
{
|
||||
DBUG_ENTER("ha_myisammrg::write_row");
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_write_count);
|
||||
|
||||
if (file->merge_insert_method == MERGE_INSERT_DISABLED || !file->tables)
|
||||
DBUG_RETURN(HA_ERR_TABLE_READONLY);
|
||||
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
|
||||
table->timestamp_field->set_time();
|
||||
if (table->next_number_field && buf == table->record[0])
|
||||
{
|
||||
int error;
|
||||
@ -1092,16 +1089,12 @@ int ha_myisammrg::write_row(uchar * buf)
|
||||
int ha_myisammrg::update_row(const uchar * old_data, uchar * new_data)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_update_count);
|
||||
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
|
||||
table->timestamp_field->set_time();
|
||||
return myrg_update(file,old_data,new_data);
|
||||
}
|
||||
|
||||
int ha_myisammrg::delete_row(const uchar * buf)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_delete_count);
|
||||
return myrg_delete(file,buf);
|
||||
}
|
||||
|
||||
@ -1110,7 +1103,6 @@ int ha_myisammrg::index_read_map(uchar * buf, const uchar * key,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
int error=myrg_rkey(file,buf,active_index, key, keypart_map, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1121,7 +1113,6 @@ int ha_myisammrg::index_read_idx_map(uchar * buf, uint index, const uchar * key,
|
||||
enum ha_rkey_function find_flag)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
int error=myrg_rkey(file,buf,index, key, keypart_map, find_flag);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1131,7 +1122,6 @@ int ha_myisammrg::index_read_last_map(uchar *buf, const uchar *key,
|
||||
key_part_map keypart_map)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
int error=myrg_rkey(file,buf,active_index, key, keypart_map,
|
||||
HA_READ_PREFIX_LAST);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
@ -1141,7 +1131,6 @@ int ha_myisammrg::index_read_last_map(uchar *buf, const uchar *key,
|
||||
int ha_myisammrg::index_next(uchar * buf)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
int error=myrg_rnext(file,buf,active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1150,7 +1139,6 @@ int ha_myisammrg::index_next(uchar * buf)
|
||||
int ha_myisammrg::index_prev(uchar * buf)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_prev_count);
|
||||
int error=myrg_rprev(file,buf, active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1159,7 +1147,6 @@ int ha_myisammrg::index_prev(uchar * buf)
|
||||
int ha_myisammrg::index_first(uchar * buf)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_first_count);
|
||||
int error=myrg_rfirst(file, buf, active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1168,7 +1155,6 @@ int ha_myisammrg::index_first(uchar * buf)
|
||||
int ha_myisammrg::index_last(uchar * buf)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_last_count);
|
||||
int error=myrg_rlast(file, buf, active_index);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1180,7 +1166,6 @@ int ha_myisammrg::index_next_same(uchar * buf,
|
||||
{
|
||||
int error;
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
do
|
||||
{
|
||||
error= myrg_rnext_same(file,buf);
|
||||
@ -1200,7 +1185,6 @@ int ha_myisammrg::rnd_init(bool scan)
|
||||
int ha_myisammrg::rnd_next(uchar *buf)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
|
||||
int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR);
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
@ -1210,7 +1194,6 @@ int ha_myisammrg::rnd_next(uchar *buf)
|
||||
int ha_myisammrg::rnd_pos(uchar * buf, uchar *pos)
|
||||
{
|
||||
DBUG_ASSERT(this->file->children_attached);
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_count);
|
||||
int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length));
|
||||
table->status=error ? STATUS_NOT_FOUND: 0;
|
||||
return error;
|
||||
|
@ -5856,8 +5856,6 @@ ha_innobase::write_row(
|
||||
ut_error;
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_write_count);
|
||||
|
||||
if (share->ib_table->is_corrupt) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
@ -6279,8 +6277,6 @@ ha_innobase::update_row(
|
||||
}
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_update_count);
|
||||
|
||||
if (share->ib_table->is_corrupt) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
@ -6395,8 +6391,6 @@ ha_innobase::delete_row(
|
||||
|
||||
ut_a(prebuilt->trx == trx);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_delete_count);
|
||||
|
||||
if (share->ib_table->is_corrupt) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
@ -6671,8 +6665,6 @@ ha_innobase::index_read(
|
||||
ut_a(prebuilt->trx == thd_to_trx(user_thd));
|
||||
ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && share->ib_table->is_corrupt) {
|
||||
DBUG_RETURN(HA_ERR_CRASHED);
|
||||
}
|
||||
@ -7036,8 +7028,6 @@ ha_innobase::index_next(
|
||||
uchar* buf) /*!< in/out: buffer for next row in MySQL
|
||||
format */
|
||||
{
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_NEXT, 0));
|
||||
}
|
||||
|
||||
@ -7052,8 +7042,6 @@ ha_innobase::index_next_same(
|
||||
const uchar* key, /*!< in: key value */
|
||||
uint keylen) /*!< in: key value length */
|
||||
{
|
||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
|
||||
}
|
||||
|
||||
@ -7067,8 +7055,6 @@ ha_innobase::index_prev(
|
||||
/*====================*/
|
||||
uchar* buf) /*!< in/out: buffer for previous row in MySQL format */
|
||||
{
|
||||
ha_statistic_increment(&SSV::ha_read_prev_count);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_PREV, 0));
|
||||
}
|
||||
|
||||
@ -7085,7 +7071,6 @@ ha_innobase::index_first(
|
||||
int error;
|
||||
|
||||
DBUG_ENTER("index_first");
|
||||
ha_statistic_increment(&SSV::ha_read_first_count);
|
||||
|
||||
error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
|
||||
|
||||
@ -7111,7 +7096,6 @@ ha_innobase::index_last(
|
||||
int error;
|
||||
|
||||
DBUG_ENTER("index_last");
|
||||
ha_statistic_increment(&SSV::ha_read_last_count);
|
||||
|
||||
error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
|
||||
|
||||
@ -7181,7 +7165,6 @@ ha_innobase::rnd_next(
|
||||
int error;
|
||||
|
||||
DBUG_ENTER("rnd_next");
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
|
||||
|
||||
if (start_of_scan) {
|
||||
error = index_first(buf);
|
||||
@ -7216,8 +7199,6 @@ ha_innobase::rnd_pos(
|
||||
DBUG_ENTER("rnd_pos");
|
||||
DBUG_DUMP("key", pos, ref_length);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_rnd_count);
|
||||
|
||||
ut_a(prebuilt->trx == thd_to_trx(ha_thd()));
|
||||
|
||||
if (prebuilt->clust_index_was_generated) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user