Commit 9b765549 authored by marko's avatar marko

branches/zip: Merge revisions 1271:1322 from trunk.

parent d5028fac
......@@ -1977,9 +1977,12 @@ dict_foreign_find_index(
ulint n_cols, /* in: number of columns */
dict_index_t* types_idx, /* in: NULL or an index to whose types the
column types must match */
ibool check_charsets)
ibool check_charsets,
/* in: whether to check charsets.
only has an effect if types_idx != NULL */
ulint check_null)
/* in: nonzero if none of the columns must
be declared NOT NULL */
{
dict_index_t* index;
dict_field_t* field;
......@@ -2009,6 +2012,12 @@ dict_foreign_find_index(
break;
}
if (check_null
&& (field->col->prtype & DATA_NOT_NULL)) {
return(NULL);
}
if (types_idx && !cmp_cols_are_equal(
dict_index_get_nth_col(index, i),
dict_index_get_nth_col(types_idx,
......@@ -2125,7 +2134,7 @@ dict_foreign_add_to_cache(
ref_table,
(const char**) for_in_cache->referenced_col_names,
for_in_cache->n_fields, for_in_cache->foreign_index,
check_charsets);
check_charsets, FALSE);
if (index == NULL) {
dict_foreign_error_report(
......@@ -2157,7 +2166,10 @@ dict_foreign_add_to_cache(
for_table,
(const char**) for_in_cache->foreign_col_names,
for_in_cache->n_fields,
for_in_cache->referenced_index, check_charsets);
for_in_cache->referenced_index, check_charsets,
for_in_cache->type
& (DICT_FOREIGN_ON_DELETE_SET_NULL
| DICT_FOREIGN_ON_UPDATE_SET_NULL));
if (index == NULL) {
dict_foreign_error_report(
......@@ -2167,7 +2179,9 @@ dict_foreign_add_to_cache(
"the columns as the first columns,"
" or the data types in the\n"
"table do not match"
" the ones in the referenced table.");
" the ones in the referenced table\n"
"or one of the ON ... SET NULL columns"
" is declared NOT NULL.");
if (for_in_cache == foreign) {
if (added_to_referenced_list) {
......@@ -2973,7 +2987,8 @@ dict_create_foreign_constraints_low(
/* Try to find an index which contains the columns
as the first fields and in the right order */
index = dict_foreign_find_index(table, column_names, i, NULL, TRUE);
index = dict_foreign_find_index(table, column_names, i,
NULL, TRUE, FALSE);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
......@@ -3244,7 +3259,8 @@ dict_create_foreign_constraints_low(
if (referenced_table) {
index = dict_foreign_find_index(referenced_table,
column_names, i,
foreign->foreign_index, TRUE);
foreign->foreign_index,
TRUE, FALSE);
if (!index) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
......
......@@ -56,53 +56,6 @@ bool innodb_inited= 0;
*/
static handlerton *legacy_innodb_hton;
/*-----------------------------------------------------------------*/
/* These variables are used to implement (semi-)synchronous MySQL binlog
replication for InnoDB tables. */
pthread_cond_t innobase_repl_cond; /* Posix cond variable;
this variable is signaled
when enough binlog has been
sent to slave, so that a
waiting trx can return the
'ok' message to the client
for a commit */
pthread_mutex_t innobase_repl_cond_mutex; /* Posix cond variable mutex
that also protects the next
innobase_repl_... variables */
uint innobase_repl_state; /* 1 if synchronous replication
is switched on and is working
ok; else 0 */
uint innobase_repl_file_name_inited = 0; /* This is set to 1 when
innobase_repl_file_name
contains meaningful data */
char* innobase_repl_file_name; /* The binlog name up to which
we have sent some binlog to
the slave */
my_off_t innobase_repl_pos; /* The position in that file
up to which we have sent the
binlog to the slave */
uint innobase_repl_n_wait_threads = 0; /* This tells how many
transactions currently are
waiting for the binlog to be
sent to the client */
uint innobase_repl_wait_file_name_inited = 0; /* This is set to 1
when we know the 'smallest'
wait position */
char* innobase_repl_wait_file_name; /* NULL, or the 'smallest'
innobase_repl_file_name that
a transaction is waiting for */
my_off_t innobase_repl_wait_pos; /* The smallest position in
that file that a trx is
waiting for: the trx can
proceed and send an 'ok' to
the client when MySQL has sent
the binlog up to this position
to the slave */
/*-----------------------------------------------------------------*/
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
uses unsigned char; the header univ.i which we include next defines
'byte' as a macro which expands to 'unsigned char' */
......@@ -221,6 +174,139 @@ static handler *innobase_create_handler(handlerton *hton,
return new (mem_root) ha_innobase(hton, table);
}
/***********************************************************************
This function is used to prepare X/Open XA distributed transaction */
static
int
innobase_xa_prepare(
/*================*/
/* out: 0 or error number */
handlerton* hton,
THD* thd, /* in: handle to the MySQL thread of the user
whose XA transaction should be prepared */
bool all); /* in: TRUE - commit transaction
FALSE - the current SQL statement ended */
/***********************************************************************
This function is used to recover X/Open XA distributed transactions */
static
int
innobase_xa_recover(
/*================*/
/* out: number of prepared transactions
stored in xid_list */
handlerton* hton,
XID* xid_list, /* in/out: prepared transactions */
uint len); /* in: number of slots in xid_list */
/***********************************************************************
This function is used to commit one X/Open XA distributed transaction
which is in the prepared state */
static
int
innobase_commit_by_xid(
/*===================*/
/* out: 0 or error number */
handlerton* hton,
XID* xid); /* in: X/Open XA transaction identification */
/***********************************************************************
This function is used to rollback one X/Open XA distributed transaction
which is in the prepared state */
static
int
innobase_rollback_by_xid(
/*=====================*/
/* out: 0 or error number */
handlerton* hton,
XID *xid); /* in: X/Open XA transaction identification */
/***********************************************************************
Create a consistent view for a cursor based on current transaction
which is created if the corresponding MySQL thread still lacks one.
This consistent view is then used inside of MySQL when accessing records
using a cursor. */
static
void*
innobase_create_cursor_view(
/*========================*/
/* out: pointer to cursor view or NULL */
handlerton* hton, /* in: innobase hton */
THD* thd); /* in: user thread handle */
/***********************************************************************
Set the given consistent cursor view to a transaction which is created
if the corresponding MySQL thread still lacks one. If the given
consistent cursor view is NULL global read view of a transaction is
restored to a transaction read view. */
static
void
innobase_set_cursor_view(
/*=====================*/
handlerton* hton,
THD* thd, /* in: user thread handle */
void* curview);/* in: Consistent cursor view to be set */
/***********************************************************************
Close the given consistent cursor view of a transaction and restore
global read view to a transaction read view. Transaction is created if the
corresponding MySQL thread still lacks one. */
static
void
innobase_close_cursor_view(
/*=======================*/
handlerton* hton,
THD* thd, /* in: user thread handle */
void* curview);/* in: Consistent read view to be closed */
/*********************************************************************
Removes all tables in the named database inside InnoDB. */
static
void
innobase_drop_database(
/*===================*/
/* out: error number */
handlerton* hton, /* in: handlerton of Innodb */
char* path); /* in: database path; inside InnoDB the name
of the last directory in the path is used as
the database name: for example, in 'mysql/data/test'
the database name is 'test' */
/***********************************************************************
Closes an InnoDB database. */
static
int
innobase_end(handlerton *hton, ha_panic_function type);
/*********************************************************************
Creates an InnoDB transaction struct for the thd if it does not yet have one.
Starts a new InnoDB transaction if a transaction is not yet started. And
assigns a new snapshot for a consistent read if the transaction does not yet
have one. */
static
int
innobase_start_trx_and_assign_read_view(
/*====================================*/
/* out: 0 */
handlerton* hton, /* in: Innodb handlerton */
THD* thd); /* in: MySQL thread handle of the user for whom
the transaction should be committed */
/********************************************************************
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
the logs, and the name of this function should be innobase_checkpoint. */
static
bool
innobase_flush_logs(
/*================*/
/* out: TRUE if error */
handlerton* hton); /* in: InnoDB handlerton */
/****************************************************************************
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
Monitor to the client. */
static
bool
innodb_show_status(
/*===============*/
handlerton* hton, /* in: the innodb handlerton */
THD* thd, /* in: the MySQL query thread of the caller */
stat_print_fn *stat_print);
static
bool innobase_show_status(handlerton *hton, THD* thd,
stat_print_fn* stat_print,
enum ha_stat_type stat_type);
/*********************************************************************
Commits a transaction in an InnoDB database. */
......@@ -378,11 +464,24 @@ innobase_release_stat_resources(
}
}
/************************************************************************
Obtain the InnoDB transaction of a MySQL thread. */
inline
trx_t*&
thd_to_trx(
/*=======*/
/* out: reference to transaction pointer */
THD* thd, /* in: MySQL thread */
handlerton* hton) /* in: InnoDB handlerton */
{
return(*(trx_t**) thd_ha_data(thd, hton));
}
/************************************************************************
Call this function when mysqld passes control to the client. That is to
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
documentation, see handler.cc. */
static
int
innobase_release_temporary_latches(
/*===============================*/
......@@ -396,7 +495,7 @@ innobase_release_temporary_latches(
return 0;
}
trx = (trx_t*) thd->ha_data[hton->slot];
trx = thd_to_trx(thd, hton);
if (trx) {
innobase_release_stat_resources(trx);
......@@ -855,12 +954,10 @@ check_trx_exists(
handlerton* hton, /* in: handlerton for innodb */
THD* thd) /* in: user thread handle */
{
trx_t* trx;
trx_t*& trx = thd_to_trx(thd, hton);
ut_ad(thd == current_thd);
trx = (trx_t*) thd->ha_data[hton->slot];
if (trx == NULL) {
DBUG_ASSERT(thd != NULL);
trx = trx_allocate_for_mysql();
......@@ -872,8 +969,6 @@ check_trx_exists(
/* Update the info whether we should skip XA steps that eat
CPU time */
trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
thd->ha_data[hton->slot] = trx;
} else {
if (trx->magic_n != TRX_MAGIC_N) {
mem_analyze_corruption(trx);
......@@ -1324,7 +1419,7 @@ ha_innobase::init_table_handle_for_HANDLER(void)
/*************************************************************************
Opens an InnoDB database. */
static
int
innobase_init(void *p)
/*===============*/
......@@ -1591,7 +1686,7 @@ innobase_init(void *p)
/***********************************************************************
Closes an InnoDB database. */
static
int
innobase_end(handlerton *hton, ha_panic_function type)
/*==============*/
......@@ -1629,7 +1724,7 @@ innobase_end(handlerton *hton, ha_panic_function type)
/********************************************************************
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
the logs, and the name of this function should be innobase_checkpoint. */
static
bool
innobase_flush_logs(handlerton *hton)
/*=====================*/
......@@ -1665,7 +1760,7 @@ Creates an InnoDB transaction struct for the thd if it does not yet have one.
Starts a new InnoDB transaction if a transaction is not yet started. And
assigns a new snapshot for a consistent read if the transaction does not yet
have one. */
static
int
innobase_start_trx_and_assign_read_view(
/*====================================*/
......@@ -1879,7 +1974,7 @@ innobase_report_binlog_offset_and_commit(
#if 0
/***********************************************************************
This function stores the binlog offset and flushes logs. */
static
void
innobase_store_binlog_offset_and_flush_log(
/*=======================================*/
......@@ -1922,7 +2017,7 @@ innobase_commit_complete(
{
trx_t* trx;
trx = (trx_t*) thd->ha_data[hton->slot];
trx = thd_to_trx(thd, hton);
if (trx && trx->active_trans) {
......@@ -2146,7 +2241,7 @@ innobase_close_connection(
{
trx_t* trx;
trx = (trx_t*)thd->ha_data[hton->slot];
trx = thd_to_trx(thd, hton);
ut_a(trx);
......@@ -2333,7 +2428,7 @@ ha_innobase::open(
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
if (ib_table->ibd_file_missing && !thd->tablespace_op) {
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
ut_print_timestamp(stderr);
sql_print_error("MySQL is trying to open a table handle but "
"the .ibd file for\ntable %s does not exist.\n"
......@@ -3232,29 +3327,27 @@ ha_innobase::write_row(
longlong auto_inc;
longlong dummy;
ibool auto_inc_used= FALSE;
THD* thd = current_thd;
trx_t* trx = thd_to_trx(thd, ht);
DBUG_ENTER("ha_innobase::write_row");
if (prebuilt->trx !=
(trx_t*) current_thd->ha_data[ht->slot]) {
if (prebuilt->trx != trx) {
sql_print_error("The transaction object for the table handle is at "
"%p, but for the current thread it is at %p",
prebuilt->trx,
(trx_t*) current_thd->ha_data[ht->slot]);
prebuilt->trx, trx);
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
fputs("\n"
"InnoDB: Dump of 200 bytes around transaction.all: ",
"InnoDB: Dump of 200 bytes around ha_data: ",
stderr);
ut_print_buf(stderr,
((byte*)(&(current_thd->ha_data[ht->slot]))) - 100,
200);
ut_print_buf(stderr, ((const byte*) trx) - 100, 200);
putc('\n', stderr);
ut_error;
}
statistic_increment(current_thd->status_var.ha_write_count,
statistic_increment(thd->status_var.ha_write_count,
&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
......@@ -3620,11 +3713,11 @@ ha_innobase::update_row(
{
upd_t* uvect;
int error = 0;
trx_t* trx = thd_to_trx(current_thd, ht);
DBUG_ENTER("ha_innobase::update_row");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == trx);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
......@@ -3633,7 +3726,7 @@ ha_innobase::update_row(
prebuilt->sql_stat_start = TRUE;
last_query_id = user_thd->query_id;
innobase_release_stat_resources(prebuilt->trx);
innobase_release_stat_resources(trx);
}
if (prebuilt->upd_node) {
......@@ -3654,11 +3747,11 @@ ha_innobase::update_row(
assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
innodb_srv_conc_enter_innodb(prebuilt->trx);
innodb_srv_conc_enter_innodb(trx);
error = row_update_for_mysql((byte*) old_row, prebuilt);
innodb_srv_conc_exit_innodb(prebuilt->trx);
innodb_srv_conc_exit_innodb(trx);
error = convert_error_code_to_mysql(error, user_thd);
......@@ -3680,17 +3773,17 @@ ha_innobase::delete_row(
const mysql_byte* record) /* in: a row in MySQL format */
{
int error = 0;
trx_t* trx = thd_to_trx(current_thd, ht);
DBUG_ENTER("ha_innobase::delete_row");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == trx);
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
last_query_id = user_thd->query_id;
innobase_release_stat_resources(prebuilt->trx);
innobase_release_stat_resources(trx);
}
if (!prebuilt->upd_node) {
......@@ -3701,11 +3794,11 @@ ha_innobase::delete_row(
prebuilt->upd_node->is_delete = TRUE;
innodb_srv_conc_enter_innodb(prebuilt->trx);
innodb_srv_conc_enter_innodb(trx);
error = row_update_for_mysql((byte*) record, prebuilt);
innodb_srv_conc_exit_innodb(prebuilt->trx);
innodb_srv_conc_exit_innodb(trx);
error = convert_error_code_to_mysql(error, user_thd);
......@@ -3733,7 +3826,7 @@ ha_innobase::unlock_row(void)
sql_print_error("last_query_id is %lu != user_thd_query_id is "
"%lu", (ulong) last_query_id,
(ulong) user_thd->query_id);
mem_analyze_corruption((byte *) prebuilt->trx);
mem_analyze_corruption(prebuilt->trx);
ut_error;
}
......@@ -3775,8 +3868,7 @@ void
ha_innobase::try_semi_consistent_read(bool yes)
/*===========================================*/
{
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
/* Row read type is set to semi consistent read if this was
requested by the MySQL and either innodb_locks_unsafe_for_binlog
......@@ -3941,8 +4033,7 @@ ha_innobase::index_read(
DBUG_ENTER("index_read");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
statistic_increment(current_thd->status_var.ha_read_key_count,
&LOCK_status);
......@@ -4050,13 +4141,12 @@ ha_innobase::change_active_index(
InnoDB */
{
KEY* key=0;
statistic_increment(current_thd->status_var.ha_read_key_count,
&LOCK_status);
THD* thd = current_thd;
statistic_increment(thd->status_var.ha_read_key_count, &LOCK_status);
DBUG_ENTER("change_active_index");
ut_ad(user_thd == current_thd);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_ad(user_thd == thd);
ut_a(prebuilt->trx == thd_to_trx(thd, ht));
active_index = keynr;
......@@ -4144,8 +4234,7 @@ ha_innobase::general_fetch(
DBUG_ENTER("general_fetch");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
innodb_srv_conc_enter_innodb(prebuilt->trx);
......@@ -4377,8 +4466,7 @@ ha_innobase::rnd_pos(
statistic_increment(current_thd->status_var.ha_read_rnd_count,
&LOCK_status);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
......@@ -4426,8 +4514,7 @@ ha_innobase::position(
{
uint len;
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
if (prebuilt->clust_index_was_generated) {
/* No primary key was defined for the table and we
......@@ -4931,9 +5018,9 @@ ha_innobase::discard_or_import_tablespace(
DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx);
ut_a(prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
dict_table = prebuilt->table;
trx = prebuilt->trx;
......@@ -5074,7 +5161,7 @@ ha_innobase::delete_table(
/*********************************************************************
Removes all tables in the named database inside InnoDB. */
static
void
innobase_drop_database(
/*===================*/
......@@ -5259,8 +5346,7 @@ ha_innobase::records_in_range(
DBUG_ENTER("records_in_range");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
prebuilt->trx->op_info = (char*)"estimating records in index range";
......@@ -5690,8 +5776,7 @@ ha_innobase::check(
ulint ret;
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
if (prebuilt->mysql_template == NULL) {
/* Build the template; we will use a dummy template
......@@ -5988,8 +6073,7 @@ ha_innobase::can_switch_engines(void)
DBUG_ENTER("ha_innobase::can_switch_engines");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->ha_data[ht->slot]);
ut_a(prebuilt->trx == thd_to_trx(current_thd, ht));
prebuilt->trx->op_info =
"determining if there are foreign key constraints";
......@@ -6097,7 +6181,7 @@ on that table.
MySQL-5.0 also calls this before each statement in an execution of a stored
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
locks all tables involved in a stored procedure with full explicit table
locks (thd->in_lock_tables is true in ::store_lock()) before executing the
locks (thd_in_lock_tables(thd) holds in store_lock()) before executing the
procedure. */
int
......@@ -6270,16 +6354,16 @@ ha_innobase::external_lock(
VERY easily deadlocks.
We do not set InnoDB table locks if user has not explicitly
requested a table lock. Note that thd->in_lock_tables
can be TRUE on some cases e.g. at the start of a stored
requested a table lock. Note that thd_in_lock_tables(thd)
can hold in some cases, e.g., at the start of a stored
procedure call (SQLCOM_CALL). */
if (prebuilt->select_lock_type != LOCK_NONE) {
if (thd->in_lock_tables &&
thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) {
if (thd->lex->sql_command == SQLCOM_LOCK_TABLES
&& thd->variables.innodb_table_locks
&& (thd->options & OPTION_NOT_AUTOCOMMIT)
&& thd_in_lock_tables(thd)) {
ulint error = row_lock_table_for_mysql(
prebuilt, NULL, 0);
......@@ -6357,7 +6441,8 @@ ha_innobase::transactional_table_lock(
update_thd(thd);
if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
if (prebuilt->table->ibd_file_missing
&& !thd_tablespace_op(current_thd)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB error:\n"
"MySQL is trying to use a table handle but the .ibd file for\n"
......@@ -6402,7 +6487,7 @@ ha_innobase::transactional_table_lock(
trx->active_trans = 1;
}
if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
if (thd->variables.innodb_table_locks && thd_in_lock_tables(thd)) {
ulint error = DB_SUCCESS;
error = row_lock_table_for_mysql(prebuilt, NULL, 0);
......@@ -6442,7 +6527,7 @@ innodb_export_status()
/****************************************************************************
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
Monitor to the client. */
static
bool
innodb_show_status(
/*===============*/
......@@ -6632,6 +6717,7 @@ innodb_mutex_show_status(
DBUG_RETURN(FALSE);
}
static
bool innobase_show_status(handlerton *hton, THD* thd,
stat_print_fn* stat_print,
enum ha_stat_type stat_type)
......@@ -6755,14 +6841,16 @@ ha_innobase::store_lock(
thd->variables.tx_isolation);
}
const bool in_lock_tables = thd_in_lock_tables(thd);
if (thd->lex->sql_command == SQLCOM_DROP_TABLE) {
/* MySQL calls this function in DROP TABLE though this table
handle may belong to another thd that is running a query. Let
us in that case skip any changes to the prebuilt struct. */
} else if ((lock_type == TL_READ && thd->in_lock_tables) ||
(lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
} else if ((lock_type == TL_READ && in_lock_tables) ||
(lock_type == TL_READ_HIGH_PRIORITY && in_lock_tables) ||
lock_type == TL_READ_WITH_SHARED_LOCKS ||
lock_type == TL_READ_NO_INSERT ||
(thd->lex->sql_command != SQLCOM_SELECT
......@@ -6833,7 +6921,7 @@ ha_innobase::store_lock(
/* Starting from 5.0.7, we weaken also the table locks
set at the start of a MySQL stored procedure call, just like
we weaken the locks set at the start of an SQL statement.
MySQL does set thd->in_lock_tables TRUE there, but in reality
MySQL does set in_lock_tables TRUE there, but in reality
we do not need table locks to make the execution of a
single transaction stored procedure call deterministic
(if it does not use a consistent read). */
......@@ -6861,14 +6949,14 @@ ha_innobase::store_lock(
We especially allow multiple writers if MySQL is at the
start of a stored procedure call (SQLCOM_CALL) or a
stored function call (MySQL does have thd->in_lock_tables
stored function call (MySQL does have in_lock_tables
TRUE there). */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
&& lock_type <= TL_WRITE)
&& !(thd->in_lock_tables
&& !(in_lock_tables
&& thd->lex->sql_command == SQLCOM_LOCK_TABLES)
&& !thd->tablespace_op
&& !thd_tablespace_op(thd)
&& thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_OPTIMIZE
......@@ -6895,7 +6983,7 @@ ha_innobase::store_lock(
We especially allow concurrent inserts if MySQL is at the
start of a stored procedure call (SQLCOM_CALL)
(MySQL does have thd->in_lock_tables TRUE there). */
(MySQL does have in_lock_tables TRUE there). */
if (lock_type == TL_READ_NO_INSERT
&& thd->lex->sql_command != SQLCOM_LOCK_TABLES) {
......@@ -7337,7 +7425,7 @@ innobase_query_is_update(void)
/***********************************************************************
This function is used to prepare X/Open XA distributed transaction */
static
int
innobase_xa_prepare(
/*================*/
......@@ -7433,7 +7521,7 @@ innobase_xa_prepare(
/***********************************************************************
This function is used to recover X/Open XA distributed transactions */
static
int
innobase_xa_recover(
/*================*/
......@@ -7454,7 +7542,7 @@ innobase_xa_recover(
/***********************************************************************
This function is used to commit one X/Open XA distributed transaction
which is in the prepared state */
static
int
innobase_commit_by_xid(
/*===================*/
......@@ -7478,7 +7566,7 @@ innobase_commit_by_xid(
/***********************************************************************
This function is used to rollback one X/Open XA distributed transaction
which is in the prepared state */
static
int
innobase_rollback_by_xid(
/*=====================*/
......@@ -7502,9 +7590,10 @@ Create a consistent view for a cursor based on current transaction
which is created if the corresponding MySQL thread still lacks one.
This consistent view is then used inside of MySQL when accessing records
using a cursor. */
static
void*
innobase_create_cursor_view(
/*========================*/
/* out: pointer to cursor view or NULL */
handlerton *hton, /* in: innobase hton */
THD* thd) /* in: user thread handle */
......@@ -7517,9 +7606,10 @@ innobase_create_cursor_view(
Close the given consistent cursor view of a transaction and restore
global read view to a transaction read view. Transaction is created if the
corresponding MySQL thread still lacks one. */
static
void
innobase_close_cursor_view(
/*=======================*/
handlerton *hton,
THD* thd, /* in: user thread handle */
void* curview)/* in: Consistent read view to be closed */
......@@ -7533,7 +7623,7 @@ Set the given consistent cursor view to a transaction which is created
if the corresponding MySQL thread still lacks one. If the given
consistent cursor view is NULL global read view of a transaction is
restored to a transaction read view. */
static
void
innobase_set_cursor_view(
/*=====================*/
......
......@@ -238,11 +238,6 @@ extern ulong srv_commit_concurrency;
extern ulong srv_flush_log_at_trx_commit;
}
int innobase_init(void);
int innobase_end(handlerton *hton, ha_panic_function type);
bool innobase_flush_logs(handlerton *hton);
uint innobase_get_free_space(void);
/*
don't delete it - it may be re-enabled later
as an optimization for the most common case InnoDB+binlog
......@@ -256,93 +251,3 @@ int innobase_report_binlog_offset_and_commit(
int innobase_commit_complete(void* trx_handle);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
#endif
void innobase_drop_database(handlerton *hton, char *path);
bool innobase_show_status(handlerton *hton, THD* thd, stat_print_fn*, enum ha_stat_type);
int innobase_release_temporary_latches(handlerton *hton, THD *thd);
void innobase_store_binlog_offset_and_flush_log(handlerton *hton, char *binlog_name,longlong offset);
int innobase_start_trx_and_assign_read_view(handlerton *hton, THD* thd);
/***********************************************************************
This function is used to prepare X/Open XA distributed transaction */
int innobase_xa_prepare(
/*====================*/
/* out: 0 or error number */
handlerton *hton, /* in: innobase hton */
THD* thd, /* in: handle to the MySQL thread of the user
whose XA transaction should be prepared */
bool all); /* in: TRUE - commit transaction
FALSE - the current SQL statement ended */
/***********************************************************************
This function is used to recover X/Open XA distributed transactions */
int innobase_xa_recover(
/*====================*/
/* out: number of prepared transactions
stored in xid_list */
handlerton *hton, /* in: innobase hton */
XID* xid_list, /* in/out: prepared transactions */
uint len); /* in: number of slots in xid_list */
/***********************************************************************
This function is used to commit one X/Open XA distributed transaction
which is in the prepared state */
int innobase_commit_by_xid(
/*=======================*/
/* out: 0 or error number */
handlerton *hton, /* in: innobase hton */
XID* xid); /* in : X/Open XA Transaction Identification */
/***********************************************************************
This function is used to rollback one X/Open XA distributed transaction
which is in the prepared state */
int innobase_rollback_by_xid(
/* out: 0 or error number */
handlerton *hton, /* in: innobase hton */
XID *xid); /* in : X/Open XA Transaction Identification */
/***********************************************************************
Create a consistent view for a cursor based on current transaction
which is created if the corresponding MySQL thread still lacks one.
This consistent view is then used inside of MySQL when accessing records
using a cursor. */
void*
innobase_create_cursor_view(
/* out: Pointer to cursor view or NULL */
handlerton *hton, /* in: innobase hton */
THD* thd); /* in: user thread handle */
/***********************************************************************
Close the given consistent cursor view of a transaction and restore
global read view to a transaction read view. Transaction is created if the
corresponding MySQL thread still lacks one. */
void
innobase_close_cursor_view(
/*=======================*/
handlerton *hton, /* in: innobase hton */
THD* thd, /* in: user thread handle */
void* curview); /* in: Consistent read view to be closed */
/***********************************************************************
Set the given consistent cursor view to a transaction which is created
if the corresponding MySQL thread still lacks one. If the given
consistent cursor view is NULL global read view of a transaction is
restored to a transaction read view. */
void
innobase_set_cursor_view(
/*=====================*/
handlerton *hton, /* in: innobase hton */
THD* thd, /* in: user thread handle */
void* curview); /* in: Consistent read view to be set */
......@@ -6,6 +6,16 @@ Mutex, the basic synchronization primitive
Created 9/5/1995 Heikki Tuuri
*******************************************************/
#if defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
/* %z0: Use the size of operand %0 which in our case is *m to determine
instruction size, it should end up as xchgl. "1" in the input constraint,
says that "in" has to go in the same place as "out".*/
#define TAS(m, in, out) \
asm volatile ("xchg%z0 %2, %0" \
: "=g" (*(m)), "=r" (out) \
: "1" (in)) /* Note: "1" here refers to "=r" (out) */
#endif
/**********************************************************************
Sets the waiters field in a mutex. */
......@@ -89,20 +99,10 @@ mutex_test_and_set(
return(res);
#elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
ulint* lw;
ulint res;
lw = &(mutex->lock_word);
/* In assembly we use the so-called AT & T syntax where
the order of operands is inverted compared to the ordinary Intel
syntax. The 'l' after the mnemonics denotes a 32-bit operation.
The line after the code tells which values come out of the asm
code, and the second line tells the input to the asm code. */
TAS(&mutex->lock_word, 1, res);
asm volatile("movl $1, %%eax; xchgl (%%ecx), %%eax" :
"=eax" (res), "=m" (*lw) :
"ecx" (lw));
return(res);
#else
ibool ret;
......@@ -141,20 +141,9 @@ mutex_reset_lock_word(
__asm MOV ECX, lw
__asm XCHG EDX, DWORD PTR [ECX]
#elif defined(not_defined) && defined(__GNUC__) && defined(UNIV_INTEL_X86)
ulint* lw;
lw = &(mutex->lock_word);
/* In assembly we use the so-called AT & T syntax where
the order of operands is inverted compared to the ordinary Intel
syntax. The 'l' after the mnemonics denotes a 32-bit operation. */
ulint res;
asm volatile("movl $0, %%eax; xchgl (%%ecx), %%eax" :
"=m" (*lw) :
"ecx" (lw) :
"eax"); /* gcc does not seem to understand
that our asm code resets eax: tell it
explicitly that after the third ':' */
TAS(&mutex->lock_word, 0, res);
#else
mutex->lock_word = 0;
......
......@@ -43,12 +43,21 @@ if we are compiling on Windows. */
# undef VERSION
/* Include the header file generated by GNU autoconf */
# ifndef __WIN__
# include "config.h"
# endif
# ifdef HAVE_SCHED_H
# include <sched.h>
# endif
/* When compiling for Itanium IA64, undefine the flag below to prevent use
of the 32-bit x86 assembler in mutex operations. */
# if defined(__WIN__) && !defined(WIN64) && !defined(_WIN64)
# define UNIV_CAN_USE_X86_ASSEMBLER
# endif
/* We only try to do explicit inlining of functions with gcc and
Microsoft Visual C++ */
......
......@@ -3447,8 +3447,6 @@ SELECT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
a
1
drop table t2, t1;
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
ERROR HY000: The used table type doesn't support SPATIAL indexes
CREATE TABLE t1 ( a int ) ENGINE=innodb;
BEGIN;
INSERT INTO t1 VALUES (1);
......@@ -3473,3 +3471,12 @@ t2 CREATE TABLE `t2` (
CONSTRAINT `t2_t1` FOREIGN KEY (`id`) REFERENCES `t1` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2, t1;
CREATE TABLE t1 (a INT, INDEX(a)) ENGINE=InnoDB;
CREATE TABLE t2 (a INT, INDEX(a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
ALTER TABLE t2 MODIFY a INT NOT NULL;
ERROR HY000: Error on rename of '#sql-temporary' to './test/t2' (errno: 150)
DELETE FROM t1;
DROP TABLE t2,t1;
......@@ -52,7 +52,7 @@ INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),
update t1 set parent_id=parent_id+100;
select * from t1 where parent_id=102;
update t1 set id=id+1000;
-- error 1062,1022
-- error ER_DUP_ENTRY_WITH_KEY_NAME,1022
update t1 set id=1024 where id=1009;
select * from t1;
update ignore t1 set id=id+1; # This will change all rows
......@@ -133,13 +133,13 @@ commit;
select n, "after commit" from t1;
commit;
insert into t1 values (5);
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 values (4);
commit;
select n, "after commit" from t1;
set autocommit=1;
insert into t1 values (6);
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 values (4);
select n from t1;
set autocommit=0;
......@@ -213,7 +213,7 @@ drop table t1;
CREATE TABLE t1 (id char(8) not null primary key, val int not null) engine=innodb;
insert into t1 values ('pippo', 12);
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 values ('pippo', 12); # Gives error
delete from t1;
delete from t1 where id = 'pippo';
......@@ -341,9 +341,9 @@ CREATE TABLE t1 (
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 (ggid,passwd) values ('test2','this will fail');
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 (ggid,id) values ('this will fail',1);
select * from t1 where ggid='test1';
......@@ -352,7 +352,7 @@ select * from t1 where id=2;
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
update t1 set id=100,ggid='test2' where id=1;
select * from t1;
select * from t1 where id=1;
......@@ -523,7 +523,7 @@ drop table t1;
create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) engine=innodb;
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
LOCK TABLES t1 WRITE;
--error 1062
--error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
select id from t1;
select id from t1;
......@@ -534,7 +534,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
LOCK TABLES t1 WRITE;
begin;
--error 1062
--error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
select id from t1;
insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D');
......@@ -1407,7 +1407,7 @@ create table t1 (rowid int not null auto_increment, val int not null,primary
key (rowid), unique(val)) engine=innodb;
replace into t1 (val) values ('1'),('2');
replace into t1 (val) values ('1'),('2');
--error 1062
--error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 (val) values ('1'),('2');
select * from t1;
drop table t1;
......@@ -1420,7 +1420,7 @@ create table t1 (a int not null auto_increment primary key, val int) engine=Inno
insert into t1 (val) values (1);
update t1 set a=2 where a=1;
# We should get the following error because InnoDB does not update the counter
--error 1062
--error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t1 (val) values (1);
select * from t1;
drop table t1;
......@@ -1876,13 +1876,13 @@ create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb;
create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb;
insert into t1 values (0x41),(0x4120),(0x4100);
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t2 values (0x41),(0x4120),(0x4100);
insert into t2 values (0x41),(0x4120);
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t3 values (0x41),(0x4120),(0x4100);
insert into t3 values (0x41),(0x4100);
-- error 1062
-- error ER_DUP_ENTRY_WITH_KEY_NAME
insert into t4 values (0x41),(0x4120),(0x4100);
insert into t4 values (0x41),(0x4100);
select hex(s1) from t1;
......@@ -2487,12 +2487,6 @@ SELECT p0.a FROM t2 p0 WHERE BINARY p0.b = 'customer_over';
drop table t2, t1;
#
# Bug #15680 (SPATIAL key in innodb)
#
--error ER_TABLE_CANT_HANDLE_SPKEYS
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
#
# Test optimize on table with open transaction
#
......@@ -2519,6 +2513,22 @@ DELETE CASCADE ON UPDATE CASCADE;
SHOW CREATE TABLE t2;
DROP TABLE t2, t1;
#
# Bug #25927: Prevent ALTER TABLE ... MODIFY ... NOT NULL on columns
# for which there is a foreign key constraint ON ... SET NULL.
#
CREATE TABLE t1 (a INT, INDEX(a)) ENGINE=InnoDB;
CREATE TABLE t2 (a INT, INDEX(a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1);
INSERT INTO t2 VALUES (1);
ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1 (a) ON DELETE SET NULL;
--replace_regex /'\.\/test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
--error 1025
ALTER TABLE t2 MODIFY a INT NOT NULL;
DELETE FROM t1;
DROP TABLE t2,t1;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
......
......@@ -460,3 +460,5 @@ ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
insert into t1 (fl) values (pointfromtext('point(1,1)'));
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1;
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
ERROR HY000: The used table type doesn't support SPATIAL indexes
--source include/have_innodb.inc
SET storage_engine=innodb;
--source include/gis_generic.inc
#
# Bug #15680 (SPATIAL key in innodb)
#
--error ER_TABLE_CANT_HANDLE_SPKEYS
create table t1 (g geometry not null, spatial gk(g)) engine=innodb;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment