mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 06:44:16 +01:00
Merge mkindahl@bk-internal.mysql.com:/home/bk/mysql-5.1-new-rpl
into mysql.com:/home/bkroot/mysql-5.1-new-rpl
This commit is contained in:
commit
3666d79d35
78 changed files with 2440 additions and 1247 deletions
|
@ -1378,9 +1378,9 @@ insert into `t2`values ( 1 ) ;
|
|||
create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb;
|
||||
insert into `t3`values ( 1 ) ;
|
||||
delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
|
||||
update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`))
|
||||
update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
|
||||
ERROR 42S22: Unknown column 't1.id' in 'where clause'
|
||||
drop table t3,t2,t1;
|
||||
|
@ -1392,7 +1392,7 @@ foreign key(pid) references t1(id) on delete cascade) engine=innodb;
|
|||
insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6),
|
||||
(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14);
|
||||
delete from t1 where id=0;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `t1` (`id`) ON DELETE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `t1` (`id`) ON DELETE CASCADE)
|
||||
delete from t1 where id=15;
|
||||
delete from t1 where id=0;
|
||||
drop table t1;
|
||||
|
@ -2633,18 +2633,18 @@ v INT,
|
|||
CONSTRAINT c1 FOREIGN KEY (v) REFERENCES t1(id)
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO t2 VALUES(2);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
|
||||
INSERT INTO t1 VALUES(1);
|
||||
INSERT INTO t2 VALUES(1);
|
||||
DELETE FROM t1 WHERE id = 1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
|
||||
DROP TABLE t1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
|
||||
SET FOREIGN_KEY_CHECKS=0;
|
||||
DROP TABLE t1;
|
||||
SET FOREIGN_KEY_CHECKS=1;
|
||||
INSERT INTO t2 VALUES(3);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`))
|
||||
DROP TABLE t2;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (1),(2);
|
||||
|
@ -2922,23 +2922,23 @@ create table t4(a int primary key,constraint foreign key(a)references t3(a)) row
|
|||
insert into t1 values(1);
|
||||
insert into t3 values(1);
|
||||
insert into t2 values(2);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
insert into t4 values(2);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
insert into t2 values(1);
|
||||
insert into t4 values(1);
|
||||
update t1 set a=2;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
update t2 set a=2;
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
update t3 set a=2;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
update t4 set a=2;
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
truncate t1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`))
|
||||
truncate t3;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`))
|
||||
truncate t2;
|
||||
truncate t4;
|
||||
truncate t1;
|
||||
|
@ -2993,7 +2993,7 @@ create table t1 (a int primary key,s1 varbinary(3) not null unique) engine=innod
|
|||
create table t2 (s1 binary(2) not null, constraint c foreign key(s1) references t1(s1) on update cascade) engine=innodb;
|
||||
insert into t1 values(1,0x4100),(2,0x41),(3,0x4120),(4,0x42);
|
||||
insert into t2 values(0x42);
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
insert into t2 values(0x41);
|
||||
select hex(s1) from t2;
|
||||
hex(s1)
|
||||
|
@ -3003,11 +3003,11 @@ select hex(s1) from t2;
|
|||
hex(s1)
|
||||
4100
|
||||
update t1 set s1=0x12 where a=1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
update t1 set s1=0x12345678 where a=1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
update t1 set s1=0x123457 where a=1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
update t1 set s1=0x1220 where a=1;
|
||||
select hex(s1) from t2;
|
||||
hex(s1)
|
||||
|
@ -3021,11 +3021,11 @@ select hex(s1) from t2;
|
|||
hex(s1)
|
||||
4200
|
||||
delete from t1 where a=1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
delete from t1 where a=2;
|
||||
update t2 set s1=0x4120;
|
||||
delete from t1;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
delete from t1 where a!=3;
|
||||
select a,hex(s1) from t1;
|
||||
a hex(s1)
|
||||
|
@ -3051,7 +3051,7 @@ hex(s1)
|
|||
12
|
||||
delete from t1 where a=1;
|
||||
delete from t1 where a=2;
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE)
|
||||
select a,hex(s1) from t1;
|
||||
a hex(s1)
|
||||
2 12
|
||||
|
|
|
@ -2510,3 +2510,16 @@ BEGIN;
|
|||
INSERT INTO t1 VALUES (1);
|
||||
OPTIMIZE TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
#######################################################################
|
||||
# #
|
||||
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
|
||||
# These files are to be modified ONLY BY INNOBASE guys. #
|
||||
# #
|
||||
# Use innodb_mysql.[test|result] files instead. #
|
||||
# #
|
||||
# If nevertheless you need to make some changes here, please, forward #
|
||||
# your commit message To: dev@innodb.com Cc: dev-innodb@mysql.com #
|
||||
# (otherwise your changes may be erased). #
|
||||
# #
|
||||
#######################################################################
|
||||
|
|
201
sql/ha_innodb.cc
201
sql/ha_innodb.cc
|
@ -134,6 +134,7 @@ extern "C" {
|
|||
#include "../storage/innobase/include/fil0fil.h"
|
||||
#include "../storage/innobase/include/trx0xa.h"
|
||||
#include "../storage/innobase/include/thr0loc.h"
|
||||
#include "../storage/innobase/include/ha_prototypes.h"
|
||||
}
|
||||
|
||||
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
|
||||
|
@ -705,6 +706,61 @@ innobase_get_cset_width(
|
|||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Converts an identifier to a table name.
|
||||
|
||||
NOTE that the exact prototype of this function has to be in
|
||||
/innobase/dict/dict0dict.c! */
|
||||
extern "C"
|
||||
void
|
||||
innobase_convert_from_table_id(
|
||||
/*===========================*/
|
||||
char* to, /* out: converted identifier */
|
||||
const char* from, /* in: identifier to convert */
|
||||
ulint len) /* in: length of 'to', in bytes */
|
||||
{
|
||||
uint errors;
|
||||
|
||||
strconvert(current_thd->charset(), from,
|
||||
&my_charset_filename, to, len, &errors);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Converts an identifier to UTF-8.
|
||||
|
||||
NOTE that the exact prototype of this function has to be in
|
||||
/innobase/dict/dict0dict.c! */
|
||||
extern "C"
|
||||
void
|
||||
innobase_convert_from_id(
|
||||
/*=====================*/
|
||||
char* to, /* out: converted identifier */
|
||||
const char* from, /* in: identifier to convert */
|
||||
ulint len) /* in: length of 'to', in bytes */
|
||||
{
|
||||
uint errors;
|
||||
|
||||
strconvert(current_thd->charset(), from,
|
||||
system_charset_info, to, len, &errors);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Removes the filename encoding of a table or database name.
|
||||
|
||||
NOTE that the exact prototype of this function has to be in
|
||||
/innobase/dict/dict0dict.c! */
|
||||
extern "C"
|
||||
void
|
||||
innobase_convert_from_filename(
|
||||
/*===========================*/
|
||||
char* s) /* in: identifier; out: decoded identifier */
|
||||
{
|
||||
uint errors;
|
||||
|
||||
strconvert(&my_charset_filename, s,
|
||||
system_charset_info, s, strlen(s), &errors);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Compares NUL-terminated UTF-8 strings case insensitively.
|
||||
|
||||
|
@ -735,6 +791,21 @@ innobase_casedn_str(
|
|||
my_casedn_str(system_charset_info, a);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Determines the connection character set.
|
||||
|
||||
NOTE that the exact prototype of this function has to be in
|
||||
/innobase/dict/dict0dict.c! */
|
||||
extern "C"
|
||||
struct charset_info_st*
|
||||
innobase_get_charset(
|
||||
/*=================*/
|
||||
/* out: connection character set */
|
||||
void* mysql_thd) /* in: MySQL thread handle */
|
||||
{
|
||||
return(((THD*) mysql_thd)->charset());
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Creates a temporary file. */
|
||||
extern "C"
|
||||
|
@ -780,6 +851,25 @@ innobase_mysql_tmpfile(void)
|
|||
return(fd2);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Wrapper around MySQL's copy_and_convert function, see it for
|
||||
documentation. */
|
||||
extern "C"
|
||||
ulint
|
||||
innobase_convert_string(
|
||||
/*====================*/
|
||||
void* to,
|
||||
ulint to_length,
|
||||
CHARSET_INFO* to_cs,
|
||||
const void* from,
|
||||
ulint from_length,
|
||||
CHARSET_INFO* from_cs,
|
||||
uint* errors)
|
||||
{
|
||||
return(copy_and_convert((char*)to, to_length, to_cs,
|
||||
(const char*)from, from_length, from_cs, errors));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Gets the InnoDB transaction handle for a MySQL handler object, creates
|
||||
an InnoDB transaction struct if the corresponding MySQL thread struct still
|
||||
|
@ -1115,23 +1205,69 @@ innobase_invalidate_query_cache(
|
|||
}
|
||||
|
||||
/*********************************************************************
|
||||
Get the quote character to be used in SQL identifiers.
|
||||
Display an SQL identifier.
|
||||
This definition must match the one in innobase/ut/ut0ut.c! */
|
||||
extern "C"
|
||||
int
|
||||
mysql_get_identifier_quote_char(
|
||||
/*============================*/
|
||||
/* out: quote character to be
|
||||
used in SQL identifiers; EOF if none */
|
||||
void
|
||||
innobase_print_identifier(
|
||||
/*======================*/
|
||||
FILE* f, /* in: output stream */
|
||||
trx_t* trx, /* in: transaction */
|
||||
ibool table_id,/* in: TRUE=decode table name */
|
||||
const char* name, /* in: name to print */
|
||||
ulint namelen)/* in: length of name */
|
||||
{
|
||||
if (!trx || !trx->mysql_thd) {
|
||||
return(EOF);
|
||||
const char* s = name;
|
||||
char* qname = NULL;
|
||||
int q;
|
||||
|
||||
if (table_id) {
|
||||
/* Decode the table name. The filename_to_tablename()
|
||||
function expects a NUL-terminated string. The input and
|
||||
output strings buffers must not be shared. The function
|
||||
only produces more output when the name contains other
|
||||
characters than [0-9A-Z_a-z]. */
|
||||
char* temp_name = my_malloc(namelen + 1, MYF(MY_WME));
|
||||
uint qnamelen = namelen
|
||||
+ (1 + sizeof srv_mysql50_table_name_prefix);
|
||||
|
||||
if (temp_name) {
|
||||
qname = my_malloc(qnamelen, MYF(MY_WME));
|
||||
if (qname) {
|
||||
memcpy(temp_name, name, namelen);
|
||||
temp_name[namelen] = 0;
|
||||
s = qname;
|
||||
namelen = filename_to_tablename(temp_name,
|
||||
qname, qnamelen);
|
||||
}
|
||||
return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
|
||||
name, (int) namelen));
|
||||
my_free(temp_name, MYF(0));
|
||||
}
|
||||
}
|
||||
|
||||
if (!trx || !trx->mysql_thd) {
|
||||
|
||||
q = '"';
|
||||
} else {
|
||||
q = get_quote_char_for_identifier((THD*) trx->mysql_thd,
|
||||
s, (int) namelen);
|
||||
}
|
||||
|
||||
if (q == EOF) {
|
||||
fwrite(s, 1, namelen, f);
|
||||
} else {
|
||||
const char* e = s + namelen;
|
||||
putc(q, f);
|
||||
while (s < e) {
|
||||
int c = *s++;
|
||||
if (c == q) {
|
||||
putc(c, f);
|
||||
}
|
||||
putc(c, f);
|
||||
}
|
||||
putc(q, f);
|
||||
}
|
||||
|
||||
my_free(qname, MYF(MY_ALLOW_ZERO_PTR));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -1247,6 +1383,24 @@ innobase_init(void)
|
|||
|
||||
ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
static const char test_filename[] = "-@";
|
||||
char test_tablename[sizeof test_filename
|
||||
+ sizeof srv_mysql50_table_name_prefix];
|
||||
if ((sizeof test_tablename) - 1
|
||||
!= filename_to_tablename(test_filename, test_tablename,
|
||||
sizeof test_tablename)
|
||||
|| strncmp(test_tablename,
|
||||
srv_mysql50_table_name_prefix,
|
||||
sizeof srv_mysql50_table_name_prefix)
|
||||
|| strcmp(test_tablename
|
||||
+ sizeof srv_mysql50_table_name_prefix,
|
||||
test_filename)) {
|
||||
sql_print_error("tablename encoding has been changed");
|
||||
goto error;
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* Check that values don't overflow on 32-bit systems. */
|
||||
if (sizeof(ulint) == 4) {
|
||||
if (innobase_buffer_pool_size > UINT_MAX32) {
|
||||
|
@ -2215,8 +2369,7 @@ ha_innobase::open(
|
|||
|
||||
/* Get pointer to a table object in InnoDB dictionary cache */
|
||||
|
||||
ib_table = dict_table_get_and_increment_handle_count(
|
||||
norm_name, NULL);
|
||||
ib_table = dict_table_get_and_increment_handle_count(norm_name);
|
||||
|
||||
if (NULL == ib_table) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
@ -4132,6 +4285,9 @@ ha_innobase::index_prev(
|
|||
mysql_byte* buf) /* in/out: buffer for previous row in MySQL
|
||||
format */
|
||||
{
|
||||
statistic_increment(current_thd->status_var.ha_read_prev_count,
|
||||
&LOCK_status);
|
||||
|
||||
return(general_fetch(buf, ROW_SEL_PREV, 0));
|
||||
}
|
||||
|
||||
|
@ -4668,7 +4824,7 @@ ha_innobase::create(
|
|||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
parent_trx = check_trx_exists(current_thd);
|
||||
parent_trx = check_trx_exists(thd);
|
||||
|
||||
/* In case MySQL calls this in the middle of a SELECT query, release
|
||||
possible adaptive hash latch to avoid deadlocks of threads */
|
||||
|
@ -4764,20 +4920,9 @@ ha_innobase::create(
|
|||
}
|
||||
}
|
||||
|
||||
if (current_thd->query != NULL) {
|
||||
LEX_STRING q;
|
||||
|
||||
if (thd->convert_string(&q, system_charset_info,
|
||||
current_thd->query,
|
||||
current_thd->query_length,
|
||||
current_thd->charset())) {
|
||||
error = HA_ERR_OUT_OF_MEM;
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (thd->query != NULL) {
|
||||
error = row_table_add_foreign_constraints(trx,
|
||||
q.str, norm_name,
|
||||
thd->query, norm_name,
|
||||
create_info->options & HA_LEX_CREATE_TMP_TABLE);
|
||||
|
||||
error = convert_error_code_to_mysql(error, NULL);
|
||||
|
@ -4797,7 +4942,7 @@ ha_innobase::create(
|
|||
|
||||
log_buffer_flush_to_disk();
|
||||
|
||||
innobase_table = dict_table_get(norm_name, NULL);
|
||||
innobase_table = dict_table_get(norm_name);
|
||||
|
||||
DBUG_ASSERT(innobase_table != 0);
|
||||
|
||||
|
@ -4933,7 +5078,7 @@ ha_innobase::delete_table(
|
|||
/* Get the transaction associated with the current thd, or create one
|
||||
if not yet created */
|
||||
|
||||
parent_trx = check_trx_exists(current_thd);
|
||||
parent_trx = check_trx_exists(thd);
|
||||
|
||||
/* In case MySQL calls this in the middle of a SELECT query, release
|
||||
possible adaptive hash latch to avoid deadlocks of threads */
|
||||
|
|
|
@ -32,4 +32,4 @@ ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
|||
thr/thr0loc.c
|
||||
trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
|
||||
usr/usr0sess.c
|
||||
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c)
|
||||
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c)
|
||||
|
|
|
@ -76,7 +76,7 @@ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr
|
|||
include/univ.i include/usr0sess.h include/usr0sess.ic include/usr0types.h \
|
||||
include/ut0byte.h include/ut0byte.ic include/ut0dbg.h include/ut0lst.h \
|
||||
include/ut0mem.h include/ut0mem.ic include/ut0rnd.h include/ut0rnd.ic \
|
||||
include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic \
|
||||
include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic include/ha_prototypes.h \
|
||||
CMakeLists.txt
|
||||
|
||||
noinst_LIBRARIES = libinnobase.a
|
||||
|
|
|
@ -190,6 +190,10 @@ btr_get_prev_user_rec(
|
|||
|| (mtr_memo_contains(mtr, buf_block_align(prev_page),
|
||||
MTR_MEMO_PAGE_X_FIX)));
|
||||
ut_a(page_is_comp(prev_page) == page_is_comp(page));
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(prev_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
return(page_rec_get_prev(page_get_supremum_rec(prev_page)));
|
||||
}
|
||||
|
@ -237,6 +241,10 @@ btr_get_next_user_rec(
|
|||
MTR_MEMO_PAGE_S_FIX))
|
||||
|| (mtr_memo_contains(mtr, buf_block_align(next_page),
|
||||
MTR_MEMO_PAGE_X_FIX)));
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(next_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
ut_a(page_is_comp(next_page) == page_is_comp(page));
|
||||
return(page_rec_get_next(page_get_infimum_rec(next_page)));
|
||||
|
@ -597,9 +605,9 @@ btr_page_get_father_for_rec(
|
|||
buf_page_print(buf_frame_align(node_ptr));
|
||||
|
||||
fputs("InnoDB: Corruption of an index tree: table ", stderr);
|
||||
ut_print_name(stderr, NULL, index->table_name);
|
||||
ut_print_name(stderr, NULL, TRUE, index->table_name);
|
||||
fputs(", index ", stderr);
|
||||
ut_print_name(stderr, NULL, index->name);
|
||||
ut_print_name(stderr, NULL, FALSE, index->name);
|
||||
fprintf(stderr, ",\n"
|
||||
"InnoDB: father ptr page no %lu, child page no %lu\n",
|
||||
(ulong)
|
||||
|
@ -1518,6 +1526,10 @@ btr_attach_half_pages(
|
|||
|
||||
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
|
||||
ut_a(page_is_comp(prev_page) == page_is_comp(page));
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(prev_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
btr_page_set_next(prev_page, lower_page_no, mtr);
|
||||
}
|
||||
|
@ -1805,6 +1817,10 @@ btr_level_list_remove(
|
|||
|
||||
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
|
||||
ut_a(page_is_comp(prev_page) == page_is_comp(page));
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(prev_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
btr_page_set_next(prev_page, next_page_no, mtr);
|
||||
}
|
||||
|
@ -1813,6 +1829,10 @@ btr_level_list_remove(
|
|||
|
||||
next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
|
||||
ut_a(page_is_comp(next_page) == page_is_comp(page));
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(next_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
btr_page_set_prev(next_page, prev_page_no, mtr);
|
||||
}
|
||||
|
@ -2032,16 +2052,24 @@ btr_compress(
|
|||
/* Decide the page to which we try to merge and which will inherit
|
||||
the locks */
|
||||
|
||||
if (left_page_no != FIL_NULL) {
|
||||
is_left = left_page_no != FIL_NULL;
|
||||
|
||||
if (is_left) {
|
||||
|
||||
is_left = TRUE;
|
||||
merge_page = btr_page_get(space, left_page_no, RW_X_LATCH,
|
||||
mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(merge_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
} else if (right_page_no != FIL_NULL) {
|
||||
|
||||
is_left = FALSE;
|
||||
merge_page = btr_page_get(space, right_page_no, RW_X_LATCH,
|
||||
mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(merge_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
} else {
|
||||
/* The page is the only one on the level, lift the records
|
||||
to the father */
|
||||
|
@ -2203,7 +2231,6 @@ btr_discard_page(
|
|||
ulint left_page_no;
|
||||
ulint right_page_no;
|
||||
page_t* merge_page;
|
||||
ibool is_left;
|
||||
page_t* page;
|
||||
rec_t* node_ptr;
|
||||
|
||||
|
@ -2223,13 +2250,19 @@ btr_discard_page(
|
|||
right_page_no = btr_page_get_next(page, mtr);
|
||||
|
||||
if (left_page_no != FIL_NULL) {
|
||||
is_left = TRUE;
|
||||
merge_page = btr_page_get(space, left_page_no, RW_X_LATCH,
|
||||
mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(merge_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
} else if (right_page_no != FIL_NULL) {
|
||||
is_left = FALSE;
|
||||
merge_page = btr_page_get(space, right_page_no, RW_X_LATCH,
|
||||
mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(merge_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
} else {
|
||||
btr_discard_only_page_on_level(tree, page, mtr);
|
||||
|
||||
|
@ -2256,7 +2289,7 @@ btr_discard_page(
|
|||
/* Remove the page from the level list */
|
||||
btr_level_list_remove(tree, page, mtr);
|
||||
|
||||
if (is_left) {
|
||||
if (left_page_no != FIL_NULL) {
|
||||
lock_update_discard(page_get_supremum_rec(merge_page), page);
|
||||
} else {
|
||||
lock_update_discard(page_rec_get_next(
|
||||
|
@ -2745,7 +2778,29 @@ loop:
|
|||
rec_t* right_rec;
|
||||
right_page = btr_page_get(space, right_page_no, RW_X_LATCH,
|
||||
&mtr);
|
||||
ut_a(page_is_comp(right_page) == page_is_comp(page));
|
||||
if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr)
|
||||
!= buf_frame_get_page_no(page))) {
|
||||
btr_validate_report2(index, level, page, right_page);
|
||||
fputs("InnoDB: broken FIL_PAGE_NEXT"
|
||||
" or FIL_PAGE_PREV links\n", stderr);
|
||||
buf_page_print(page);
|
||||
buf_page_print(right_page);
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(page_is_comp(right_page)
|
||||
!= page_is_comp(page))) {
|
||||
btr_validate_report2(index, level, page, right_page);
|
||||
fputs("InnoDB: 'compact' flag mismatch\n", stderr);
|
||||
buf_page_print(page);
|
||||
buf_page_print(right_page);
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
goto node_ptr_fails;
|
||||
}
|
||||
|
||||
rec = page_rec_get_prev(page_get_supremum_rec(page));
|
||||
right_rec = page_rec_get_next(
|
||||
page_get_infimum_rec(right_page));
|
||||
|
@ -2753,8 +2808,8 @@ loop:
|
|||
offsets, ULINT_UNDEFINED, &heap);
|
||||
offsets2 = rec_get_offsets(right_rec, index,
|
||||
offsets2, ULINT_UNDEFINED, &heap);
|
||||
if (cmp_rec_rec(rec, right_rec, offsets, offsets2, index)
|
||||
>= 0) {
|
||||
if (UNIV_UNLIKELY(cmp_rec_rec(rec, right_rec,
|
||||
offsets, offsets2, index) >= 0)) {
|
||||
|
||||
btr_validate_report2(index, level, page, right_page);
|
||||
|
||||
|
@ -2869,10 +2924,7 @@ loop:
|
|||
ut_a(node_ptr == page_rec_get_prev(
|
||||
page_get_supremum_rec(father_page)));
|
||||
ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL);
|
||||
}
|
||||
|
||||
if (right_page_no != FIL_NULL) {
|
||||
|
||||
} else {
|
||||
right_node_ptr = btr_page_get_father_node_ptr(tree,
|
||||
right_page, &mtr);
|
||||
if (page_rec_get_next(node_ptr) !=
|
||||
|
@ -2934,14 +2986,15 @@ loop:
|
|||
}
|
||||
|
||||
node_ptr_fails:
|
||||
/* Commit the mini-transaction to release the latch on 'page'.
|
||||
Re-acquire the latch on right_page, which will become 'page'
|
||||
on the next loop. The page has already been checked. */
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (right_page_no != FIL_NULL) {
|
||||
ulint comp = page_is_comp(page);
|
||||
mtr_start(&mtr);
|
||||
|
||||
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
|
||||
ut_a(page_is_comp(page) == comp);
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
|
|
@ -157,6 +157,10 @@ btr_cur_latch_leaves(
|
|||
if (left_page_no != FIL_NULL) {
|
||||
get_page = btr_page_get(space, left_page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(get_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
ut_a(page_is_comp(get_page) == page_is_comp(page));
|
||||
buf_block_align(get_page)->check_index_page_at_flush =
|
||||
TRUE;
|
||||
|
@ -171,6 +175,10 @@ btr_cur_latch_leaves(
|
|||
if (right_page_no != FIL_NULL) {
|
||||
get_page = btr_page_get(space, right_page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(get_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
buf_block_align(get_page)->check_index_page_at_flush =
|
||||
TRUE;
|
||||
}
|
||||
|
@ -183,6 +191,10 @@ btr_cur_latch_leaves(
|
|||
if (left_page_no != FIL_NULL) {
|
||||
cursor->left_page = btr_page_get(space, left_page_no,
|
||||
RW_S_LATCH, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(cursor->left_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
ut_a(page_is_comp(cursor->left_page) ==
|
||||
page_is_comp(page));
|
||||
buf_block_align(
|
||||
|
@ -201,6 +213,10 @@ btr_cur_latch_leaves(
|
|||
if (left_page_no != FIL_NULL) {
|
||||
cursor->left_page = btr_page_get(space, left_page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(cursor->left_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
ut_a(page_is_comp(cursor->left_page) ==
|
||||
page_is_comp(page));
|
||||
buf_block_align(
|
||||
|
@ -1731,6 +1747,10 @@ btr_cur_pess_upd_restore_supremum(
|
|||
|
||||
ut_ad(prev_page_no != FIL_NULL);
|
||||
prev_page = buf_page_get_with_no_latch(space, prev_page_no, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(prev_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
/* We must already have an x-latch to prev_page! */
|
||||
ut_ad(mtr_memo_contains(mtr, buf_block_align(prev_page),
|
||||
|
@ -3771,11 +3791,6 @@ btr_copy_externally_stored_field(
|
|||
|
||||
page_no = btr_blob_get_next_page_no(blob_header);
|
||||
|
||||
/* On other BLOB pages except the first the BLOB header
|
||||
always is at the page data start: */
|
||||
|
||||
offset = FIL_PAGE_DATA;
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (page_no == FIL_NULL) {
|
||||
|
@ -3786,6 +3801,11 @@ btr_copy_externally_stored_field(
|
|||
return(buf);
|
||||
}
|
||||
|
||||
/* On other BLOB pages except the first the BLOB header
|
||||
always is at the page data start: */
|
||||
|
||||
offset = FIL_PAGE_DATA;
|
||||
|
||||
ut_a(copied_len < local_len + extern_len);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -397,6 +397,9 @@ btr_pcur_move_to_next_page(
|
|||
ut_ad(next_page_no != FIL_NULL);
|
||||
|
||||
next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(next_page, mtr) == buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
ut_a(page_is_comp(next_page) == page_is_comp(page));
|
||||
buf_block_align(next_page)->check_index_page_at_flush = TRUE;
|
||||
|
||||
|
|
|
@ -136,13 +136,12 @@ btr_search_sys_create(
|
|||
|
||||
btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t));
|
||||
|
||||
rw_lock_create(&btr_search_latch);
|
||||
rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS);
|
||||
|
||||
btr_search_sys = mem_alloc(sizeof(btr_search_sys_t));
|
||||
|
||||
btr_search_sys->hash_index = ha_create(TRUE, hash_size, 0, 0);
|
||||
|
||||
rw_lock_set_level(&btr_search_latch, SYNC_SEARCH_SYS);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
|
|
@ -524,12 +524,11 @@ buf_block_init(
|
|||
|
||||
block->n_pointers = 0;
|
||||
|
||||
rw_lock_create(&(block->lock));
|
||||
rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
|
||||
ut_ad(rw_lock_validate(&(block->lock)));
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_create(&(block->debug_latch));
|
||||
rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
|
||||
rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
}
|
||||
|
||||
|
@ -572,8 +571,7 @@ buf_pool_init(
|
|||
|
||||
/* 1. Initialize general fields
|
||||
---------------------------- */
|
||||
mutex_create(&(buf_pool->mutex));
|
||||
mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
|
||||
mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
|
@ -1856,7 +1854,6 @@ buf_page_io_complete(
|
|||
buf_block_t* block) /* in: pointer to the block in question */
|
||||
{
|
||||
ulint io_type;
|
||||
ulint read_page_no;
|
||||
|
||||
ut_ad(block);
|
||||
|
||||
|
@ -1866,18 +1863,36 @@ buf_page_io_complete(
|
|||
|
||||
if (io_type == BUF_IO_READ) {
|
||||
/* If this page is not uninitialized and not in the
|
||||
doublewrite buffer, then the page number should be the
|
||||
same as in block */
|
||||
|
||||
read_page_no = mach_read_from_4((block->frame)
|
||||
doublewrite buffer, then the page number and space id
|
||||
should be the same as in block. */
|
||||
ulint read_page_no = mach_read_from_4((block->frame)
|
||||
+ FIL_PAGE_OFFSET);
|
||||
if (read_page_no != 0
|
||||
&& !trx_doublewrite_page_inside(read_page_no)
|
||||
&& read_page_no != block->offset) {
|
||||
ulint read_space_id = mach_read_from_4((block->frame)
|
||||
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
|
||||
|
||||
if (!block->space && trx_doublewrite_page_inside(
|
||||
block->offset)) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
|
||||
(ulong) read_page_no, (ulong) block->offset);
|
||||
" InnoDB: Error: reading page %lu\n"
|
||||
"InnoDB: which is in the doublewrite buffer!\n",
|
||||
(ulong) block->offset);
|
||||
} else if (!read_space_id && !read_page_no) {
|
||||
/* This is likely an uninitialized page. */
|
||||
} else if ((block->space && block->space != read_space_id)
|
||||
|| block->offset != read_page_no) {
|
||||
/* We did not compare space_id to read_space_id
|
||||
if block->space == 0, because the field on the
|
||||
page may contain garbage in MySQL < 4.1.1,
|
||||
which only supported block->space == 0. */
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: space id and page n:o stored in the page\n"
|
||||
"InnoDB: read in are %lu:%lu, should be %lu:%lu!\n",
|
||||
(ulong) read_space_id, (ulong) read_page_no,
|
||||
(ulong) block->space, (ulong) block->offset);
|
||||
}
|
||||
/* From version 3.23.38 up we store the page checksum
|
||||
to the 4 first bytes of the page end lsn field */
|
||||
|
@ -2233,7 +2248,8 @@ buf_get_latched_pages_number(void)
|
|||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
return fixed_pages_number;
|
||||
|
||||
return(fixed_pages_number);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
|
|
@ -26,7 +26,7 @@ Created 11/11/1995 Heikki Tuuri
|
|||
#include "trx0sys.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/* When flushed, dirty blocks are searched in neigborhoods of this size, and
|
||||
/* When flushed, dirty blocks are searched in neighborhoods of this size, and
|
||||
flushed along with the original page. */
|
||||
|
||||
#define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\
|
||||
|
|
|
@ -293,3 +293,36 @@ dtype_print(
|
|||
|
||||
fprintf(stderr, " len %lu prec %lu", (ulong) len, (ulong) type->prec);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Returns the maximum size of a data type. Note: types in system tables may be
|
||||
incomplete and return incorrect information. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_max_size(
|
||||
/*===============*/
|
||||
/* out: maximum size (ULINT_MAX for
|
||||
unbounded types) */
|
||||
const dtype_t* type) /* in: type */
|
||||
{
|
||||
switch (type->mtype) {
|
||||
case DATA_SYS:
|
||||
case DATA_CHAR:
|
||||
case DATA_FIXBINARY:
|
||||
case DATA_INT:
|
||||
case DATA_FLOAT:
|
||||
case DATA_DOUBLE:
|
||||
case DATA_MYSQL:
|
||||
case DATA_VARCHAR:
|
||||
case DATA_BINARY:
|
||||
case DATA_DECIMAL:
|
||||
case DATA_VARMYSQL:
|
||||
return(type->len);
|
||||
case DATA_BLOB:
|
||||
return(ULINT_MAX);
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(ULINT_MAX);
|
||||
}
|
||||
|
|
|
@ -1250,9 +1250,9 @@ dict_foreign_eval_sql(
|
|||
ut_print_timestamp(ef);
|
||||
fputs(" Error in foreign key constraint creation for table ",
|
||||
ef);
|
||||
ut_print_name(ef, trx, table->name);
|
||||
ut_print_name(ef, trx, TRUE, table->name);
|
||||
fputs(".\nA foreign key constraint of name ", ef);
|
||||
ut_print_name(ef, trx, foreign->id);
|
||||
ut_print_name(ef, trx, FALSE, foreign->id);
|
||||
fputs("\nalready exists."
|
||||
" (Note that internally InnoDB adds 'databasename/'\n"
|
||||
"in front of the user-defined constraint name).\n",
|
||||
|
@ -1280,7 +1280,7 @@ dict_foreign_eval_sql(
|
|||
ut_print_timestamp(ef);
|
||||
fputs(" Internal error in foreign key constraint creation"
|
||||
" for table ", ef);
|
||||
ut_print_name(ef, trx, table->name);
|
||||
ut_print_name(ef, trx, TRUE, table->name);
|
||||
fputs(".\n"
|
||||
"See the MySQL .err log in the datadir for more information.\n", ef);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
|
|
@ -26,6 +26,9 @@ Created 1/8/1996 Heikki Tuuri
|
|||
#include "pars0sym.h"
|
||||
#include "que0que.h"
|
||||
#include "rem0cmp.h"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "m_ctype.h" /* my_isspace() */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
dict_sys_t* dict_sys = NULL; /* the dictionary system */
|
||||
|
||||
|
@ -55,6 +58,42 @@ static char dict_ibfk[] = "_ibfk_";
|
|||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/**********************************************************************
|
||||
Converts an identifier to a table name.
|
||||
|
||||
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
||||
this function, you MUST change also the prototype here! */
|
||||
extern
|
||||
void
|
||||
innobase_convert_from_table_id(
|
||||
/*===========================*/
|
||||
char* to, /* out: converted identifier */
|
||||
const char* from, /* in: identifier to convert */
|
||||
ulint len); /* in: length of 'to', in bytes;
|
||||
should be at least 5 * strlen(to) + 1 */
|
||||
/**********************************************************************
|
||||
Converts an identifier to UTF-8.
|
||||
|
||||
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
||||
this function, you MUST change also the prototype here! */
|
||||
extern
|
||||
void
|
||||
innobase_convert_from_id(
|
||||
/*=====================*/
|
||||
char* to, /* out: converted identifier */
|
||||
const char* from, /* in: identifier to convert */
|
||||
ulint len); /* in: length of 'to', in bytes;
|
||||
should be at least 3 * strlen(to) + 1 */
|
||||
/**********************************************************************
|
||||
Removes the filename encoding of a table or database name.
|
||||
|
||||
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
||||
this function, you MUST change also the prototype here! */
|
||||
extern
|
||||
void
|
||||
innobase_convert_from_filename(
|
||||
/*===========================*/
|
||||
char* s); /* in: identifier; out: decoded identifier */
|
||||
/**********************************************************************
|
||||
Compares NUL-terminated UTF-8 strings case insensitively.
|
||||
|
||||
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
||||
|
@ -77,6 +116,17 @@ void
|
|||
innobase_casedn_str(
|
||||
/*================*/
|
||||
char* a); /* in/out: string to put in lower case */
|
||||
|
||||
/**************************************************************************
|
||||
Determines the connection character set.
|
||||
|
||||
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
||||
this function, you MUST change also the prototype here! */
|
||||
struct charset_info_st*
|
||||
innobase_get_charset(
|
||||
/*=================*/
|
||||
/* out: connection character set */
|
||||
void* mysql_thd); /* in: MySQL thread handle */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -607,7 +657,7 @@ dict_index_get_nth_field_pos(
|
|||
}
|
||||
|
||||
/**************************************************************************
|
||||
Returns a table object, based on table id, and memoryfixes it. */
|
||||
Returns a table object based on table id. */
|
||||
|
||||
dict_table_t*
|
||||
dict_table_get_on_id(
|
||||
|
@ -629,12 +679,12 @@ dict_table_get_on_id(
|
|||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
return(dict_table_get_on_id_low(table_id, trx));
|
||||
return(dict_table_get_on_id_low(table_id));
|
||||
}
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
table = dict_table_get_on_id_low(table_id, trx);
|
||||
table = dict_table_get_on_id_low(table_id);
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
|
@ -716,8 +766,7 @@ dict_init(void)
|
|||
{
|
||||
dict_sys = mem_alloc(sizeof(dict_sys_t));
|
||||
|
||||
mutex_create(&(dict_sys->mutex));
|
||||
mutex_set_level(&(dict_sys->mutex), SYNC_DICT);
|
||||
mutex_create(&dict_sys->mutex, SYNC_DICT);
|
||||
|
||||
dict_sys->table_hash = hash_create(buf_pool_get_max_size() /
|
||||
(DICT_POOL_PER_TABLE_HASH *
|
||||
|
@ -732,32 +781,28 @@ dict_init(void)
|
|||
|
||||
UT_LIST_INIT(dict_sys->table_LRU);
|
||||
|
||||
rw_lock_create(&dict_operation_lock);
|
||||
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
|
||||
rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION);
|
||||
|
||||
dict_foreign_err_file = os_file_create_tmpfile();
|
||||
ut_a(dict_foreign_err_file);
|
||||
mutex_create(&dict_foreign_err_mutex);
|
||||
mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
|
||||
|
||||
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Returns a table object and memoryfixes it. NOTE! This is a high-level
|
||||
function to be used mainly from outside the 'dict' directory. Inside this
|
||||
directory dict_table_get_low is usually the appropriate function. */
|
||||
Returns a table object. NOTE! This is a high-level function to be used
|
||||
mainly from outside the 'dict' directory. Inside this directory
|
||||
dict_table_get_low is usually the appropriate function. */
|
||||
|
||||
dict_table_t*
|
||||
dict_table_get(
|
||||
/*===========*/
|
||||
/* out: table, NULL if
|
||||
does not exist */
|
||||
const char* table_name, /* in: table name */
|
||||
trx_t* trx) /* in: transaction handle or NULL */
|
||||
const char* table_name) /* in: table name */
|
||||
{
|
||||
dict_table_t* table;
|
||||
|
||||
UT_NOT_USED(trx);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
table = dict_table_get_low(table_name);
|
||||
|
@ -781,13 +826,10 @@ dict_table_get_and_increment_handle_count(
|
|||
/*======================================*/
|
||||
/* out: table, NULL if
|
||||
does not exist */
|
||||
const char* table_name, /* in: table name */
|
||||
trx_t* trx) /* in: transaction handle or NULL */
|
||||
const char* table_name) /* in: table name */
|
||||
{
|
||||
dict_table_t* table;
|
||||
|
||||
UT_NOT_USED(trx);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
table = dict_table_get_low(table_name);
|
||||
|
@ -819,6 +861,7 @@ dict_table_add_to_cache(
|
|||
ulint fold;
|
||||
ulint id_fold;
|
||||
ulint i;
|
||||
ulint row_len;
|
||||
|
||||
ut_ad(table);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
|
@ -866,6 +909,24 @@ dict_table_add_to_cache(
|
|||
#error "DATA_N_SYS_COLS != 4"
|
||||
#endif
|
||||
|
||||
row_len = 0;
|
||||
for (i = 0; i < table->n_def; i++) {
|
||||
ulint col_len = dtype_get_max_size(
|
||||
dict_col_get_type(dict_table_get_nth_col(table, i)));
|
||||
|
||||
/* If we have a single unbounded field, or several gigantic
|
||||
fields, mark the maximum row size as ULINT_MAX. */
|
||||
if (ut_max(col_len, row_len) >= (ULINT_MAX / 2)) {
|
||||
row_len = ULINT_MAX;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
row_len += col_len;
|
||||
}
|
||||
|
||||
table->max_row_size = row_len;
|
||||
|
||||
/* Look for a table with the same name: error if such exists */
|
||||
{
|
||||
dict_table_t* table2;
|
||||
|
@ -897,10 +958,7 @@ dict_table_add_to_cache(
|
|||
/* Add table to LRU list of tables */
|
||||
UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
|
||||
|
||||
/* If the dictionary cache grows too big, trim the table LRU list */
|
||||
|
||||
dict_sys->size += mem_heap_get_size(table->heap);
|
||||
/* dict_table_LRU_trim(); */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -1265,38 +1323,6 @@ dict_table_remove_from_cache(
|
|||
dict_mem_table_free(table);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Frees tables from the end of table_LRU if the dictionary cache occupies
|
||||
too much space. Currently not used! */
|
||||
|
||||
void
|
||||
dict_table_LRU_trim(void)
|
||||
/*=====================*/
|
||||
{
|
||||
dict_table_t* table;
|
||||
dict_table_t* prev_table;
|
||||
|
||||
ut_error;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
table = UT_LIST_GET_LAST(dict_sys->table_LRU);
|
||||
|
||||
while (table && (dict_sys->size >
|
||||
buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
|
||||
|
||||
prev_table = UT_LIST_GET_PREV(table_LRU, table);
|
||||
|
||||
if (table->mem_fix == 0) {
|
||||
dict_table_remove_from_cache(table);
|
||||
}
|
||||
|
||||
table = prev_table;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Adds a column to the data dictionary hash table. */
|
||||
static
|
||||
|
@ -1443,6 +1469,7 @@ dict_index_add_to_cache(
|
|||
|
||||
ut_ad(mem_heap_validate(index->heap));
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
{
|
||||
dict_index_t* index2;
|
||||
index2 = UT_LIST_GET_FIRST(table->indexes);
|
||||
|
@ -1452,10 +1479,11 @@ dict_index_add_to_cache(
|
|||
|
||||
index2 = UT_LIST_GET_NEXT(indexes, index2);
|
||||
}
|
||||
|
||||
ut_a(UT_LIST_GET_LEN(table->indexes) == 0
|
||||
|| (index->type & DICT_CLUSTERED) == 0);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
ut_a(!(index->type & DICT_CLUSTERED)
|
||||
|| UT_LIST_GET_LEN(table->indexes) == 0);
|
||||
|
||||
success = dict_index_find_cols(table, index);
|
||||
|
||||
|
@ -1526,10 +1554,7 @@ dict_index_add_to_cache(
|
|||
/* Add the index to the list of indexes stored in the tree */
|
||||
tree->tree_index = new_index;
|
||||
|
||||
/* If the dictionary cache grows too big, trim the table LRU list */
|
||||
|
||||
dict_sys->size += mem_heap_get_size(new_index->heap);
|
||||
/* dict_table_LRU_trim(); */
|
||||
|
||||
dict_mem_index_free(index);
|
||||
|
||||
|
@ -2091,6 +2116,7 @@ dict_foreign_find(
|
|||
return(NULL);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************************
|
||||
Tries to find an index whose first fields are the columns in the array,
|
||||
in the same order. */
|
||||
|
@ -2108,7 +2134,6 @@ dict_foreign_find_index(
|
|||
only has an effect if types_idx !=
|
||||
NULL. */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
dict_index_t* index;
|
||||
const char* col_name;
|
||||
ulint i;
|
||||
|
@ -2154,13 +2179,6 @@ dict_foreign_find_index(
|
|||
}
|
||||
|
||||
return(NULL);
|
||||
#else /* UNIV_HOTBACKUP */
|
||||
/* This function depends on MySQL code that is not included in
|
||||
InnoDB Hot Backup builds. Besides, this function should never
|
||||
be called in InnoDB Hot Backup. */
|
||||
ut_error;
|
||||
return(NULL);
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -2196,7 +2214,7 @@ dict_foreign_error_report(
|
|||
putc('\n', file);
|
||||
if (fk->foreign_index) {
|
||||
fputs("The index in the foreign key in table is ", file);
|
||||
ut_print_name(file, NULL, fk->foreign_index->name);
|
||||
ut_print_name(file, NULL, FALSE, fk->foreign_index->name);
|
||||
fputs(
|
||||
"\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
|
||||
"for correct foreign key definition.\n",
|
||||
|
@ -2359,12 +2377,13 @@ dict_scan_to(
|
|||
|
||||
/*************************************************************************
|
||||
Accepts a specified string. Comparisons are case-insensitive. */
|
||||
|
||||
static
|
||||
const char*
|
||||
dict_accept(
|
||||
/*========*/
|
||||
/* out: if string was accepted, the pointer
|
||||
is moved after that, else ptr is returned */
|
||||
struct charset_info_st* cs,/* in: the character set of ptr */
|
||||
const char* ptr, /* in: scan from this */
|
||||
const char* string, /* in: accept only this string as the next
|
||||
non-whitespace string */
|
||||
|
@ -2375,7 +2394,7 @@ dict_accept(
|
|||
|
||||
*success = FALSE;
|
||||
|
||||
while (isspace(*ptr)) {
|
||||
while (my_isspace(cs, *ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
|
@ -2400,12 +2419,15 @@ const char*
|
|||
dict_scan_id(
|
||||
/*=========*/
|
||||
/* out: scanned to */
|
||||
struct charset_info_st* cs,/* in: the character set of ptr */
|
||||
const char* ptr, /* in: scanned to */
|
||||
mem_heap_t* heap, /* in: heap where to allocate the id
|
||||
(NULL=id will not be allocated, but it
|
||||
will point to string near ptr) */
|
||||
const char** id, /* out,own: the id; NULL if no id was
|
||||
scannable */
|
||||
ibool table_id,/* in: TRUE=convert the allocated id
|
||||
as a table name; FALSE=convert to UTF-8 */
|
||||
ibool accept_also_dot)
|
||||
/* in: TRUE if also a dot can appear in a
|
||||
non-quoted id; in a quoted id it can appear
|
||||
|
@ -2414,13 +2436,12 @@ dict_scan_id(
|
|||
char quote = '\0';
|
||||
ulint len = 0;
|
||||
const char* s;
|
||||
char* d;
|
||||
ulint id_len;
|
||||
byte* b;
|
||||
char* str;
|
||||
char* dst;
|
||||
|
||||
*id = NULL;
|
||||
|
||||
while (isspace(*ptr)) {
|
||||
while (my_isspace(cs, *ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
|
@ -2451,7 +2472,7 @@ dict_scan_id(
|
|||
len++;
|
||||
}
|
||||
} else {
|
||||
while (!isspace(*ptr) && *ptr != '(' && *ptr != ')'
|
||||
while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')'
|
||||
&& (accept_also_dot || *ptr != '.')
|
||||
&& *ptr != ',' && *ptr != '\0') {
|
||||
|
||||
|
@ -2461,43 +2482,50 @@ dict_scan_id(
|
|||
len = ptr - s;
|
||||
}
|
||||
|
||||
if (quote && heap) {
|
||||
*id = d = mem_heap_alloc(heap, len + 1);
|
||||
if (UNIV_UNLIKELY(!heap)) {
|
||||
/* no heap given: id will point to source string */
|
||||
*id = s;
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
if (quote) {
|
||||
char* d;
|
||||
str = d = mem_heap_alloc(heap, len + 1);
|
||||
while (len--) {
|
||||
if ((*d++ = *s++) == quote) {
|
||||
s++;
|
||||
}
|
||||
}
|
||||
*d++ = 0;
|
||||
ut_a(*s == quote);
|
||||
ut_a(s + 1 == ptr);
|
||||
} else if (heap) {
|
||||
*id = mem_heap_strdupl(heap, s, len);
|
||||
len = d - str;
|
||||
ut_ad(*s == quote);
|
||||
ut_ad(s + 1 == ptr);
|
||||
} else {
|
||||
/* no heap given: id will point to source string */
|
||||
*id = s;
|
||||
str = mem_heap_strdupl(heap, s, len);
|
||||
}
|
||||
|
||||
if (heap && !quote) {
|
||||
/* EMS MySQL Manager sometimes adds characters 0xA0 (in
|
||||
latin1, a 'non-breakable space') to the end of a table name.
|
||||
But isspace(0xA0) is not true, which confuses our foreign key
|
||||
parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2
|
||||
and 0xA0 are at the end of the string.
|
||||
if (!table_id) {
|
||||
convert_id:
|
||||
/* Convert the identifier from connection character set
|
||||
to UTF-8. */
|
||||
len = 3 * len + 1;
|
||||
*id = dst = mem_heap_alloc(heap, len);
|
||||
|
||||
TODO: we should lex the string using thd->charset_info, and
|
||||
my_isspace(). Only after that, convert id names to UTF-8. */
|
||||
innobase_convert_from_id(dst, str, len);
|
||||
} else if (!strncmp(str, srv_mysql50_table_name_prefix,
|
||||
sizeof srv_mysql50_table_name_prefix)) {
|
||||
/* This is a pre-5.1 table name
|
||||
containing chars other than [A-Za-z0-9].
|
||||
Discard the prefix and use raw UTF-8 encoding. */
|
||||
str += sizeof srv_mysql50_table_name_prefix;
|
||||
len -= sizeof srv_mysql50_table_name_prefix;
|
||||
goto convert_id;
|
||||
} else {
|
||||
/* Encode using filename-safe characters. */
|
||||
len = 5 * len + 1;
|
||||
*id = dst = mem_heap_alloc(heap, len);
|
||||
|
||||
b = (byte*)(*id);
|
||||
id_len = strlen((char*) b);
|
||||
|
||||
if (id_len >= 3 && b[id_len - 1] == 0xA0
|
||||
&& b[id_len - 2] == 0xC2) {
|
||||
|
||||
/* Strip the 2 last bytes */
|
||||
|
||||
b[id_len - 2] = '\0';
|
||||
}
|
||||
innobase_convert_from_table_id(dst, str, len);
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
|
@ -2510,6 +2538,7 @@ const char*
|
|||
dict_scan_col(
|
||||
/*==========*/
|
||||
/* out: scanned to */
|
||||
struct charset_info_st* cs,/* in: the character set of ptr */
|
||||
const char* ptr, /* in: scanned to */
|
||||
ibool* success,/* out: TRUE if success */
|
||||
dict_table_t* table, /* in: table in which the column is */
|
||||
|
@ -2518,13 +2547,12 @@ dict_scan_col(
|
|||
const char** name) /* out,own: the column name; NULL if no name
|
||||
was scannable */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
dict_col_t* col;
|
||||
ulint i;
|
||||
|
||||
*success = FALSE;
|
||||
|
||||
ptr = dict_scan_id(ptr, heap, name, TRUE);
|
||||
ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE);
|
||||
|
||||
if (*name == NULL) {
|
||||
|
||||
|
@ -2552,13 +2580,6 @@ dict_scan_col(
|
|||
}
|
||||
|
||||
return(ptr);
|
||||
#else /* UNIV_HOTBACKUP */
|
||||
/* This function depends on MySQL code that is not included in
|
||||
InnoDB Hot Backup builds. Besides, this function should never
|
||||
be called in InnoDB Hot Backup. */
|
||||
ut_error;
|
||||
return(NULL);
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -2568,6 +2589,7 @@ const char*
|
|||
dict_scan_table_name(
|
||||
/*=================*/
|
||||
/* out: scanned to */
|
||||
struct charset_info_st* cs,/* in: the character set of ptr */
|
||||
const char* ptr, /* in: scanned to */
|
||||
dict_table_t** table, /* out: table object or NULL */
|
||||
const char* name, /* in: foreign key table name */
|
||||
|
@ -2576,7 +2598,6 @@ dict_scan_table_name(
|
|||
const char** ref_name)/* out,own: the table name;
|
||||
NULL if no name was scannable */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
const char* database_name = NULL;
|
||||
ulint database_name_len = 0;
|
||||
const char* table_name = NULL;
|
||||
|
@ -2587,7 +2608,7 @@ dict_scan_table_name(
|
|||
*success = FALSE;
|
||||
*table = NULL;
|
||||
|
||||
ptr = dict_scan_id(ptr, heap, &scan_name, FALSE);
|
||||
ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE);
|
||||
|
||||
if (scan_name == NULL) {
|
||||
|
||||
|
@ -2602,7 +2623,7 @@ dict_scan_table_name(
|
|||
database_name = scan_name;
|
||||
database_name_len = strlen(database_name);
|
||||
|
||||
ptr = dict_scan_id(ptr, heap, &table_name, FALSE);
|
||||
ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE);
|
||||
|
||||
if (table_name == NULL) {
|
||||
|
||||
|
@ -2658,13 +2679,6 @@ dict_scan_table_name(
|
|||
*table = dict_table_get_low(ref);
|
||||
|
||||
return(ptr);
|
||||
#else /* UNIV_HOTBACKUP */
|
||||
/* This function depends on MySQL code that is not included in
|
||||
InnoDB Hot Backup builds. Besides, this function should never
|
||||
be called in InnoDB Hot Backup. */
|
||||
ut_error;
|
||||
return(NULL);
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -2674,6 +2688,7 @@ const char*
|
|||
dict_skip_word(
|
||||
/*===========*/
|
||||
/* out: scanned to */
|
||||
struct charset_info_st* cs,/* in: the character set of ptr */
|
||||
const char* ptr, /* in: scanned to */
|
||||
ibool* success)/* out: TRUE if success, FALSE if just spaces
|
||||
left in string or a syntax error */
|
||||
|
@ -2682,7 +2697,7 @@ dict_skip_word(
|
|||
|
||||
*success = FALSE;
|
||||
|
||||
ptr = dict_scan_id(ptr, NULL, &start, TRUE);
|
||||
ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE);
|
||||
|
||||
if (start) {
|
||||
*success = TRUE;
|
||||
|
@ -2860,6 +2875,7 @@ dict_create_foreign_constraints_low(
|
|||
/* out: error code or DB_SUCCESS */
|
||||
trx_t* trx, /* in: transaction */
|
||||
mem_heap_t* heap, /* in: memory heap */
|
||||
struct charset_info_st* cs,/* in: the character set of sql_string */
|
||||
const char* sql_string,
|
||||
/* in: CREATE TABLE or ALTER TABLE statement
|
||||
where foreign keys are declared like:
|
||||
|
@ -2917,14 +2933,14 @@ dict_create_foreign_constraints_low(
|
|||
/* First check if we are actually doing an ALTER TABLE, and in that
|
||||
case look for the table being altered */
|
||||
|
||||
ptr = dict_accept(ptr, "ALTER", &success);
|
||||
ptr = dict_accept(cs, ptr, "ALTER", &success);
|
||||
|
||||
if (!success) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "TABLE", &success);
|
||||
ptr = dict_accept(cs, ptr, "TABLE", &success);
|
||||
|
||||
if (!success) {
|
||||
|
||||
|
@ -2933,7 +2949,7 @@ dict_create_foreign_constraints_low(
|
|||
|
||||
/* We are doing an ALTER TABLE: scan the table name we are altering */
|
||||
|
||||
ptr = dict_scan_table_name(ptr, &table_to_alter, name,
|
||||
ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name,
|
||||
&success, heap, &referenced_table_name);
|
||||
if (!success) {
|
||||
fprintf(stderr,
|
||||
|
@ -2973,21 +2989,22 @@ loop:
|
|||
of the constraint to system tables. */
|
||||
ptr = ptr1;
|
||||
|
||||
ptr = dict_accept(ptr, "CONSTRAINT", &success);
|
||||
ptr = dict_accept(cs, ptr, "CONSTRAINT", &success);
|
||||
|
||||
ut_a(success);
|
||||
|
||||
if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') {
|
||||
if (!my_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') {
|
||||
goto loop;
|
||||
}
|
||||
|
||||
while (isspace(*ptr)) {
|
||||
while (my_isspace(cs, *ptr)) {
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* read constraint name unless got "CONSTRAINT FOREIGN" */
|
||||
if (ptr != ptr2) {
|
||||
ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE);
|
||||
ptr = dict_scan_id(cs, ptr, heap,
|
||||
&constraint_name, FALSE, FALSE);
|
||||
}
|
||||
} else {
|
||||
ptr = ptr2;
|
||||
|
@ -3002,7 +3019,8 @@ loop:
|
|||
if so, immediately reject the command if the table is a
|
||||
temporary one. For now, this kludge will work. */
|
||||
if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) {
|
||||
return DB_CANNOT_ADD_CONSTRAINT;
|
||||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
/**********************************************************/
|
||||
|
@ -3016,28 +3034,28 @@ loop:
|
|||
|
||||
start_of_latest_foreign = ptr;
|
||||
|
||||
ptr = dict_accept(ptr, "FOREIGN", &success);
|
||||
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
|
||||
|
||||
if (!success) {
|
||||
goto loop;
|
||||
}
|
||||
|
||||
if (!isspace(*ptr)) {
|
||||
if (!my_isspace(cs, *ptr)) {
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "KEY", &success);
|
||||
ptr = dict_accept(cs, ptr, "KEY", &success);
|
||||
|
||||
if (!success) {
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "(", &success);
|
||||
ptr = dict_accept(cs, ptr, "(", &success);
|
||||
|
||||
if (!success) {
|
||||
/* MySQL allows also an index id before the '('; we
|
||||
skip it */
|
||||
ptr = dict_skip_word(ptr, &success);
|
||||
ptr = dict_skip_word(cs, ptr, &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_report_syntax_err(name,
|
||||
|
@ -3046,7 +3064,7 @@ loop:
|
|||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "(", &success);
|
||||
ptr = dict_accept(cs, ptr, "(", &success);
|
||||
|
||||
if (!success) {
|
||||
/* We do not flag a syntax error here because in an
|
||||
|
@ -3061,7 +3079,7 @@ loop:
|
|||
/* Scan the columns in the first list */
|
||||
col_loop1:
|
||||
ut_a(i < (sizeof column_names) / sizeof *column_names);
|
||||
ptr = dict_scan_col(ptr, &success, table, columns + i,
|
||||
ptr = dict_scan_col(cs, ptr, &success, table, columns + i,
|
||||
heap, column_names + i);
|
||||
if (!success) {
|
||||
mutex_enter(&dict_foreign_err_mutex);
|
||||
|
@ -3075,13 +3093,13 @@ col_loop1:
|
|||
|
||||
i++;
|
||||
|
||||
ptr = dict_accept(ptr, ",", &success);
|
||||
ptr = dict_accept(cs, ptr, ",", &success);
|
||||
|
||||
if (success) {
|
||||
goto col_loop1;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, ")", &success);
|
||||
ptr = dict_accept(cs, ptr, ")", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||
|
@ -3098,7 +3116,7 @@ col_loop1:
|
|||
mutex_enter(&dict_foreign_err_mutex);
|
||||
dict_foreign_error_report_low(ef, name);
|
||||
fputs("There is no index in table ", ef);
|
||||
ut_print_name(ef, NULL, name);
|
||||
ut_print_name(ef, NULL, TRUE, name);
|
||||
fprintf(ef, " where the columns appear\n"
|
||||
"as the first columns. Constraint:\n%s\n"
|
||||
"See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n"
|
||||
|
@ -3108,9 +3126,9 @@ col_loop1:
|
|||
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
ptr = dict_accept(ptr, "REFERENCES", &success);
|
||||
ptr = dict_accept(cs, ptr, "REFERENCES", &success);
|
||||
|
||||
if (!success || !isspace(*ptr)) {
|
||||
if (!success || !my_isspace(cs, *ptr)) {
|
||||
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
|
||||
ptr);
|
||||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
|
@ -3150,7 +3168,7 @@ col_loop1:
|
|||
mem_heap_strdup(foreign->heap, columns[i]->name);
|
||||
}
|
||||
|
||||
ptr = dict_scan_table_name(ptr, &referenced_table, name,
|
||||
ptr = dict_scan_table_name(cs, ptr, &referenced_table, name,
|
||||
&success, heap, &referenced_table_name);
|
||||
|
||||
/* Note that referenced_table can be NULL if the user has suppressed
|
||||
|
@ -3169,7 +3187,7 @@ col_loop1:
|
|||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "(", &success);
|
||||
ptr = dict_accept(cs, ptr, "(", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
@ -3182,7 +3200,7 @@ col_loop1:
|
|||
i = 0;
|
||||
|
||||
col_loop2:
|
||||
ptr = dict_scan_col(ptr, &success, referenced_table, columns + i,
|
||||
ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i,
|
||||
heap, column_names + i);
|
||||
i++;
|
||||
|
||||
|
@ -3199,13 +3217,13 @@ col_loop2:
|
|||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, ",", &success);
|
||||
ptr = dict_accept(cs, ptr, ",", &success);
|
||||
|
||||
if (success) {
|
||||
goto col_loop2;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, ")", &success);
|
||||
ptr = dict_accept(cs, ptr, ")", &success);
|
||||
|
||||
if (!success || foreign->n_fields != i) {
|
||||
dict_foreign_free(foreign);
|
||||
|
@ -3221,17 +3239,17 @@ col_loop2:
|
|||
scan_on_conditions:
|
||||
/* Loop here as long as we can find ON ... conditions */
|
||||
|
||||
ptr = dict_accept(ptr, "ON", &success);
|
||||
ptr = dict_accept(cs, ptr, "ON", &success);
|
||||
|
||||
if (!success) {
|
||||
|
||||
goto try_find_index;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "DELETE", &success);
|
||||
ptr = dict_accept(cs, ptr, "DELETE", &success);
|
||||
|
||||
if (!success) {
|
||||
ptr = dict_accept(ptr, "UPDATE", &success);
|
||||
ptr = dict_accept(cs, ptr, "UPDATE", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
@ -3248,13 +3266,13 @@ scan_on_conditions:
|
|||
n_on_deletes++;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "RESTRICT", &success);
|
||||
ptr = dict_accept(cs, ptr, "RESTRICT", &success);
|
||||
|
||||
if (success) {
|
||||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "CASCADE", &success);
|
||||
ptr = dict_accept(cs, ptr, "CASCADE", &success);
|
||||
|
||||
if (success) {
|
||||
if (is_on_delete) {
|
||||
|
@ -3266,10 +3284,10 @@ scan_on_conditions:
|
|||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "NO", &success);
|
||||
ptr = dict_accept(cs, ptr, "NO", &success);
|
||||
|
||||
if (success) {
|
||||
ptr = dict_accept(ptr, "ACTION", &success);
|
||||
ptr = dict_accept(cs, ptr, "ACTION", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
@ -3288,7 +3306,7 @@ scan_on_conditions:
|
|||
goto scan_on_conditions;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "SET", &success);
|
||||
ptr = dict_accept(cs, ptr, "SET", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
@ -3297,7 +3315,7 @@ scan_on_conditions:
|
|||
return(DB_CANNOT_ADD_CONSTRAINT);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "NULL", &success);
|
||||
ptr = dict_accept(cs, ptr, "NULL", &success);
|
||||
|
||||
if (!success) {
|
||||
dict_foreign_free(foreign);
|
||||
|
@ -3407,6 +3425,25 @@ try_find_index:
|
|||
goto loop;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Determines whether a string starts with the specified keyword. */
|
||||
|
||||
ibool
|
||||
dict_str_starts_with_keyword(
|
||||
/*=========================*/
|
||||
/* out: TRUE if str starts
|
||||
with keyword */
|
||||
void* mysql_thd, /* in: MySQL thread handle */
|
||||
const char* str, /* in: string to scan for keyword */
|
||||
const char* keyword) /* in: keyword to look for */
|
||||
{
|
||||
struct charset_info_st* cs = innobase_get_charset(mysql_thd);
|
||||
ibool success;
|
||||
|
||||
dict_accept(cs, str, keyword, &success);
|
||||
return(success);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Scans a table create SQL string and adds to the data dictionary the foreign
|
||||
key constraints declared in the string. This function should be called after
|
||||
|
@ -3438,11 +3475,14 @@ dict_create_foreign_constraints(
|
|||
ulint err;
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_a(trx && trx->mysql_thd);
|
||||
|
||||
str = dict_strip_comments(sql_string);
|
||||
heap = mem_heap_create(10000);
|
||||
|
||||
err = dict_create_foreign_constraints_low(trx, heap, str, name,
|
||||
reject_fks);
|
||||
err = dict_create_foreign_constraints_low(trx, heap,
|
||||
innobase_get_charset(trx->mysql_thd),
|
||||
str, name, reject_fks);
|
||||
|
||||
mem_heap_free(heap);
|
||||
mem_free(str);
|
||||
|
@ -3475,6 +3515,11 @@ dict_foreign_parse_drop_constraints(
|
|||
const char* ptr;
|
||||
const char* id;
|
||||
FILE* ef = dict_foreign_err_file;
|
||||
struct charset_info_st* cs;
|
||||
|
||||
ut_a(trx && trx->mysql_thd);
|
||||
|
||||
cs = innobase_get_charset(trx->mysql_thd);
|
||||
|
||||
*n = 0;
|
||||
|
||||
|
@ -3495,28 +3540,28 @@ loop:
|
|||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "DROP", &success);
|
||||
ptr = dict_accept(cs, ptr, "DROP", &success);
|
||||
|
||||
if (!isspace(*ptr)) {
|
||||
if (!my_isspace(cs, *ptr)) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "FOREIGN", &success);
|
||||
ptr = dict_accept(cs, ptr, "FOREIGN", &success);
|
||||
|
||||
if (!success) {
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
ptr = dict_accept(ptr, "KEY", &success);
|
||||
ptr = dict_accept(cs, ptr, "KEY", &success);
|
||||
|
||||
if (!success) {
|
||||
|
||||
goto syntax_error;
|
||||
}
|
||||
|
||||
ptr = dict_scan_id(ptr, heap, &id, TRUE);
|
||||
ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE);
|
||||
|
||||
if (id == NULL) {
|
||||
|
||||
|
@ -3549,12 +3594,12 @@ loop:
|
|||
ut_print_timestamp(ef);
|
||||
fputs(
|
||||
" Error in dropping of a foreign key constraint of table ", ef);
|
||||
ut_print_name(ef, NULL, table->name);
|
||||
ut_print_name(ef, NULL, TRUE, table->name);
|
||||
fputs(",\n"
|
||||
"in SQL command\n", ef);
|
||||
fputs(str, ef);
|
||||
fputs("\nCannot find a constraint with the given id ", ef);
|
||||
ut_print_name(ef, NULL, id);
|
||||
ut_print_name(ef, NULL, FALSE, id);
|
||||
fputs(".\n", ef);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
|
@ -3571,7 +3616,7 @@ syntax_error:
|
|||
ut_print_timestamp(ef);
|
||||
fputs(
|
||||
" Syntax error in dropping of a foreign key constraint of table ", ef);
|
||||
ut_print_name(ef, NULL, table->name);
|
||||
ut_print_name(ef, NULL, TRUE, table->name);
|
||||
fprintf(ef, ",\n"
|
||||
"close to:\n%s\n in SQL command\n%s\n", ptr, str);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
@ -3580,6 +3625,7 @@ syntax_error:
|
|||
|
||||
return(DB_CANNOT_DROP_CONSTRAINT);
|
||||
}
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
|
||||
|
||||
|
@ -3653,9 +3699,7 @@ dict_tree_create(
|
|||
|
||||
tree->magic_n = DICT_TREE_MAGIC_N;
|
||||
|
||||
rw_lock_create(&(tree->lock));
|
||||
|
||||
rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE);
|
||||
rw_lock_create(&tree->lock, SYNC_INDEX_TREE);
|
||||
|
||||
return(tree);
|
||||
}
|
||||
|
@ -4232,11 +4276,11 @@ dict_print_info_on_foreign_key_in_create_format(
|
|||
}
|
||||
|
||||
fputs(" CONSTRAINT ", file);
|
||||
ut_print_name(file, trx, stripped_id);
|
||||
ut_print_name(file, trx, FALSE, stripped_id);
|
||||
fputs(" FOREIGN KEY (", file);
|
||||
|
||||
for (i = 0;;) {
|
||||
ut_print_name(file, trx, foreign->foreign_col_names[i]);
|
||||
ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]);
|
||||
if (++i < foreign->n_fields) {
|
||||
fputs(", ", file);
|
||||
} else {
|
||||
|
@ -4249,7 +4293,7 @@ dict_print_info_on_foreign_key_in_create_format(
|
|||
if (dict_tables_have_same_db(foreign->foreign_table_name,
|
||||
foreign->referenced_table_name)) {
|
||||
/* Do not print the database name of the referenced table */
|
||||
ut_print_name(file, trx, dict_remove_db_name(
|
||||
ut_print_name(file, trx, TRUE, dict_remove_db_name(
|
||||
foreign->referenced_table_name));
|
||||
} else {
|
||||
/* Look for the '/' in the table name */
|
||||
|
@ -4259,9 +4303,10 @@ dict_print_info_on_foreign_key_in_create_format(
|
|||
i++;
|
||||
}
|
||||
|
||||
ut_print_namel(file, trx, foreign->referenced_table_name, i);
|
||||
ut_print_namel(file, trx, TRUE,
|
||||
foreign->referenced_table_name, i);
|
||||
putc('.', file);
|
||||
ut_print_name(file, trx,
|
||||
ut_print_name(file, trx, TRUE,
|
||||
foreign->referenced_table_name + i + 1);
|
||||
}
|
||||
|
||||
|
@ -4269,7 +4314,8 @@ dict_print_info_on_foreign_key_in_create_format(
|
|||
putc('(', file);
|
||||
|
||||
for (i = 0;;) {
|
||||
ut_print_name(file, trx, foreign->referenced_col_names[i]);
|
||||
ut_print_name(file, trx, FALSE,
|
||||
foreign->referenced_col_names[i]);
|
||||
if (++i < foreign->n_fields) {
|
||||
fputs(", ", file);
|
||||
} else {
|
||||
|
@ -4343,12 +4389,12 @@ dict_print_info_on_foreign_keys(
|
|||
putc(' ', file);
|
||||
}
|
||||
|
||||
ut_print_name(file, trx,
|
||||
ut_print_name(file, trx, FALSE,
|
||||
foreign->foreign_col_names[i]);
|
||||
}
|
||||
|
||||
fputs(") REFER ", file);
|
||||
ut_print_name(file, trx,
|
||||
ut_print_name(file, trx, TRUE,
|
||||
foreign->referenced_table_name);
|
||||
putc('(', file);
|
||||
|
||||
|
@ -4356,7 +4402,7 @@ dict_print_info_on_foreign_keys(
|
|||
if (i) {
|
||||
putc(' ', file);
|
||||
}
|
||||
ut_print_name(file, trx,
|
||||
ut_print_name(file, trx, FALSE,
|
||||
foreign->referenced_col_names[i]);
|
||||
}
|
||||
|
||||
|
@ -4403,7 +4449,7 @@ dict_index_name_print(
|
|||
const dict_index_t* index) /* in: index to print */
|
||||
{
|
||||
fputs("index ", file);
|
||||
ut_print_name(file, trx, index->name);
|
||||
ut_print_name(file, trx, FALSE, index->name);
|
||||
fputs(" of table ", file);
|
||||
ut_print_name(file, trx, index->table_name);
|
||||
ut_print_name(file, trx, TRUE, index->table_name);
|
||||
}
|
||||
|
|
|
@ -184,7 +184,7 @@ loop:
|
|||
|
||||
if (table == NULL) {
|
||||
fputs("InnoDB: Failed to load table ", stderr);
|
||||
ut_print_namel(stderr, NULL, (char*) field, len);
|
||||
ut_print_namel(stderr, NULL, TRUE, (char*) field, len);
|
||||
putc('\n', stderr);
|
||||
} else {
|
||||
/* The table definition was corrupt if there
|
||||
|
|
|
@ -58,7 +58,6 @@ dict_mem_table_create(
|
|||
table->tablespace_discarded = FALSE;
|
||||
table->n_def = 0;
|
||||
table->n_cols = n_cols + DATA_N_SYS_COLS;
|
||||
table->mem_fix = 0;
|
||||
|
||||
table->n_mysql_handles_opened = 0;
|
||||
table->n_foreign_key_checks_running = 0;
|
||||
|
@ -83,8 +82,9 @@ dict_mem_table_create(
|
|||
|
||||
table->stat_modified_counter = 0;
|
||||
|
||||
mutex_create(&(table->autoinc_mutex));
|
||||
mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX);
|
||||
table->max_row_size = 0;
|
||||
|
||||
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
|
||||
|
||||
table->autoinc_inited = FALSE;
|
||||
|
||||
|
|
|
@ -1050,8 +1050,7 @@ try_again:
|
|||
|
||||
space->ibuf_data = NULL;
|
||||
|
||||
rw_lock_create(&(space->latch));
|
||||
rw_lock_set_level(&(space->latch), SYNC_FSP);
|
||||
rw_lock_create(&space->latch, SYNC_FSP);
|
||||
|
||||
HASH_INSERT(fil_space_t, hash, system->spaces, id, space);
|
||||
|
||||
|
@ -1295,9 +1294,7 @@ fil_system_create(
|
|||
|
||||
system = mem_alloc(sizeof(fil_system_t));
|
||||
|
||||
mutex_create(&(system->mutex));
|
||||
|
||||
mutex_set_level(&(system->mutex), SYNC_ANY_LATCH);
|
||||
mutex_create(&system->mutex, SYNC_ANY_LATCH);
|
||||
|
||||
system->spaces = hash_create(hash_size);
|
||||
system->name_hash = hash_create(hash_size);
|
||||
|
|
|
@ -144,9 +144,7 @@ hash_create_mutexes(
|
|||
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
|
||||
|
||||
for (i = 0; i < n_mutexes; i++) {
|
||||
mutex_create(table->mutexes + i);
|
||||
|
||||
mutex_set_level(table->mutexes + i, sync_level);
|
||||
mutex_create(table->mutexes + i, sync_level);
|
||||
}
|
||||
|
||||
table->n_mutexes = n_mutexes;
|
||||
|
|
|
@ -144,6 +144,7 @@ static ulint ibuf_rnd = 986058871;
|
|||
|
||||
ulint ibuf_flush_count = 0;
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
/* Dimensions for the ibuf_count array */
|
||||
#define IBUF_COUNT_N_SPACES 500
|
||||
#define IBUF_COUNT_N_PAGES 2000
|
||||
|
@ -152,6 +153,7 @@ ulint ibuf_flush_count = 0;
|
|||
static ulint* ibuf_counts[IBUF_COUNT_N_SPACES];
|
||||
|
||||
static ibool ibuf_counts_inited = FALSE;
|
||||
#endif
|
||||
|
||||
/* The start address for an insert buffer bitmap page bitmap */
|
||||
#define IBUF_BITMAP PAGE_DATA
|
||||
|
@ -314,6 +316,7 @@ ibuf_tree_root_get(
|
|||
return(page);
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
/**********************************************************************
|
||||
Gets the ibuf count for a given page. */
|
||||
|
||||
|
@ -338,7 +341,6 @@ ibuf_count_get(
|
|||
|
||||
/**********************************************************************
|
||||
Sets the ibuf count for a given page. */
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
static
|
||||
void
|
||||
ibuf_count_set(
|
||||
|
@ -389,23 +391,18 @@ ibuf_init_at_db_start(void)
|
|||
ibuf_count_set(i, j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mutex_create(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
mutex_set_level(&ibuf_pessimistic_insert_mutex,
|
||||
SYNC_IBUF_PESS_INSERT_MUTEX);
|
||||
mutex_create(&ibuf_mutex);
|
||||
|
||||
mutex_set_level(&ibuf_mutex, SYNC_IBUF_MUTEX);
|
||||
|
||||
mutex_create(&ibuf_bitmap_mutex);
|
||||
|
||||
mutex_set_level(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
|
||||
|
||||
fil_ibuf_init_at_db_start();
|
||||
|
||||
ibuf_counts_inited = TRUE;
|
||||
}
|
||||
#endif
|
||||
mutex_create(&ibuf_pessimistic_insert_mutex,
|
||||
SYNC_IBUF_PESS_INSERT_MUTEX);
|
||||
|
||||
mutex_create(&ibuf_mutex, SYNC_IBUF_MUTEX);
|
||||
|
||||
mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
|
||||
|
||||
fil_ibuf_init_at_db_start();
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
|
@ -2348,6 +2345,10 @@ ibuf_get_volume_buffered(
|
|||
}
|
||||
|
||||
prev_page = buf_page_get(0, prev_page_no, RW_X_LATCH, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_next(prev_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
buf_page_dbg_add_level(prev_page, SYNC_TREE_NODE);
|
||||
|
@ -2411,6 +2412,10 @@ count_later:
|
|||
}
|
||||
|
||||
next_page = buf_page_get(0, next_page_no, RW_X_LATCH, mtr);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(btr_page_get_prev(next_page, mtr)
|
||||
== buf_frame_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
buf_page_dbg_add_level(next_page, SYNC_TREE_NODE);
|
||||
|
|
|
@ -330,6 +330,16 @@ dtype_get_min_size(
|
|||
/* out: minimum size */
|
||||
const dtype_t* type); /* in: type */
|
||||
/***************************************************************************
|
||||
Returns the maximum size of a data type. Note: types in system tables may be
|
||||
incomplete and return incorrect information. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
dtype_get_max_size(
|
||||
/*===============*/
|
||||
/* out: maximum size (ULINT_MAX for
|
||||
unbounded types) */
|
||||
const dtype_t* type); /* in: type */
|
||||
/***************************************************************************
|
||||
Returns a stored SQL NULL size for a type. For fixed length types it is
|
||||
the fixed length of the type, otherwise 0. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -44,18 +44,6 @@ dict_get_db_name_len(
|
|||
/* out: database name length */
|
||||
const char* name); /* in: table name in the form
|
||||
dbname '/' tablename */
|
||||
/*************************************************************************
|
||||
Accepts a specified string. Comparisons are case-insensitive. */
|
||||
|
||||
const char*
|
||||
dict_accept(
|
||||
/*========*/
|
||||
/* out: if string was accepted, the pointer
|
||||
is moved after that, else ptr is returned */
|
||||
const char* ptr, /* in: scan from this */
|
||||
const char* string, /* in: accept only this string as the next
|
||||
non-whitespace string */
|
||||
ibool* success);/* out: TRUE if accepted */
|
||||
/************************************************************************
|
||||
Decrements the count of open MySQL handles to a table. */
|
||||
|
||||
|
@ -219,6 +207,17 @@ dict_table_referenced_by_foreign_key(
|
|||
/* out: TRUE if table is referenced by a
|
||||
foreign key */
|
||||
dict_table_t* table); /* in: InnoDB table */
|
||||
/**************************************************************************
|
||||
Determines whether a string starts with the specified keyword. */
|
||||
|
||||
ibool
|
||||
dict_str_starts_with_keyword(
|
||||
/*=========================*/
|
||||
/* out: TRUE if str starts
|
||||
with keyword */
|
||||
void* mysql_thd, /* in: MySQL thread handle */
|
||||
const char* str, /* in: string to scan for keyword */
|
||||
const char* keyword); /* in: keyword to look for */
|
||||
/*************************************************************************
|
||||
Scans a table create SQL string and adds to the data dictionary
|
||||
the foreign key constraints declared in the string. This function
|
||||
|
@ -265,17 +264,16 @@ dict_foreign_parse_drop_constraints(
|
|||
const char*** constraints_to_drop); /* out: id's of the
|
||||
constraints to drop */
|
||||
/**************************************************************************
|
||||
Returns a table object and memoryfixes it. NOTE! This is a high-level
|
||||
function to be used mainly from outside the 'dict' directory. Inside this
|
||||
directory dict_table_get_low is usually the appropriate function. */
|
||||
Returns a table object. NOTE! This is a high-level function to be used
|
||||
mainly from outside the 'dict' directory. Inside this directory
|
||||
dict_table_get_low is usually the appropriate function. */
|
||||
|
||||
dict_table_t*
|
||||
dict_table_get(
|
||||
/*===========*/
|
||||
/* out: table, NULL if
|
||||
does not exist */
|
||||
const char* table_name, /* in: table name */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
const char* table_name); /* in: table name */
|
||||
/**************************************************************************
|
||||
Returns a table object and increments MySQL open handle count on the table.
|
||||
*/
|
||||
|
@ -285,10 +283,9 @@ dict_table_get_and_increment_handle_count(
|
|||
/*======================================*/
|
||||
/* out: table, NULL if
|
||||
does not exist */
|
||||
const char* table_name, /* in: table name */
|
||||
trx_t* trx); /* in: transaction handle or NULL */
|
||||
const char* table_name); /* in: table name */
|
||||
/**************************************************************************
|
||||
Returns a table object, based on table id, and memoryfixes it. */
|
||||
Returns a table object based on table id. */
|
||||
|
||||
dict_table_t*
|
||||
dict_table_get_on_id(
|
||||
|
@ -297,21 +294,13 @@ dict_table_get_on_id(
|
|||
dulint table_id, /* in: table id */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
/**************************************************************************
|
||||
Returns a table object, based on table id, and memoryfixes it. */
|
||||
Returns a table object based on table id. */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_get_on_id_low(
|
||||
/*=====================*/
|
||||
/* out: table, NULL if does not exist */
|
||||
dulint table_id, /* in: table id */
|
||||
trx_t* trx); /* in: transaction handle */
|
||||
/**************************************************************************
|
||||
Releases a table from being memoryfixed. Currently this has no relevance. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_table_release(
|
||||
/*===============*/
|
||||
dict_table_t* table); /* in: table to be released */
|
||||
dulint table_id); /* in: table id */
|
||||
/**************************************************************************
|
||||
Checks if a table is in the dictionary cache. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -545,14 +545,13 @@ dict_table_get_low(
|
|||
}
|
||||
|
||||
/**************************************************************************
|
||||
Returns a table object, based on table id, and memoryfixes it. */
|
||||
Returns a table object based on table id. */
|
||||
UNIV_INLINE
|
||||
dict_table_t*
|
||||
dict_table_get_on_id_low(
|
||||
/*=====================*/
|
||||
/* out: table, NULL if does not exist */
|
||||
dulint table_id, /* in: table id */
|
||||
trx_t* trx) /* in: transaction handle */
|
||||
dulint table_id) /* in: table id */
|
||||
{
|
||||
dict_table_t* table;
|
||||
ulint fold;
|
||||
|
@ -560,7 +559,6 @@ dict_table_get_on_id_low(
|
|||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
UT_NOT_USED(trx);
|
||||
|
||||
/* Look for the table name in the hash table */
|
||||
fold = ut_fold_dulint(table_id);
|
||||
|
@ -571,32 +569,11 @@ dict_table_get_on_id_low(
|
|||
table = dict_load_table_on_id(table_id);
|
||||
}
|
||||
|
||||
if (table != NULL) {
|
||||
table->mem_fix++;
|
||||
|
||||
/* lock_push(trx, table, LOCK_DICT_MEM_FIX) */
|
||||
}
|
||||
|
||||
/* TODO: should get the type information from MySQL */
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Releases a table from being memoryfixed. Currently this has no relevance. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
dict_table_release(
|
||||
/*===============*/
|
||||
dict_table_t* table) /* in: table to be released */
|
||||
{
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
table->mem_fix--;
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Returns an index object. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -169,10 +169,6 @@ struct dict_tree_struct{
|
|||
the same memory cache line */
|
||||
rw_lock_t lock; /* read-write lock protecting the upper levels
|
||||
of the index tree */
|
||||
ulint mem_fix;/* count of how many times this tree
|
||||
struct has been memoryfixed (by mini-
|
||||
transactions wanting to access the index
|
||||
tree) */
|
||||
dict_index_t* tree_index; /* the index stored in the
|
||||
index tree */
|
||||
ulint magic_n;/* magic number */
|
||||
|
@ -315,9 +311,6 @@ struct dict_table_struct{
|
|||
which refer to this table */
|
||||
UT_LIST_NODE_T(dict_table_t)
|
||||
table_LRU; /* node of the LRU list of tables */
|
||||
ulint mem_fix;/* count of how many times the table
|
||||
and its indexes has been fixed in memory;
|
||||
currently NOT used */
|
||||
ulint n_mysql_handles_opened;
|
||||
/* count of how many handles MySQL has opened
|
||||
to this table; dropping of the table is
|
||||
|
@ -348,6 +341,12 @@ struct dict_table_struct{
|
|||
had an IX lock on */
|
||||
UT_LIST_BASE_NODE_T(lock_t)
|
||||
locks; /* list of locks on the table */
|
||||
ulint max_row_size;
|
||||
/* maximum size of a single row in the
|
||||
table, not guaranteed to be especially
|
||||
accurate. it's ULINT_MAX if there are
|
||||
unbounded variable-width fields. initialized
|
||||
in dict_table_add_to_cache. */
|
||||
/*----------------------*/
|
||||
ibool does_not_fit_in_memory;
|
||||
/* this field is used to specify in simulations
|
||||
|
|
|
@ -57,9 +57,21 @@ extern fil_addr_t fil_addr_null;
|
|||
page */
|
||||
#define FIL_PAGE_OFFSET 4 /* page offset inside space */
|
||||
#define FIL_PAGE_PREV 8 /* if there is a 'natural' predecessor
|
||||
of the page, its offset */
|
||||
of the page, its offset.
|
||||
Otherwise FIL_NULL.
|
||||
This field is not set on BLOB pages,
|
||||
which are stored as a singly-linked
|
||||
list. See also FIL_PAGE_NEXT. */
|
||||
#define FIL_PAGE_NEXT 12 /* if there is a 'natural' successor
|
||||
of the page, its offset */
|
||||
of the page, its offset.
|
||||
Otherwise FIL_NULL.
|
||||
B-tree index pages
|
||||
(FIL_PAGE_TYPE contains FIL_PAGE_INDEX)
|
||||
on the same PAGE_LEVEL are maintained
|
||||
as a doubly linked list via
|
||||
FIL_PAGE_PREV and FIL_PAGE_NEXT
|
||||
in the collation order of the
|
||||
smallest user record on each page. */
|
||||
#define FIL_PAGE_LSN 16 /* lsn of the end of the newest
|
||||
modification log record to the page */
|
||||
#define FIL_PAGE_TYPE 24 /* file page type: FIL_PAGE_INDEX,...,
|
||||
|
|
|
@ -360,24 +360,28 @@ description takes less than 1 byte; a descriptor page is repeated every
|
|||
this many file pages */
|
||||
#define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE
|
||||
|
||||
/* The space low address page map, and also offsets for extent descriptor and
|
||||
bitmap pages which are repeated always after XDES_DESCRIBED_PER_PAGE more
|
||||
pages: */
|
||||
/* The space low address page map */
|
||||
/*--------------------------------------*/
|
||||
#define FSP_XDES_OFFSET 0
|
||||
#define FSP_IBUF_BITMAP_OFFSET 1
|
||||
/* The following two pages are repeated
|
||||
every XDES_DESCRIBED_PER_PAGE pages in
|
||||
every tablespace. */
|
||||
#define FSP_XDES_OFFSET 0 /* extent descriptor */
|
||||
#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */
|
||||
/* The ibuf bitmap pages are the ones whose
|
||||
page number is the number above plus a
|
||||
multiple of XDES_DESCRIBED_PER_PAGE */
|
||||
#define FSP_FIRST_INODE_PAGE_NO 2
|
||||
#define FSP_IBUF_HEADER_PAGE_NO 3
|
||||
#define FSP_IBUF_TREE_ROOT_PAGE_NO 4
|
||||
|
||||
#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */
|
||||
/* The following pages exist
|
||||
in the system tablespace (space 0). */
|
||||
#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */
|
||||
#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */
|
||||
/* The ibuf tree root page number in
|
||||
tablespace 0; its fseg inode is on the page
|
||||
number FSP_FIRST_INODE_PAGE_NO */
|
||||
#define FSP_TRX_SYS_PAGE_NO 5
|
||||
#define FSP_FIRST_RSEG_PAGE_NO 6
|
||||
#define FSP_DICT_HDR_PAGE_NO 7
|
||||
#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */
|
||||
#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */
|
||||
#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */
|
||||
/*--------------------------------------*/
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
|
|
22
storage/innobase/include/ha_prototypes.h
Normal file
22
storage/innobase/include/ha_prototypes.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef HA_INNODB_PROTOTYPES_H
|
||||
#define HA_INNODB_PROTOTYPES_H
|
||||
|
||||
/* Prototypes for global functions in ha_innodb.cc that are called by
|
||||
InnoDB's C-code. */
|
||||
|
||||
/*************************************************************************
|
||||
Wrapper around MySQL's copy_and_convert function, see it for
|
||||
documentation. */
|
||||
|
||||
ulint
|
||||
innobase_convert_string(
|
||||
/*====================*/
|
||||
void* to,
|
||||
ulint to_length,
|
||||
CHARSET_INFO* to_cs,
|
||||
const void* from,
|
||||
ulint from_length,
|
||||
CHARSET_INFO* from_cs,
|
||||
uint* errors);
|
||||
|
||||
#endif
|
|
@ -267,6 +267,7 @@ ibuf_parse_bitmap_init(
|
|||
byte* end_ptr,/* in: buffer end */
|
||||
page_t* page, /* in: page or NULL */
|
||||
mtr_t* mtr); /* in: mtr or NULL */
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
/**********************************************************************
|
||||
Gets the ibuf count for a given page. */
|
||||
|
||||
|
@ -277,6 +278,7 @@ ibuf_count_get(
|
|||
currently buffered for this page */
|
||||
ulint space, /* in: space id */
|
||||
ulint page_no);/* in: page number */
|
||||
#endif
|
||||
/**********************************************************************
|
||||
Looks if the insert buffer is empty. */
|
||||
|
||||
|
|
|
@ -322,6 +322,44 @@ mem_heap_strcat(
|
|||
const char* s1, /* in: string 1 */
|
||||
const char* s2); /* in: string 2 */
|
||||
|
||||
/**************************************************************************
|
||||
Duplicate a block of data, allocated from a memory heap. */
|
||||
|
||||
void*
|
||||
mem_heap_dup(
|
||||
/*=========*/
|
||||
/* out, own: a copy of the data */
|
||||
mem_heap_t* heap, /* in: memory heap where copy is allocated */
|
||||
const void* data, /* in: data to be copied */
|
||||
ulint len); /* in: length of data, in bytes */
|
||||
|
||||
/**************************************************************************
|
||||
Concatenate two memory blocks and return the result, using a memory heap. */
|
||||
|
||||
void*
|
||||
mem_heap_cat(
|
||||
/*=========*/
|
||||
/* out, own: the result */
|
||||
mem_heap_t* heap, /* in: memory heap where result is allocated */
|
||||
const void* b1, /* in: block 1 */
|
||||
ulint len1, /* in: length of b1, in bytes */
|
||||
const void* b2, /* in: block 2 */
|
||||
ulint len2); /* in: length of b2, in bytes */
|
||||
|
||||
/********************************************************************
|
||||
A simple (s)printf replacement that dynamically allocates the space for the
|
||||
formatted string from the given heap. This supports a very limited set of
|
||||
the printf syntax: types 's' and 'u' and length modifier 'l' (which is
|
||||
required for the 'u' type). */
|
||||
|
||||
char*
|
||||
mem_heap_printf(
|
||||
/*============*/
|
||||
/* out: heap-allocated formatted string */
|
||||
mem_heap_t* heap, /* in: memory heap */
|
||||
const char* format, /* in: format string */
|
||||
...) __attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
/**********************************************************************
|
||||
Goes through the list of all allocated mem blocks, checks their magic
|
||||
|
|
|
@ -531,6 +531,16 @@ pars_info_add_function(
|
|||
pars_user_func_cb_t func, /* in: function address */
|
||||
void* arg); /* in: user-supplied argument */
|
||||
|
||||
/********************************************************************
|
||||
Add bound id. */
|
||||
|
||||
void
|
||||
pars_info_add_id(
|
||||
/*=============*/
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name, /* in: name */
|
||||
const char* id); /* in: id */
|
||||
|
||||
/********************************************************************
|
||||
Get user function with the given name.*/
|
||||
|
||||
|
@ -553,6 +563,17 @@ pars_info_get_bound_lit(
|
|||
pars_info_t* info, /* in: info struct */
|
||||
const char* name); /* in: bound literal name to find */
|
||||
|
||||
/********************************************************************
|
||||
Get bound id with the given name.*/
|
||||
|
||||
pars_bound_id_t*
|
||||
pars_info_get_bound_id(
|
||||
/*===================*/
|
||||
/* out: bound id, or NULL if not
|
||||
found */
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name); /* in: bound id name to find */
|
||||
|
||||
|
||||
/* Extra information supplied for pars_sql(). */
|
||||
struct pars_info_struct {
|
||||
|
@ -562,6 +583,8 @@ struct pars_info_struct {
|
|||
(pars_user_func_t*) */
|
||||
ib_vector_t* bound_lits; /* bound literals, or NULL
|
||||
(pars_bound_lit_t*) */
|
||||
ib_vector_t* bound_ids; /* bound ids, or NULL
|
||||
(pars_bound_id_t*) */
|
||||
|
||||
ibool graph_owns_us; /* if TRUE (which is the default),
|
||||
que_graph_free() will free us */
|
||||
|
@ -583,6 +606,12 @@ struct pars_bound_lit_struct {
|
|||
ulint prtype; /* precise type, e.g. DATA_UNSIGNED */
|
||||
};
|
||||
|
||||
/* Bound id. */
|
||||
struct pars_bound_id_struct {
|
||||
const char* name; /* name */
|
||||
const char* id; /* id */
|
||||
};
|
||||
|
||||
/* Struct used to denote a reserved word in a parsing tree */
|
||||
struct pars_res_word_struct{
|
||||
int code; /* the token code for the reserved word from
|
||||
|
|
|
@ -82,6 +82,16 @@ sym_tab_add_id(
|
|||
byte* name, /* in: identifier name */
|
||||
ulint len); /* in: identifier length */
|
||||
|
||||
/**********************************************************************
|
||||
Add a bound identifier to a symbol table. */
|
||||
|
||||
sym_node_t*
|
||||
sym_tab_add_bound_id(
|
||||
/*===========*/
|
||||
/* out: symbol table node */
|
||||
sym_tab_t* sym_tab, /* in: symbol table */
|
||||
const char* name); /* in: name of bound id */
|
||||
|
||||
#define SYM_CLUST_FIELD_NO 0
|
||||
#define SYM_SEC_FIELD_NO 1
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ Created 1/11/1998 Heikki Tuuri
|
|||
typedef struct pars_info_struct pars_info_t;
|
||||
typedef struct pars_user_func_struct pars_user_func_t;
|
||||
typedef struct pars_bound_lit_struct pars_bound_lit_t;
|
||||
typedef struct pars_bound_id_struct pars_bound_id_t;
|
||||
typedef struct sym_node_struct sym_node_t;
|
||||
typedef struct sym_tab_struct sym_tab_t;
|
||||
typedef struct pars_res_word_struct pars_res_word_t;
|
||||
|
|
|
@ -19,8 +19,10 @@ Created 5/30/1994 Heikki Tuuri
|
|||
#define REC_MAX_HEAP_NO (2 * 8192 - 1)
|
||||
#define REC_MAX_N_OWNED (16 - 1)
|
||||
|
||||
/* Flag denoting the predefined minimum record: this bit is ORed in the 4
|
||||
info bits of a record */
|
||||
/* Info bit denoting the predefined minimum record: this bit is set
|
||||
if and only if the record is the first user record on a non-leaf
|
||||
B-tree page that is the leftmost page on its level
|
||||
(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */
|
||||
#define REC_INFO_MIN_REC_FLAG 0x10UL
|
||||
|
||||
/* Number of extra bytes in an old-style record,
|
||||
|
|
|
@ -56,9 +56,7 @@ struct purge_node_struct{
|
|||
determined by ref was found in the clustered
|
||||
index, and we were able to position pcur on
|
||||
it */
|
||||
dict_table_t* table; /* table where purge is done; NOTE that the
|
||||
table has to be released explicitly with
|
||||
dict_table_release */
|
||||
dict_table_t* table; /* table where purge is done */
|
||||
ulint cmpl_info;/* compiler analysis info of an update */
|
||||
upd_t* update; /* update vector for a clustered index record */
|
||||
dtuple_t* ref; /* NULL, or row reference to the next row to
|
||||
|
|
|
@ -84,9 +84,7 @@ struct undo_node_struct{
|
|||
record */
|
||||
btr_pcur_t pcur; /* persistent cursor used in searching the
|
||||
clustered index record */
|
||||
dict_table_t* table; /* table where undo is done; NOTE that the
|
||||
table has to be released explicitly with
|
||||
dict_table_release */
|
||||
dict_table_t* table; /* table where undo is done */
|
||||
ulint cmpl_info;/* compiler analysis of an update */
|
||||
upd_t* update; /* update vector for a clustered index record */
|
||||
dtuple_t* ref; /* row reference to the next row to handle */
|
||||
|
|
|
@ -18,6 +18,9 @@ Created 10/10/1995 Heikki Tuuri
|
|||
|
||||
extern const char* srv_main_thread_op_info;
|
||||
|
||||
/* Prefix used by MySQL to indicate pre-5.1 table name encoding */
|
||||
extern const char srv_mysql50_table_name_prefix[9];
|
||||
|
||||
/* When this event is set the lock timeout and InnoDB monitor
|
||||
thread starts running */
|
||||
extern os_event_t srv_lock_timeout_thread_event;
|
||||
|
|
|
@ -61,7 +61,7 @@ Creates, or rather, initializes an rw-lock object in a specified memory
|
|||
location (which must be appropriately aligned). The rw-lock is initialized
|
||||
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
|
||||
is necessary only if the memory block containing it is freed. */
|
||||
#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L)
|
||||
#define rw_lock_create(L, level) rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
|
||||
|
||||
/*=====================*/
|
||||
/**********************************************************************
|
||||
|
@ -74,6 +74,7 @@ void
|
|||
rw_lock_create_func(
|
||||
/*================*/
|
||||
rw_lock_t* lock, /* in: pointer to memory */
|
||||
ulint level, /* in: level */
|
||||
const char* cfile_name, /* in: file name where created */
|
||||
ulint cline, /* in: file line where created */
|
||||
const char* cmutex_name); /* in: mutex name */
|
||||
|
@ -299,14 +300,6 @@ rw_lock_x_unlock_direct(
|
|||
/*====================*/
|
||||
rw_lock_t* lock); /* in: rw-lock */
|
||||
/**********************************************************************
|
||||
Sets the rw-lock latching level field. */
|
||||
|
||||
void
|
||||
rw_lock_set_level(
|
||||
/*==============*/
|
||||
rw_lock_t* lock, /* in: rw-lock */
|
||||
ulint level); /* in: level */
|
||||
/**********************************************************************
|
||||
Returns the value of writer_count for the lock. Does not reserve the lock
|
||||
mutex, so the caller must be sure it is not changed during the call. */
|
||||
UNIV_INLINE
|
||||
|
@ -448,8 +441,8 @@ struct rw_lock_struct {
|
|||
/* In the debug version: pointer to the debug
|
||||
info list of the lock */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint level; /* Level in the global latching
|
||||
order; default SYNC_LEVEL_NONE */
|
||||
|
||||
ulint level; /* Level in the global latching order. */
|
||||
const char* cfile_name;/* File name where lock created */
|
||||
ulint cline; /* Line where created */
|
||||
const char* last_s_file_name;/* File name where last s-locked */
|
||||
|
|
|
@ -39,7 +39,7 @@ location (which must be appropriately aligned). The mutex is initialized
|
|||
in the reset state. Explicit freeing of the mutex with mutex_free is
|
||||
necessary only if the memory block containing it is freed. */
|
||||
|
||||
#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, #M)
|
||||
#define mutex_create(M, level) mutex_create_func((M), (level), __FILE__, __LINE__, #M)
|
||||
/*===================*/
|
||||
/**********************************************************************
|
||||
Creates, or rather, initializes a mutex object in a specified memory
|
||||
|
@ -51,6 +51,7 @@ void
|
|||
mutex_create_func(
|
||||
/*==============*/
|
||||
mutex_t* mutex, /* in: pointer to memory */
|
||||
ulint level, /* in: level */
|
||||
const char* cfile_name, /* in: file name where created */
|
||||
ulint cline, /* in: file line where created */
|
||||
const char* cmutex_name); /* in: mutex name */
|
||||
|
@ -155,14 +156,6 @@ mutex_validate(
|
|||
/*===========*/
|
||||
mutex_t* mutex);
|
||||
/**********************************************************************
|
||||
Sets the mutex latching level field. */
|
||||
|
||||
void
|
||||
mutex_set_level(
|
||||
/*============*/
|
||||
mutex_t* mutex, /* in: mutex */
|
||||
ulint level); /* in: level */
|
||||
/**********************************************************************
|
||||
Adds a latch and its level in the thread level array. Allocates the memory
|
||||
for the array if called first time for this OS thread. Makes the checks
|
||||
against other latch levels stored in the array for this thread. */
|
||||
|
@ -171,8 +164,8 @@ void
|
|||
sync_thread_add_level(
|
||||
/*==================*/
|
||||
void* latch, /* in: pointer to a mutex or an rw-lock */
|
||||
ulint level); /* in: level in the latching order; if SYNC_LEVEL_NONE,
|
||||
nothing is done */
|
||||
ulint level); /* in: level in the latching order; if
|
||||
SYNC_LEVEL_VARYING, nothing is done */
|
||||
/**********************************************************************
|
||||
Removes a latch from the thread level array if it is found there. */
|
||||
|
||||
|
@ -383,7 +376,12 @@ or row lock! */
|
|||
#define SYNC_USER_TRX_LOCK 9999
|
||||
#define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress
|
||||
latching order checking */
|
||||
#define SYNC_LEVEL_NONE 2000 /* default: level not defined */
|
||||
#define SYNC_LEVEL_VARYING 2000 /* Level is varying. Only used with
|
||||
buffer pool page locks, which do not
|
||||
have a fixed level, but instead have
|
||||
their level set after the page is
|
||||
locked; see e.g.
|
||||
ibuf_bitmap_get_map_page(). */
|
||||
#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
|
||||
this in X-mode, implicit or backround
|
||||
operations purge, rollback, foreign
|
||||
|
@ -426,6 +424,7 @@ or row lock! */
|
|||
#define SYNC_TRX_SYS_HEADER 290
|
||||
#define SYNC_LOG 170
|
||||
#define SYNC_RECV 168
|
||||
#define SYNC_WORK_QUEUE 161
|
||||
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
|
||||
heap that can be extended to the
|
||||
buffer pool, its logical level is
|
||||
|
@ -472,8 +471,7 @@ struct mutex_struct {
|
|||
os_thread_id_t thread_id; /* Debug version: The thread id of the
|
||||
thread which locked the mutex. */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint level; /* Level in the global latching
|
||||
order; default SYNC_LEVEL_NONE */
|
||||
ulint level; /* Level in the global latching order */
|
||||
const char* cfile_name;/* File name where mutex created */
|
||||
ulint cline; /* Line where created */
|
||||
ulint magic_n;
|
||||
|
|
|
@ -82,7 +82,7 @@ memory is read outside the allocated blocks. */
|
|||
|
||||
/* Make a non-inline debug version */
|
||||
|
||||
/*
|
||||
#if 0
|
||||
#define UNIV_DEBUG
|
||||
#define UNIV_MEM_DEBUG
|
||||
#define UNIV_IBUF_DEBUG
|
||||
|
@ -90,8 +90,10 @@ memory is read outside the allocated blocks. */
|
|||
#define UNIV_SEARCH_DEBUG
|
||||
#define UNIV_SYNC_PERF_STAT
|
||||
#define UNIV_SEARCH_PERF_STAT
|
||||
#define UNIV_SRV_PRINT_LATCH_WAITS;
|
||||
*/
|
||||
#define UNIV_SRV_PRINT_LATCH_WAITS
|
||||
#endif
|
||||
|
||||
#define UNIV_BTR_DEBUG
|
||||
#define UNIV_LIGHT_MEM_DEBUG
|
||||
|
||||
#define YYDEBUG 1
|
||||
|
|
|
@ -41,13 +41,22 @@ void ut_dbg_panic(void);
|
|||
/* Stop threads in ut_a(). */
|
||||
# define UT_DBG_STOP while (0) /* We do not do this on NetWare */
|
||||
#else /* __NETWARE__ */
|
||||
# if defined(__WIN__) || defined(__INTEL_COMPILER)
|
||||
# undef UT_DBG_USE_ABORT
|
||||
# elif defined(__GNUC__) && (__GNUC__ > 2)
|
||||
# define UT_DBG_USE_ABORT
|
||||
# endif
|
||||
|
||||
# ifndef UT_DBG_USE_ABORT
|
||||
/* A null pointer that will be dereferenced to trigger a memory trap */
|
||||
extern ulint* ut_dbg_null_ptr;
|
||||
# endif
|
||||
|
||||
# if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
|
||||
/* Flag for indicating that all threads should stop. This will be set
|
||||
by ut_dbg_assertion_failed(). */
|
||||
extern ibool ut_dbg_stop_threads;
|
||||
|
||||
/* A null pointer that will be dereferenced to trigger a memory trap */
|
||||
extern ulint* ut_dbg_null_ptr;
|
||||
|
||||
/*****************************************************************
|
||||
Stop a thread after assertion failure. */
|
||||
|
||||
|
@ -56,7 +65,14 @@ ut_dbg_stop_thread(
|
|||
/*===============*/
|
||||
const char* file,
|
||||
ulint line);
|
||||
# endif
|
||||
|
||||
# ifdef UT_DBG_USE_ABORT
|
||||
/* Abort the execution. */
|
||||
# define UT_DBG_PANIC abort()
|
||||
/* Stop threads (null operation) */
|
||||
# define UT_DBG_STOP while (0)
|
||||
# else /* UT_DBG_USE_ABORT */
|
||||
/* Abort the execution. */
|
||||
# define UT_DBG_PANIC \
|
||||
if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL
|
||||
|
@ -65,6 +81,7 @@ ut_dbg_stop_thread(
|
|||
if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \
|
||||
ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \
|
||||
} while (0)
|
||||
# endif /* UT_DBG_USE_ABORT */
|
||||
#endif /* __NETWARE__ */
|
||||
|
||||
/* Abort execution if EXPR does not evaluate to nonzero. */
|
||||
|
|
148
storage/innobase/include/ut0list.h
Normal file
148
storage/innobase/include/ut0list.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/***********************************************************************
|
||||
A double-linked list. This differs from the one in ut0lst.h in that in this
|
||||
one, each list node contains a pointer to the data, whereas the one in
|
||||
ut0lst.h uses a strategy where the list pointers are embedded in the data
|
||||
items themselves.
|
||||
|
||||
Use this one when you need to store arbitrary data in the list where you
|
||||
can't embed the list pointers in the data, if a data item needs to be
|
||||
stored in multiple lists, etc.
|
||||
|
||||
Note about the memory management: ib_list_t is a fixed-size struct whose
|
||||
allocation/deallocation is done through ib_list_create/ib_list_free, but the
|
||||
memory for the list nodes is allocated through a user-given memory heap,
|
||||
which can either be the same for all nodes or vary per node. Most users will
|
||||
probably want to create a memory heap to store the item-specific data, and
|
||||
pass in this same heap to the list node creation functions, thus
|
||||
automatically freeing the list node when the item's heap is freed.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
|
||||
#ifndef IB_LIST_H
|
||||
#define IB_LIST_H
|
||||
|
||||
#include "mem0mem.h"
|
||||
|
||||
typedef struct ib_list_struct ib_list_t;
|
||||
typedef struct ib_list_node_struct ib_list_node_t;
|
||||
typedef struct ib_list_helper_struct ib_list_helper_t;
|
||||
|
||||
/********************************************************************
|
||||
Create a new list using mem_alloc. Lists created with this function must be
|
||||
freed with ib_list_free. */
|
||||
|
||||
ib_list_t*
|
||||
ib_list_create(void);
|
||||
/*=================*/
|
||||
/* out: list */
|
||||
|
||||
|
||||
/********************************************************************
|
||||
Create a new list using the given heap. ib_list_free MUST NOT BE CALLED for
|
||||
lists created with this function. */
|
||||
|
||||
ib_list_t*
|
||||
ib_list_create_heap(
|
||||
/*================*/
|
||||
/* out: list */
|
||||
mem_heap_t* heap); /* in: memory heap to use */
|
||||
|
||||
/********************************************************************
|
||||
Free a list. */
|
||||
|
||||
void
|
||||
ib_list_free(
|
||||
/*=========*/
|
||||
ib_list_t* list); /* in: list */
|
||||
|
||||
/********************************************************************
|
||||
Add the data to the start of the list. */
|
||||
|
||||
ib_list_node_t*
|
||||
ib_list_add_first(
|
||||
/*==============*/
|
||||
/* out: new list node*/
|
||||
ib_list_t* list, /* in: list */
|
||||
void* data, /* in: data */
|
||||
mem_heap_t* heap); /* in: memory heap to use */
|
||||
|
||||
/********************************************************************
|
||||
Add the data to the end of the list. */
|
||||
|
||||
ib_list_node_t*
|
||||
ib_list_add_last(
|
||||
/*=============*/
|
||||
/* out: new list node*/
|
||||
ib_list_t* list, /* in: list */
|
||||
void* data, /* in: data */
|
||||
mem_heap_t* heap); /* in: memory heap to use */
|
||||
|
||||
/********************************************************************
|
||||
Add the data after the indicated node. */
|
||||
|
||||
ib_list_node_t*
|
||||
ib_list_add_after(
|
||||
/*==============*/
|
||||
/* out: new list node*/
|
||||
ib_list_t* list, /* in: list */
|
||||
ib_list_node_t* prev_node, /* in: node preceding new node (can
|
||||
be NULL) */
|
||||
void* data, /* in: data */
|
||||
mem_heap_t* heap); /* in: memory heap to use */
|
||||
|
||||
/********************************************************************
|
||||
Remove the node from the list. */
|
||||
|
||||
void
|
||||
ib_list_remove(
|
||||
/*===========*/
|
||||
ib_list_t* list, /* in: list */
|
||||
ib_list_node_t* node); /* in: node to remove */
|
||||
|
||||
/********************************************************************
|
||||
Get the first node in the list. */
|
||||
UNIV_INLINE
|
||||
ib_list_node_t*
|
||||
ib_list_get_first(
|
||||
/*==============*/
|
||||
/* out: first node, or NULL */
|
||||
ib_list_t* list); /* in: list */
|
||||
|
||||
/********************************************************************
|
||||
Get the last node in the list. */
|
||||
UNIV_INLINE
|
||||
ib_list_node_t*
|
||||
ib_list_get_last(
|
||||
/*=============*/
|
||||
/* out: last node, or NULL */
|
||||
ib_list_t* list); /* in: list */
|
||||
|
||||
/* List. */
|
||||
struct ib_list_struct {
|
||||
ib_list_node_t* first; /* first node */
|
||||
ib_list_node_t* last; /* last node */
|
||||
ibool is_heap_list; /* TRUE if this list was
|
||||
allocated through a heap */
|
||||
};
|
||||
|
||||
/* A list node. */
|
||||
struct ib_list_node_struct {
|
||||
ib_list_node_t* prev; /* previous node */
|
||||
ib_list_node_t* next; /* next node */
|
||||
void* data; /* user data */
|
||||
};
|
||||
|
||||
/* Quite often, the only additional piece of data you need is the per-item
|
||||
memory heap, so we have this generic struct available to use in those
|
||||
cases. */
|
||||
struct ib_list_helper_struct {
|
||||
mem_heap_t* heap; /* memory heap */
|
||||
void* data; /* user data */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ut0list.ic"
|
||||
#endif
|
||||
|
||||
#endif
|
23
storage/innobase/include/ut0list.ic
Normal file
23
storage/innobase/include/ut0list.ic
Normal file
|
@ -0,0 +1,23 @@
|
|||
/********************************************************************
|
||||
Get the first node in the list. */
|
||||
UNIV_INLINE
|
||||
ib_list_node_t*
|
||||
ib_list_get_first(
|
||||
/*==============*/
|
||||
/* out: first node, or NULL */
|
||||
ib_list_t* list) /* in: list */
|
||||
{
|
||||
return(list->first);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Get the last node in the list. */
|
||||
UNIV_INLINE
|
||||
ib_list_node_t*
|
||||
ib_list_get_last(
|
||||
/*=============*/
|
||||
/* out: last node, or NULL */
|
||||
ib_list_t* list) /* in: list */
|
||||
{
|
||||
return(list->last);
|
||||
}
|
|
@ -224,6 +224,7 @@ ut_print_name(
|
|||
/*==========*/
|
||||
FILE* f, /* in: output stream */
|
||||
struct trx_struct*trx, /* in: transaction */
|
||||
ibool table_id,/* in: TRUE=decode table name */
|
||||
const char* name); /* in: name to print */
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -234,6 +235,7 @@ ut_print_namel(
|
|||
/*===========*/
|
||||
FILE* f, /* in: output stream */
|
||||
struct trx_struct*trx, /* in: transaction (NULL=no quotes) */
|
||||
ibool table_id,/* in: TRUE=decode table name */
|
||||
const char* name, /* in: name to print */
|
||||
ulint namelen);/* in: length of name */
|
||||
|
||||
|
|
60
storage/innobase/include/ut0wqueue.h
Normal file
60
storage/innobase/include/ut0wqueue.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/***********************************************************************
|
||||
A Work queue. Threads can add work items to the queue and other threads can
|
||||
wait for work items to be available and take them off the queue for
|
||||
processing.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
#ifndef IB_WORK_QUEUE_H
|
||||
#define IB_WORK_QUEUE_H
|
||||
|
||||
#include "ut0list.h"
|
||||
#include "mem0mem.h"
|
||||
#include "os0sync.h"
|
||||
#include "sync0types.h"
|
||||
|
||||
typedef struct ib_wqueue_struct ib_wqueue_t;
|
||||
|
||||
/********************************************************************
|
||||
Create a new work queue. */
|
||||
|
||||
ib_wqueue_t*
|
||||
ib_wqueue_create(void);
|
||||
/*===================*/
|
||||
/* out: work queue */
|
||||
|
||||
/********************************************************************
|
||||
Free a work queue. */
|
||||
|
||||
void
|
||||
ib_wqueue_free(
|
||||
/*===========*/
|
||||
ib_wqueue_t* wq); /* in: work queue */
|
||||
|
||||
/********************************************************************
|
||||
Add a work item to the queue. */
|
||||
|
||||
void
|
||||
ib_wqueue_add(
|
||||
/*==========*/
|
||||
ib_wqueue_t* wq, /* in: work queue */
|
||||
void* item, /* in: work item */
|
||||
mem_heap_t* heap); /* in: memory heap to use for allocating the
|
||||
list node */
|
||||
|
||||
/********************************************************************
|
||||
Wait for a work item to appear in the queue. */
|
||||
|
||||
void*
|
||||
ib_wqueue_wait(
|
||||
/* out: work item */
|
||||
ib_wqueue_t* wq); /* in: work queue */
|
||||
|
||||
/* Work queue. */
|
||||
struct ib_wqueue_struct {
|
||||
mutex_t mutex; /* mutex protecting everything */
|
||||
ib_list_t* items; /* work item list */
|
||||
os_event_t event; /* event we use to signal additions to list */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1860,7 +1860,7 @@ lock_rec_enqueue_waiting(
|
|||
fputs(
|
||||
" InnoDB: Error: a record lock wait happens in a dictionary operation!\n"
|
||||
"InnoDB: Table name ", stderr);
|
||||
ut_print_name(stderr, trx, index->table_name);
|
||||
ut_print_name(stderr, trx, TRUE, index->table_name);
|
||||
fputs(".\n"
|
||||
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n",
|
||||
stderr);
|
||||
|
@ -1899,7 +1899,7 @@ lock_rec_enqueue_waiting(
|
|||
if (lock_print_waits) {
|
||||
fprintf(stderr, "Lock wait for trx %lu in index ",
|
||||
(ulong) ut_dulint_get_low(trx->id));
|
||||
ut_print_name(stderr, trx, index->name);
|
||||
ut_print_name(stderr, trx, FALSE, index->name);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
|
@ -3555,7 +3555,7 @@ lock_table_enqueue_waiting(
|
|||
fputs(
|
||||
" InnoDB: Error: a table lock wait happens in a dictionary operation!\n"
|
||||
"InnoDB: Table name ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs(".\n"
|
||||
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n",
|
||||
stderr);
|
||||
|
@ -4074,7 +4074,8 @@ lock_table_print(
|
|||
ut_a(lock_get_type(lock) == LOCK_TABLE);
|
||||
|
||||
fputs("TABLE LOCK table ", file);
|
||||
ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name);
|
||||
ut_print_name(file, lock->trx, TRUE,
|
||||
lock->un_member.tab_lock.table->name);
|
||||
fprintf(file, " trx id %lu %lu",
|
||||
(ulong) (lock->trx)->id.high, (ulong) (lock->trx)->id.low);
|
||||
|
||||
|
|
|
@ -741,8 +741,7 @@ log_init(void)
|
|||
|
||||
log_sys = mem_alloc(sizeof(log_t));
|
||||
|
||||
mutex_create(&(log_sys->mutex));
|
||||
mutex_set_level(&(log_sys->mutex), SYNC_LOG);
|
||||
mutex_create(&log_sys->mutex, SYNC_LOG);
|
||||
|
||||
mutex_enter(&(log_sys->mutex));
|
||||
|
||||
|
@ -798,8 +797,7 @@ log_init(void)
|
|||
log_sys->last_checkpoint_lsn = log_sys->lsn;
|
||||
log_sys->n_pending_checkpoint_writes = 0;
|
||||
|
||||
rw_lock_create(&(log_sys->checkpoint_lock));
|
||||
rw_lock_set_level(&(log_sys->checkpoint_lock), SYNC_NO_ORDER_CHECK);
|
||||
rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
log_sys->checkpoint_buf = ut_align(
|
||||
mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE),
|
||||
|
@ -815,8 +813,7 @@ log_init(void)
|
|||
|
||||
log_sys->n_pending_archive_ios = 0;
|
||||
|
||||
rw_lock_create(&(log_sys->archive_lock));
|
||||
rw_lock_set_level(&(log_sys->archive_lock), SYNC_NO_ORDER_CHECK);
|
||||
rw_lock_create(&log_sys->archive_lock, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
log_sys->archive_buf = NULL;
|
||||
|
||||
|
|
|
@ -112,8 +112,7 @@ recv_sys_create(void)
|
|||
|
||||
recv_sys = mem_alloc(sizeof(recv_sys_t));
|
||||
|
||||
mutex_create(&(recv_sys->mutex));
|
||||
mutex_set_level(&(recv_sys->mutex), SYNC_RECV);
|
||||
mutex_create(&recv_sys->mutex, SYNC_RECV);
|
||||
|
||||
recv_sys->heap = NULL;
|
||||
recv_sys->addr_hash = NULL;
|
||||
|
@ -894,7 +893,6 @@ recv_parse_or_apply_log_rec_body(
|
|||
recv_sys->found_corrupt_log = TRUE;
|
||||
}
|
||||
|
||||
ut_ad(!page || ptr);
|
||||
if (index) {
|
||||
dict_table_t* table = index->table;
|
||||
|
||||
|
|
|
@ -122,8 +122,7 @@ mem_init(
|
|||
/* Initialize the hash table */
|
||||
ut_a(FALSE == mem_hash_initialized);
|
||||
|
||||
mutex_create(&mem_hash_mutex);
|
||||
mutex_set_level(&mem_hash_mutex, SYNC_MEM_HASH);
|
||||
mutex_create(&mem_hash_mutex, SYNC_MEM_HASH);
|
||||
|
||||
for (i = 0; i < MEM_HASH_SIZE; i++) {
|
||||
UT_LIST_INIT(*mem_hash_get_nth_cell(i));
|
||||
|
|
|
@ -17,6 +17,7 @@ Created 6/9/1994 Heikki Tuuri
|
|||
#include "btr0sea.h"
|
||||
#include "srv0srv.h"
|
||||
#include "mem0dbg.c"
|
||||
#include <stdarg.h>
|
||||
|
||||
/*
|
||||
THE MEMORY MANAGEMENT
|
||||
|
@ -110,8 +111,42 @@ mem_heap_strdup(
|
|||
mem_heap_t* heap, /* in: memory heap where string is allocated */
|
||||
const char* str) /* in: string to be copied */
|
||||
{
|
||||
ulint len = strlen(str) + 1;
|
||||
return(memcpy(mem_heap_alloc(heap, len), str, len));
|
||||
return(mem_heap_dup(heap, str, strlen(str) + 1));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Duplicate a block of data, allocated from a memory heap. */
|
||||
|
||||
void*
|
||||
mem_heap_dup(
|
||||
/*=========*/
|
||||
/* out, own: a copy of the data */
|
||||
mem_heap_t* heap, /* in: memory heap where copy is allocated */
|
||||
const void* data, /* in: data to be copied */
|
||||
ulint len) /* in: length of data, in bytes */
|
||||
{
|
||||
return(memcpy(mem_heap_alloc(heap, len), data, len));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Concatenate two memory blocks and return the result, using a memory heap. */
|
||||
|
||||
void*
|
||||
mem_heap_cat(
|
||||
/*=========*/
|
||||
/* out, own: the result */
|
||||
mem_heap_t* heap, /* in: memory heap where result is allocated */
|
||||
const void* b1, /* in: block 1 */
|
||||
ulint len1, /* in: length of b1, in bytes */
|
||||
const void* b2, /* in: block 2 */
|
||||
ulint len2) /* in: length of b2, in bytes */
|
||||
{
|
||||
void* res = mem_heap_alloc(heap, len1 + len2);
|
||||
|
||||
memcpy(res, b1, len1);
|
||||
memcpy(res + len1, b2, len2);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -139,6 +174,150 @@ mem_heap_strcat(
|
|||
return(s);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************
|
||||
Helper function for mem_heap_printf. */
|
||||
static
|
||||
ulint
|
||||
mem_heap_printf_low(
|
||||
/*================*/
|
||||
/* out: length of formatted string,
|
||||
including terminating NUL */
|
||||
char* buf, /* in/out: buffer to store formatted string
|
||||
in, or NULL to just calculate length */
|
||||
const char* format, /* in: format string */
|
||||
va_list ap) /* in: arguments */
|
||||
{
|
||||
ulint len = 0;
|
||||
|
||||
while (*format) {
|
||||
|
||||
/* Does this format specifier have the 'l' length modifier. */
|
||||
ibool is_long = FALSE;
|
||||
|
||||
/* Length of one parameter. */
|
||||
size_t plen;
|
||||
|
||||
if (*format++ != '%') {
|
||||
/* Non-format character. */
|
||||
|
||||
len++;
|
||||
|
||||
if (buf) {
|
||||
*buf++ = *(format - 1);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*format == 'l') {
|
||||
is_long = TRUE;
|
||||
format++;
|
||||
}
|
||||
|
||||
switch (*format++) {
|
||||
case 's':
|
||||
/* string */
|
||||
{
|
||||
char* s = va_arg(ap, char*);
|
||||
|
||||
/* "%ls" is a non-sensical format specifier. */
|
||||
ut_a(!is_long);
|
||||
|
||||
plen = strlen(s);
|
||||
len += plen;
|
||||
|
||||
if (buf) {
|
||||
memcpy(buf, s, plen);
|
||||
buf += plen;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
/* unsigned int */
|
||||
{
|
||||
char tmp[32];
|
||||
unsigned long val;
|
||||
|
||||
/* We only support 'long' values for now. */
|
||||
ut_a(is_long);
|
||||
|
||||
val = va_arg(ap, unsigned long);
|
||||
|
||||
plen = sprintf(tmp, "%lu", val);
|
||||
len += plen;
|
||||
|
||||
if (buf) {
|
||||
memcpy(buf, tmp, plen);
|
||||
buf += plen;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case '%':
|
||||
|
||||
/* "%l%" is a non-sensical format specifier. */
|
||||
ut_a(!is_long);
|
||||
|
||||
len++;
|
||||
|
||||
if (buf) {
|
||||
*buf++ = '%';
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* For the NUL character. */
|
||||
len++;
|
||||
|
||||
if (buf) {
|
||||
*buf = '\0';
|
||||
}
|
||||
|
||||
return(len);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
A simple (s)printf replacement that dynamically allocates the space for the
|
||||
formatted string from the given heap. This supports a very limited set of
|
||||
the printf syntax: types 's' and 'u' and length modifier 'l' (which is
|
||||
required for the 'u' type). */
|
||||
|
||||
char*
|
||||
mem_heap_printf(
|
||||
/*============*/
|
||||
/* out: heap-allocated formatted string */
|
||||
mem_heap_t* heap, /* in: memory heap */
|
||||
const char* format, /* in: format string */
|
||||
...)
|
||||
{
|
||||
va_list ap;
|
||||
char* str;
|
||||
ulint len;
|
||||
|
||||
/* Calculate length of string */
|
||||
len = 0;
|
||||
va_start(ap, format);
|
||||
len = mem_heap_printf_low(NULL, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Now create it for real. */
|
||||
str = mem_heap_alloc(heap, len);
|
||||
va_start(ap, format);
|
||||
mem_heap_printf_low(str, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Creates a memory heap block where data can be allocated. */
|
||||
|
||||
|
|
|
@ -204,8 +204,7 @@ mem_pool_create(
|
|||
pool->buf = ut_malloc_low(size, FALSE, TRUE);
|
||||
pool->size = size;
|
||||
|
||||
mutex_create(&(pool->mutex));
|
||||
mutex_set_level(&(pool->mutex), SYNC_MEM_POOL);
|
||||
mutex_create(&pool->mutex, SYNC_MEM_POOL);
|
||||
|
||||
/* Initialize the free lists */
|
||||
|
||||
|
|
|
@ -3679,6 +3679,37 @@ os_aio_posix_handle(
|
|||
}
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
Do a 'last millisecond' check that the page end is sensible;
|
||||
reported page checksum errors from Linux seem to wipe over the page end. */
|
||||
static
|
||||
void
|
||||
os_file_check_page_trailers(
|
||||
/*========================*/
|
||||
byte* combined_buf, /* in: combined write buffer */
|
||||
ulint total_len) /* in: size of combined_buf, in bytes
|
||||
(a multiple of UNIV_PAGE_SIZE) */
|
||||
{
|
||||
ulint len;
|
||||
|
||||
for (len = 0; len + UNIV_PAGE_SIZE <= total_len;
|
||||
len += UNIV_PAGE_SIZE) {
|
||||
byte* buf = combined_buf + len;
|
||||
|
||||
if (memcmp(buf + (FIL_PAGE_LSN + 4), buf + (UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4), 4)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: ERROR: The page to be written seems corrupt!\n"
|
||||
"InnoDB: Writing a block of %lu bytes, currently at offset %lu\n",
|
||||
(ulong)total_len, (ulong)len);
|
||||
buf_page_print(buf);
|
||||
fprintf(stderr,
|
||||
"InnoDB: ERROR: The page to be written seems corrupt!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Does simulated aio. This function should be called by an i/o-handler
|
||||
thread. */
|
||||
|
@ -3716,7 +3747,6 @@ os_aio_simulated_handle(
|
|||
ibool ret;
|
||||
ulint n;
|
||||
ulint i;
|
||||
ulint len2;
|
||||
|
||||
segment = os_aio_get_array_and_local_segment(&array, global_segment);
|
||||
|
||||
|
@ -3924,32 +3954,15 @@ consecutive_loop:
|
|||
ut_error;
|
||||
}
|
||||
|
||||
/* Do a 'last millisecond' check that the page end
|
||||
is sensible; reported page checksum errors from
|
||||
Linux seem to wipe over the page end */
|
||||
|
||||
for (len2 = 0; len2 + UNIV_PAGE_SIZE <= total_len;
|
||||
len2 += UNIV_PAGE_SIZE) {
|
||||
if (mach_read_from_4(combined_buf + len2
|
||||
+ FIL_PAGE_LSN + 4)
|
||||
!= mach_read_from_4(combined_buf + len2
|
||||
+ UNIV_PAGE_SIZE
|
||||
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: ERROR: The page to be written seems corrupt!\n");
|
||||
fprintf(stderr,
|
||||
"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n",
|
||||
(ulong)total_len, (ulong)len2);
|
||||
buf_page_print(combined_buf + len2);
|
||||
fprintf(stderr,
|
||||
"InnoDB: ERROR: The page to be written seems corrupt!\n");
|
||||
}
|
||||
}
|
||||
os_file_check_page_trailers(combined_buf, total_len);
|
||||
}
|
||||
|
||||
ret = os_file_write(slot->name, slot->file, combined_buf,
|
||||
slot->offset, slot->offset_high, total_len);
|
||||
|
||||
if (array == os_aio_write_array) {
|
||||
os_file_check_page_trailers(combined_buf, total_len);
|
||||
}
|
||||
} else {
|
||||
ret = os_file_read(slot->file, combined_buf,
|
||||
slot->offset, slot->offset_high, total_len);
|
||||
|
|
|
@ -220,7 +220,7 @@ os_thread_join(
|
|||
/*===========*/
|
||||
os_thread_id_t thread_id) /* in: id of the thread to join */
|
||||
{
|
||||
return pthread_join(thread_id, NULL);
|
||||
return(pthread_join(thread_id, NULL));
|
||||
}
|
||||
#endif
|
||||
/*********************************************************************
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -84,6 +84,7 @@ string_append(
|
|||
DIGIT [0-9]
|
||||
ID [a-z_A-Z][a-z_A-Z0-9]*
|
||||
BOUND_LIT \:[a-z_A-Z0-9]+
|
||||
BOUND_ID \$[a-z_A-Z0-9]+
|
||||
|
||||
%x comment
|
||||
%x quoted
|
||||
|
@ -111,6 +112,13 @@ BOUND_LIT \:[a-z_A-Z0-9]+
|
|||
return(type);
|
||||
}
|
||||
|
||||
{BOUND_ID} {
|
||||
yylval = sym_tab_add_bound_id(pars_sym_tab_global,
|
||||
yytext + 1);
|
||||
|
||||
return(PARS_ID_TOKEN);
|
||||
}
|
||||
|
||||
"'" {
|
||||
/* Quoted character string literals are handled in an explicit
|
||||
start state 'quoted'. This state is entered and the buffer for
|
||||
|
|
|
@ -1931,6 +1931,7 @@ pars_info_create(void)
|
|||
info->heap = heap;
|
||||
info->funcs = NULL;
|
||||
info->bound_lits = NULL;
|
||||
info->bound_ids = NULL;
|
||||
info->graph_owns_us = TRUE;
|
||||
|
||||
return(info);
|
||||
|
@ -2070,6 +2071,32 @@ pars_info_add_function(
|
|||
ib_vector_push(info->funcs, puf);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add bound id. */
|
||||
|
||||
void
|
||||
pars_info_add_id(
|
||||
/*=============*/
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name, /* in: name */
|
||||
const char* id) /* in: id */
|
||||
{
|
||||
pars_bound_id_t* bid;
|
||||
|
||||
ut_ad(!pars_info_get_bound_id(info, name));
|
||||
|
||||
bid = mem_heap_alloc(info->heap, sizeof(*bid));
|
||||
|
||||
bid->name = name;
|
||||
bid->id = id;
|
||||
|
||||
if (!info->bound_ids) {
|
||||
info->bound_ids = ib_vector_create(info->heap, 8);
|
||||
}
|
||||
|
||||
ib_vector_push(info->bound_ids, bid);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Get user function with the given name.*/
|
||||
|
||||
|
@ -2131,3 +2158,34 @@ pars_info_get_bound_lit(
|
|||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Get bound id with the given name.*/
|
||||
|
||||
pars_bound_id_t*
|
||||
pars_info_get_bound_id(
|
||||
/*===================*/
|
||||
/* out: bound id, or NULL if not
|
||||
found */
|
||||
pars_info_t* info, /* in: info struct */
|
||||
const char* name) /* in: bound id name to find */
|
||||
{
|
||||
ulint i;
|
||||
ib_vector_t* vec;
|
||||
|
||||
if (!info || !info->bound_ids) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
vec = info->bound_ids;
|
||||
|
||||
for (i = 0; i < ib_vector_size(vec); i++) {
|
||||
pars_bound_id_t* bid = ib_vector_get(vec, i);
|
||||
|
||||
if (strcmp(bid->name, name) == 0) {
|
||||
return(bid);
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
|
|
@ -207,6 +207,13 @@ sym_tab_add_bound_lit(
|
|||
*lit_type = PARS_STR_LIT;
|
||||
break;
|
||||
|
||||
case DATA_CHAR:
|
||||
ut_a(blit->length > 0);
|
||||
|
||||
len = blit->length;
|
||||
*lit_type = PARS_STR_LIT;
|
||||
break;
|
||||
|
||||
case DATA_INT:
|
||||
ut_a(blit->length > 0);
|
||||
ut_a(blit->length <= 8);
|
||||
|
@ -304,3 +311,42 @@ sym_tab_add_id(
|
|||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Add a bound identifier to a symbol table. */
|
||||
|
||||
sym_node_t*
|
||||
sym_tab_add_bound_id(
|
||||
/*===========*/
|
||||
/* out: symbol table node */
|
||||
sym_tab_t* sym_tab, /* in: symbol table */
|
||||
const char* name) /* in: name of bound id */
|
||||
{
|
||||
sym_node_t* node;
|
||||
pars_bound_id_t* bid;
|
||||
|
||||
bid = pars_info_get_bound_id(sym_tab->info, name);
|
||||
ut_a(bid);
|
||||
|
||||
node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t));
|
||||
|
||||
node->common.type = QUE_NODE_SYMBOL;
|
||||
|
||||
node->resolved = FALSE;
|
||||
node->indirection = NULL;
|
||||
|
||||
node->name = mem_heap_strdup(sym_tab->heap, bid->id);
|
||||
node->name_len = strlen(node->name);
|
||||
|
||||
UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node);
|
||||
|
||||
dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL);
|
||||
|
||||
node->common.val_buf_size = 0;
|
||||
node->prefetch_buf = NULL;
|
||||
node->cursor_def = NULL;
|
||||
|
||||
node->sym_table = sym_tab;
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
|
|
@ -601,7 +601,7 @@ row_ins_set_detailed(
|
|||
rewind(srv_misc_tmpfile);
|
||||
|
||||
if (os_file_set_eof(srv_misc_tmpfile)) {
|
||||
ut_print_name(srv_misc_tmpfile, trx,
|
||||
ut_print_name(srv_misc_tmpfile, trx, TRUE,
|
||||
foreign->foreign_table_name);
|
||||
dict_print_info_on_foreign_key_in_create_format(
|
||||
srv_misc_tmpfile,
|
||||
|
@ -643,22 +643,22 @@ row_ins_foreign_report_err(
|
|||
trx_print(ef, trx, 600);
|
||||
|
||||
fputs("Foreign key constraint fails for table ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
|
||||
fputs(":\n", ef);
|
||||
dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign,
|
||||
TRUE);
|
||||
putc('\n', ef);
|
||||
fputs(errstr, ef);
|
||||
fputs(" in parent table, in index ", ef);
|
||||
ut_print_name(ef, trx, foreign->referenced_index->name);
|
||||
ut_print_name(ef, trx, FALSE, foreign->referenced_index->name);
|
||||
if (entry) {
|
||||
fputs(" tuple:\n", ef);
|
||||
dtuple_print(ef, entry);
|
||||
}
|
||||
fputs("\nBut in child table ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
|
||||
fputs(", in index ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_index->name);
|
||||
ut_print_name(ef, trx, FALSE, foreign->foreign_index->name);
|
||||
if (rec) {
|
||||
fputs(", there is a record:\n", ef);
|
||||
rec_print(ef, rec, foreign->foreign_index);
|
||||
|
@ -696,20 +696,20 @@ row_ins_foreign_report_add_err(
|
|||
fputs(" Transaction:\n", ef);
|
||||
trx_print(ef, trx, 600);
|
||||
fputs("Foreign key constraint fails for table ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
|
||||
fputs(":\n", ef);
|
||||
dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign,
|
||||
TRUE);
|
||||
fputs("\nTrying to add in child table, in index ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_index->name);
|
||||
ut_print_name(ef, trx, FALSE, foreign->foreign_index->name);
|
||||
if (entry) {
|
||||
fputs(" tuple:\n", ef);
|
||||
dtuple_print(ef, entry);
|
||||
}
|
||||
fputs("\nBut in parent table ", ef);
|
||||
ut_print_name(ef, trx, foreign->referenced_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->referenced_table_name);
|
||||
fputs(", in index ", ef);
|
||||
ut_print_name(ef, trx, foreign->referenced_index->name);
|
||||
ut_print_name(ef, trx, FALSE, foreign->referenced_index->name);
|
||||
fputs(",\nthe closest match we can find is record:\n", ef);
|
||||
if (rec && page_rec_is_supremum(rec)) {
|
||||
/* If the cursor ended on a supremum record, it is better
|
||||
|
@ -1277,16 +1277,19 @@ run_again:
|
|||
fputs(" Transaction:\n", ef);
|
||||
trx_print(ef, trx, 600);
|
||||
fputs("Foreign key constraint fails for table ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE,
|
||||
foreign->foreign_table_name);
|
||||
fputs(":\n", ef);
|
||||
dict_print_info_on_foreign_key_in_create_format(ef,
|
||||
trx, foreign, TRUE);
|
||||
fputs("\nTrying to add to index ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_index->name);
|
||||
ut_print_name(ef, trx, FALSE,
|
||||
foreign->foreign_index->name);
|
||||
fputs(" tuple:\n", ef);
|
||||
dtuple_print(ef, entry);
|
||||
fputs("\nBut the parent table ", ef);
|
||||
ut_print_name(ef, trx, foreign->referenced_table_name);
|
||||
ut_print_name(ef, trx, TRUE,
|
||||
foreign->referenced_table_name);
|
||||
fputs("\nor its .ibd file does not currently exist!\n", ef);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
|
@ -1513,8 +1516,7 @@ row_ins_check_foreign_constraints(
|
|||
if (foreign->foreign_index == index) {
|
||||
|
||||
if (foreign->referenced_table == NULL) {
|
||||
dict_table_get(foreign->referenced_table_name,
|
||||
trx);
|
||||
dict_table_get(foreign->referenced_table_name);
|
||||
}
|
||||
|
||||
if (0 == trx->dict_operation_lock_mode) {
|
||||
|
|
|
@ -680,7 +680,7 @@ row_prebuilt_free(
|
|||
"InnoDB: table handle. Magic n %lu, magic n2 %lu, table name",
|
||||
(ulong) prebuilt->magic_n,
|
||||
(ulong) prebuilt->magic_n2);
|
||||
ut_print_name(stderr, NULL, prebuilt->table->name);
|
||||
ut_print_name(stderr, NULL, TRUE, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
@ -773,7 +773,7 @@ row_update_prebuilt_trx(
|
|||
"InnoDB: Error: trying to use a corrupt\n"
|
||||
"InnoDB: table handle. Magic n %lu, table name",
|
||||
(ulong) prebuilt->magic_n);
|
||||
ut_print_name(stderr, NULL, prebuilt->table->name);
|
||||
ut_print_name(stderr, NULL, TRUE, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
@ -1094,7 +1094,8 @@ row_insert_for_mysql(
|
|||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
"InnoDB: table handle. Magic n %lu, table name",
|
||||
(ulong) prebuilt->magic_n);
|
||||
ut_print_name(stderr, prebuilt->trx, prebuilt->table->name);
|
||||
ut_print_name(stderr, prebuilt->trx, TRUE,
|
||||
prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
@ -1329,7 +1330,8 @@ row_update_for_mysql(
|
|||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
"InnoDB: table handle. Magic n %lu, table name",
|
||||
(ulong) prebuilt->magic_n);
|
||||
ut_print_name(stderr, prebuilt->trx, prebuilt->table->name);
|
||||
ut_print_name(stderr, prebuilt->trx, TRUE,
|
||||
prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
@ -1941,7 +1943,7 @@ row_create_table_for_mysql(
|
|||
|
||||
fputs(" InnoDB: Warning: cannot create table ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs(" because tablespace full\n", stderr);
|
||||
|
||||
if (dict_table_get_low(table->name)) {
|
||||
|
@ -1954,7 +1956,7 @@ row_create_table_for_mysql(
|
|||
ut_print_timestamp(stderr);
|
||||
|
||||
fputs(" InnoDB: Error: table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs(" already exists in InnoDB internal\n"
|
||||
"InnoDB: data dictionary. Have you deleted the .frm file\n"
|
||||
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
|
||||
|
@ -2031,7 +2033,7 @@ row_create_index_for_mysql(
|
|||
ut_print_timestamp(stderr);
|
||||
|
||||
fputs(" InnoDB: Error: column ", stderr);
|
||||
ut_print_name(stderr, trx,
|
||||
ut_print_name(stderr, trx, FALSE,
|
||||
dict_index_get_nth_field(index, i)->name);
|
||||
fputs(" appears twice in ", stderr);
|
||||
dict_index_name_print(stderr, trx, index);
|
||||
|
@ -2196,7 +2198,7 @@ row_drop_table_for_mysql_in_background(
|
|||
trx->check_foreigns = FALSE;
|
||||
|
||||
/* fputs("InnoDB: Error: Dropping table ", stderr);
|
||||
ut_print_name(stderr, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs(" in background drop list\n", stderr); */
|
||||
|
||||
/* Try to drop the table in InnoDB */
|
||||
|
@ -2360,7 +2362,7 @@ row_add_table_to_background_drop_list(
|
|||
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
|
||||
|
||||
/* fputs("InnoDB: Adding table ", stderr);
|
||||
ut_print_name(stderr, drop->table_name);
|
||||
ut_print_name(stderr, trx, TRUE, drop->table_name);
|
||||
fputs(" to background drop list\n", stderr); */
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
@ -2429,7 +2431,7 @@ do not allow the discard. We also reserve the data dictionary latch. */
|
|||
if (table->space == 0) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error: table ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr);
|
||||
err = DB_ERROR;
|
||||
|
@ -2441,7 +2443,7 @@ do not allow the discard. We also reserve the data dictionary latch. */
|
|||
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: You are trying to DISCARD table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs("\n"
|
||||
"InnoDB: though there is a foreign key check running on it.\n"
|
||||
"InnoDB: Cannot discard the table.\n",
|
||||
|
@ -2475,10 +2477,10 @@ do not allow the discard. We also reserve the data dictionary latch. */
|
|||
ut_print_timestamp(ef);
|
||||
|
||||
fputs(" Cannot DISCARD table ", ef);
|
||||
ut_print_name(ef, trx, name);
|
||||
ut_print_name(ef, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"because it is referenced by ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
|
||||
putc('\n', ef);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
|
@ -2540,10 +2542,10 @@ do not allow the discard. We also reserve the data dictionary latch. */
|
|||
}
|
||||
|
||||
funct_exit:
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
|
@ -2590,7 +2592,7 @@ row_import_tablespace_for_mysql(
|
|||
if (!success) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr);
|
||||
|
||||
|
@ -2611,7 +2613,7 @@ row_import_tablespace_for_mysql(
|
|||
if (!table) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: table ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"InnoDB: does not exist in the InnoDB data dictionary\n"
|
||||
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
|
||||
|
@ -2625,7 +2627,7 @@ row_import_tablespace_for_mysql(
|
|||
if (table->space == 0) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error: table ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr);
|
||||
err = DB_ERROR;
|
||||
|
@ -2638,7 +2640,7 @@ row_import_tablespace_for_mysql(
|
|||
fputs(
|
||||
" InnoDB: Error: you are trying to IMPORT a tablespace\n"
|
||||
"InnoDB: ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs(", though you have not called DISCARD on it yet\n"
|
||||
"InnoDB: during the lifetime of the mysqld process!\n", stderr);
|
||||
|
||||
|
@ -2663,7 +2665,7 @@ row_import_tablespace_for_mysql(
|
|||
fputs(
|
||||
" InnoDB: cannot find or open in the database directory the .ibd file of\n"
|
||||
"InnoDB: table ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n",
|
||||
stderr);
|
||||
|
@ -2673,10 +2675,10 @@ row_import_tablespace_for_mysql(
|
|||
}
|
||||
|
||||
funct_exit:
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
|
@ -2783,10 +2785,10 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
|
|||
ut_print_timestamp(ef);
|
||||
|
||||
fputs(" Cannot truncate table ", ef);
|
||||
ut_print_name(ef, trx, table->name);
|
||||
ut_print_name(ef, trx, TRUE, table->name);
|
||||
fputs(" by DROP+CREATE\n"
|
||||
"InnoDB: because it is referenced by ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
|
||||
putc('\n', ef);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
|
@ -2803,7 +2805,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
|
|||
if (table->n_foreign_key_checks_running > 0) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Cannot truncate table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs(" by DROP+CREATE\n"
|
||||
"InnoDB: because there is a foreign key check running on it.\n",
|
||||
stderr);
|
||||
|
@ -2918,7 +2920,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */
|
|||
trx->error_state = DB_SUCCESS;
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Unable to assign a new identifier to table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs("\n"
|
||||
"InnoDB: after truncating it. Background processes may corrupt the table!\n",
|
||||
stderr);
|
||||
|
@ -3045,7 +3047,7 @@ row_drop_table_for_mysql(
|
|||
ut_print_timestamp(stderr);
|
||||
|
||||
fputs(" InnoDB: Error: table ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs(" does not exist in the InnoDB internal\n"
|
||||
"InnoDB: data dictionary though MySQL is trying to drop it.\n"
|
||||
"InnoDB: Have you copied the .frm file of the table to the\n"
|
||||
|
@ -3081,10 +3083,10 @@ row_drop_table_for_mysql(
|
|||
ut_print_timestamp(ef);
|
||||
|
||||
fputs(" Cannot drop table ", ef);
|
||||
ut_print_name(ef, trx, name);
|
||||
ut_print_name(ef, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"because it is referenced by ", ef);
|
||||
ut_print_name(ef, trx, foreign->foreign_table_name);
|
||||
ut_print_name(ef, trx, TRUE, foreign->foreign_table_name);
|
||||
putc('\n', ef);
|
||||
mutex_exit(&dict_foreign_err_mutex);
|
||||
|
||||
|
@ -3103,7 +3105,7 @@ row_drop_table_for_mysql(
|
|||
if (added) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs("\n"
|
||||
"InnoDB: though there are still open handles to it.\n"
|
||||
"InnoDB: Adding the table to the background drop queue.\n",
|
||||
|
@ -3136,7 +3138,7 @@ fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr);
|
|||
if (added) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: You are trying to drop table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs("\n"
|
||||
"InnoDB: though there is a foreign key check running on it.\n"
|
||||
"InnoDB: Adding the table to the background drop queue.\n",
|
||||
|
@ -3259,7 +3261,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
|
|||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error: not able to remove table ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs(" from the dictionary cache!\n", stderr);
|
||||
err = DB_ERROR;
|
||||
}
|
||||
|
@ -3277,7 +3279,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
|
|||
fprintf(stderr,
|
||||
"InnoDB: We removed now the InnoDB internal data dictionary entry\n"
|
||||
"InnoDB: of table ");
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fprintf(stderr, ".\n");
|
||||
|
||||
goto funct_exit;
|
||||
|
@ -3289,14 +3291,14 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
|
|||
fprintf(stderr,
|
||||
"InnoDB: We removed now the InnoDB internal data dictionary entry\n"
|
||||
"InnoDB: of table ");
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fprintf(stderr, ".\n");
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: not able to delete tablespace %lu of table ",
|
||||
(ulong) space_id);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("!\n", stderr);
|
||||
err = DB_ERROR;
|
||||
}
|
||||
|
@ -3304,6 +3306,8 @@ fputs(" InnoDB: You are trying to drop table ", stderr);
|
|||
}
|
||||
funct_exit:
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
if (locked_dictionary) {
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
}
|
||||
|
@ -3312,8 +3316,6 @@ funct_exit:
|
|||
mem_free(dir_path_of_temp_table);
|
||||
}
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
@ -3364,10 +3366,10 @@ loop:
|
|||
ut_print_timestamp(stderr);
|
||||
fputs(
|
||||
" InnoDB: Warning: MySQL is trying to drop database ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fputs("\n"
|
||||
"InnoDB: though there are still open handles to table ", stderr);
|
||||
ut_print_name(stderr, trx, table_name);
|
||||
ut_print_name(stderr, trx, TRUE, table_name);
|
||||
fputs(".\n", stderr);
|
||||
|
||||
os_thread_sleep(1000000);
|
||||
|
@ -3383,19 +3385,19 @@ loop:
|
|||
|
||||
if (err != DB_SUCCESS) {
|
||||
fputs("InnoDB: DROP DATABASE ", stderr);
|
||||
ut_print_name(stderr, trx, name);
|
||||
ut_print_name(stderr, trx, TRUE, name);
|
||||
fprintf(stderr, " failed with error %lu for table ",
|
||||
(ulint) err);
|
||||
ut_print_name(stderr, trx, table_name);
|
||||
ut_print_name(stderr, trx, TRUE, table_name);
|
||||
putc('\n', stderr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return(err);
|
||||
|
@ -3543,7 +3545,7 @@ row_rename_table_for_mysql(
|
|||
ut_print_timestamp(stderr);
|
||||
|
||||
fputs(" InnoDB: Error: table ", stderr);
|
||||
ut_print_name(stderr, trx, old_name);
|
||||
ut_print_name(stderr, trx, TRUE, old_name);
|
||||
fputs(" does not exist in the InnoDB internal\n"
|
||||
"InnoDB: data dictionary though MySQL is trying to rename the table.\n"
|
||||
"InnoDB: Have you copied the .frm file of the table to the\n"
|
||||
|
@ -3559,7 +3561,7 @@ row_rename_table_for_mysql(
|
|||
ut_print_timestamp(stderr);
|
||||
|
||||
fputs(" InnoDB: Error: table ", stderr);
|
||||
ut_print_name(stderr, trx, old_name);
|
||||
ut_print_name(stderr, trx, TRUE, old_name);
|
||||
fputs(
|
||||
" does not have an .ibd file in the database directory.\n"
|
||||
"InnoDB: You can look for further help from\n"
|
||||
|
@ -3704,17 +3706,17 @@ end:
|
|||
"InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n"
|
||||
"InnoDB: to have the same internal name in case-insensitive comparison.\n"
|
||||
"InnoDB: 2) table ", stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
ut_print_name(stderr, trx, TRUE, new_name);
|
||||
fputs(" exists in the InnoDB internal data\n"
|
||||
"InnoDB: dictionary though MySQL is trying rename table ", stderr);
|
||||
ut_print_name(stderr, trx, old_name);
|
||||
ut_print_name(stderr, trx, TRUE, old_name);
|
||||
fputs(" to it.\n"
|
||||
"InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n"
|
||||
"InnoDB: You can look for further help from\n"
|
||||
"InnoDB: http://dev.mysql.com/doc/mysql/en/"
|
||||
"InnoDB_troubleshooting_datadict.html\n"
|
||||
"InnoDB: If table ", stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
ut_print_name(stderr, trx, TRUE, new_name);
|
||||
fputs(
|
||||
" is a temporary table #sql..., then it can be that\n"
|
||||
"InnoDB: there are still queries running on the table, and it will be\n"
|
||||
|
@ -3742,9 +3744,9 @@ end:
|
|||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error in table rename, cannot rename ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, old_name);
|
||||
ut_print_name(stderr, trx, TRUE, old_name);
|
||||
fputs(" to ", stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
ut_print_name(stderr, trx, TRUE, new_name);
|
||||
putc('\n', stderr);
|
||||
err = DB_ERROR;
|
||||
|
||||
|
@ -3763,7 +3765,7 @@ end:
|
|||
if (old_is_tmp) {
|
||||
fputs(" InnoDB: Error: in ALTER TABLE ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
ut_print_name(stderr, trx, TRUE, new_name);
|
||||
fputs("\n"
|
||||
"InnoDB: has or is referenced in foreign key constraints\n"
|
||||
"InnoDB: which are not compatible with the new table definition.\n",
|
||||
|
@ -3772,7 +3774,7 @@ end:
|
|||
fputs(
|
||||
" InnoDB: Error: in RENAME TABLE table ",
|
||||
stderr);
|
||||
ut_print_name(stderr, trx, new_name);
|
||||
ut_print_name(stderr, trx, TRUE, new_name);
|
||||
fputs("\n"
|
||||
"InnoDB: is referenced in foreign key constraints\n"
|
||||
"InnoDB: which are not compatible with the new table definition.\n",
|
||||
|
@ -3788,6 +3790,8 @@ end:
|
|||
}
|
||||
|
||||
funct_exit:
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
if (!recovering_temp_table) {
|
||||
row_mysql_unlock_data_dictionary(trx);
|
||||
}
|
||||
|
@ -3796,8 +3800,6 @@ funct_exit:
|
|||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
|
@ -3986,7 +3988,7 @@ row_check_table_for_mysql(
|
|||
|
||||
while (index != NULL) {
|
||||
/* fputs("Validating index ", stderr);
|
||||
ut_print_name(stderr, index->name);
|
||||
ut_print_name(stderr, trx, FALSE, index->name);
|
||||
putc('\n', stderr); */
|
||||
|
||||
if (!btr_validate_tree(index->tree, prebuilt->trx)) {
|
||||
|
|
|
@ -520,7 +520,7 @@ row_purge_parse_undo_rec(
|
|||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
node->table = dict_table_get_on_id_low(table_id, trx);
|
||||
node->table = dict_table_get_on_id_low(table_id);
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
|
|
|
@ -480,12 +480,12 @@ row_build_row_ref_in_tuple(
|
|||
|
||||
ut_a(ref && index && rec);
|
||||
|
||||
if (!index->table) {
|
||||
if (UNIV_UNLIKELY(!index->table)) {
|
||||
fputs("InnoDB: table ", stderr);
|
||||
notfound:
|
||||
ut_print_name(stderr, trx, index->table_name);
|
||||
ut_print_name(stderr, trx, TRUE, index->table_name);
|
||||
fputs(" for index ", stderr);
|
||||
ut_print_name(stderr, trx, index->name);
|
||||
ut_print_name(stderr, trx, FALSE, index->name);
|
||||
fputs(" not found\n", stderr);
|
||||
ut_error;
|
||||
}
|
||||
|
|
|
@ -302,19 +302,45 @@ row_sel_fetch_columns(
|
|||
}
|
||||
|
||||
while (column) {
|
||||
mem_heap_t* heap = NULL;
|
||||
ibool needs_copy;
|
||||
|
||||
field_no = column->field_nos[index_type];
|
||||
|
||||
if (field_no != ULINT_UNDEFINED) {
|
||||
|
||||
data = rec_get_nth_field(rec, offsets, field_no, &len);
|
||||
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
|
||||
field_no))) {
|
||||
|
||||
if (column->copy_val) {
|
||||
/* Copy an externally stored field to the
|
||||
temporary heap */
|
||||
|
||||
heap = mem_heap_create(1);
|
||||
|
||||
data = btr_rec_copy_externally_stored_field(
|
||||
rec, offsets, field_no, &len, heap);
|
||||
|
||||
ut_a(len != UNIV_SQL_NULL);
|
||||
|
||||
needs_copy = TRUE;
|
||||
} else {
|
||||
data = rec_get_nth_field(rec, offsets,
|
||||
field_no, &len);
|
||||
|
||||
needs_copy = column->copy_val;
|
||||
}
|
||||
|
||||
if (needs_copy) {
|
||||
eval_node_copy_and_alloc_val(column, data,
|
||||
len);
|
||||
} else {
|
||||
val = que_node_get_val(column);
|
||||
dfield_set_data(val, data, len);
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
}
|
||||
|
||||
column = UT_LIST_GET_NEXT(col_var_list, column);
|
||||
|
@ -2036,8 +2062,13 @@ row_fetch_print(
|
|||
dtype_print(type);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if (dfield_get_len(dfield) != UNIV_SQL_NULL) {
|
||||
ut_print_buf(stderr, dfield_get_data(dfield),
|
||||
dfield_get_len(dfield));
|
||||
} else {
|
||||
fprintf(stderr, " <NULL>;");
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
exp = que_node_get_next(exp);
|
||||
|
@ -2542,6 +2573,7 @@ row_sel_store_mysql_rec(
|
|||
{
|
||||
mysql_row_templ_t* templ;
|
||||
mem_heap_t* extern_field_heap = NULL;
|
||||
mem_heap_t* heap;
|
||||
byte* data;
|
||||
ulint len;
|
||||
ulint i;
|
||||
|
@ -2558,9 +2590,6 @@ row_sel_store_mysql_rec(
|
|||
|
||||
templ = prebuilt->mysql_template + i;
|
||||
|
||||
data = rec_get_nth_field(rec, offsets,
|
||||
templ->rec_field_no, &len);
|
||||
|
||||
if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets,
|
||||
templ->rec_field_no))) {
|
||||
|
||||
|
@ -2569,7 +2598,19 @@ row_sel_store_mysql_rec(
|
|||
|
||||
ut_a(!prebuilt->trx->has_search_latch);
|
||||
|
||||
extern_field_heap = mem_heap_create(UNIV_PAGE_SIZE);
|
||||
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
|
||||
if (prebuilt->blob_heap == NULL) {
|
||||
prebuilt->blob_heap =
|
||||
mem_heap_create(UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
heap = prebuilt->blob_heap;
|
||||
} else {
|
||||
extern_field_heap =
|
||||
mem_heap_create(UNIV_PAGE_SIZE);
|
||||
|
||||
heap = extern_field_heap;
|
||||
}
|
||||
|
||||
/* NOTE: if we are retrieving a big BLOB, we may
|
||||
already run out of memory in the next call, which
|
||||
|
@ -2577,54 +2618,17 @@ row_sel_store_mysql_rec(
|
|||
|
||||
data = btr_rec_copy_externally_stored_field(rec,
|
||||
offsets, templ->rec_field_no, &len,
|
||||
extern_field_heap);
|
||||
heap);
|
||||
|
||||
ut_a(len != UNIV_SQL_NULL);
|
||||
} else {
|
||||
/* Field is stored in the row. */
|
||||
|
||||
data = rec_get_nth_field(rec, offsets,
|
||||
templ->rec_field_no, &len);
|
||||
}
|
||||
|
||||
if (len != UNIV_SQL_NULL) {
|
||||
if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) {
|
||||
|
||||
ut_a(prebuilt->templ_contains_blob);
|
||||
|
||||
/* A heuristic test that we can allocate the
|
||||
memory for a big BLOB. We have a safety margin
|
||||
of 1000000 bytes. Since the test takes some
|
||||
CPU time, we do not use it for small BLOBs. */
|
||||
|
||||
if (UNIV_UNLIKELY(len > 2000000)
|
||||
&& UNIV_UNLIKELY(!ut_test_malloc(
|
||||
len + 1000000))) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Warning: could not allocate %lu + 1000000 bytes to retrieve\n"
|
||||
"InnoDB: a big column. Table name ", (ulong) len);
|
||||
ut_print_name(stderr,
|
||||
prebuilt->trx,
|
||||
prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
if (extern_field_heap) {
|
||||
mem_heap_free(
|
||||
extern_field_heap);
|
||||
}
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* Copy the BLOB data to the BLOB heap of
|
||||
prebuilt */
|
||||
|
||||
if (prebuilt->blob_heap == NULL) {
|
||||
prebuilt->blob_heap =
|
||||
mem_heap_create(len);
|
||||
}
|
||||
|
||||
data = memcpy(mem_heap_alloc(
|
||||
prebuilt->blob_heap, len),
|
||||
data, len);
|
||||
}
|
||||
|
||||
row_sel_field_store_in_mysql_format(
|
||||
mysql_rec + templ->mysql_col_offset,
|
||||
templ, data, len);
|
||||
|
@ -3244,7 +3248,7 @@ row_search_for_mysql(
|
|||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
"InnoDB: table handle. Magic n %lu, table name ",
|
||||
(ulong) prebuilt->magic_n);
|
||||
ut_print_name(stderr, trx, prebuilt->table->name);
|
||||
ut_print_name(stderr, trx, TRUE, prebuilt->table->name);
|
||||
putc('\n', stderr);
|
||||
|
||||
mem_analyze_corruption(prebuilt);
|
||||
|
@ -3530,15 +3534,13 @@ shortcut_fails_too_big_rec:
|
|||
|
||||
if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
|
||||
&& prebuilt->select_lock_type != LOCK_NONE
|
||||
&& trx->mysql_query_str) {
|
||||
&& trx->mysql_query_str && trx->mysql_thd) {
|
||||
|
||||
/* Scan the MySQL query string; check if SELECT is the first
|
||||
word there */
|
||||
ibool success;
|
||||
|
||||
dict_accept(*trx->mysql_query_str, "SELECT", &success);
|
||||
|
||||
if (success) {
|
||||
if (dict_str_starts_with_keyword(trx->mysql_thd,
|
||||
*trx->mysql_query_str, "SELECT")) {
|
||||
/* It is a plain locking SELECT and the isolation
|
||||
level is low: do not lock gaps */
|
||||
|
||||
|
@ -4402,7 +4404,7 @@ row_search_check_if_query_cache_permitted(
|
|||
dict_table_t* table;
|
||||
ibool ret = FALSE;
|
||||
|
||||
table = dict_table_get(norm_name, trx);
|
||||
table = dict_table_get(norm_name);
|
||||
|
||||
if (table == NULL) {
|
||||
|
||||
|
|
|
@ -202,8 +202,7 @@ row_upd_check_references_constraints(
|
|||
foreign->n_fields))) {
|
||||
|
||||
if (foreign->foreign_table == NULL) {
|
||||
dict_table_get(foreign->foreign_table_name,
|
||||
trx);
|
||||
dict_table_get(foreign->foreign_table_name);
|
||||
}
|
||||
|
||||
if (foreign->foreign_table) {
|
||||
|
|
|
@ -68,6 +68,9 @@ ibool srv_error_monitor_active = FALSE;
|
|||
|
||||
const char* srv_main_thread_op_info = "";
|
||||
|
||||
/* Prefix used by MySQL to indicate pre-5.1 table name encoding */
|
||||
const char srv_mysql50_table_name_prefix[9] = "#mysql50#";
|
||||
|
||||
/* Server parameters which are read from the initfile */
|
||||
|
||||
/* The following three are dir paths which are catenated before file
|
||||
|
@ -849,11 +852,9 @@ srv_init(void)
|
|||
srv_sys = mem_alloc(sizeof(srv_sys_t));
|
||||
|
||||
kernel_mutex_temp = mem_alloc(sizeof(mutex_t));
|
||||
mutex_create(&kernel_mutex);
|
||||
mutex_set_level(&kernel_mutex, SYNC_KERNEL);
|
||||
mutex_create(&kernel_mutex, SYNC_KERNEL);
|
||||
|
||||
mutex_create(&srv_innodb_monitor_mutex);
|
||||
mutex_set_level(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t));
|
||||
|
||||
|
@ -2559,18 +2560,9 @@ suspend_thread:
|
|||
os_thread_exit(NULL);
|
||||
}
|
||||
|
||||
/* When there is user activity, InnoDB will set the event and the main
|
||||
thread goes back to loop: */
|
||||
/* When there is user activity, InnoDB will set the event and the
|
||||
main thread goes back to loop. */
|
||||
|
||||
goto loop;
|
||||
|
||||
/* We count the number of threads in os_thread_exit(). A created
|
||||
thread should always use that to exit and not use return() to exit.
|
||||
The thread actually never comes here because it is exited in an
|
||||
os_event_wait(). */
|
||||
|
||||
os_thread_exit(NULL);
|
||||
|
||||
OS_THREAD_DUMMY_RETURN;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
|
|
@ -108,12 +108,45 @@ static char* srv_monitor_file_name;
|
|||
static int inno_bcmp(register const char *s1, register const char *s2,
|
||||
register uint len)
|
||||
{
|
||||
while (len-- != 0 && *s1++ == *s2++) ;
|
||||
return len+1;
|
||||
while ((len-- != 0) && (*s1++ == *s2++))
|
||||
;
|
||||
|
||||
return(len + 1);
|
||||
}
|
||||
#define memcmp(A,B,C) inno_bcmp((A),(B),(C))
|
||||
#endif
|
||||
|
||||
static
|
||||
char*
|
||||
srv_parse_megabytes(
|
||||
/*================*/
|
||||
/* out: next character in string */
|
||||
char* str, /* in: string containing a quantity in bytes */
|
||||
ulint* megs) /* out: the number in megabytes */
|
||||
{
|
||||
char* endp;
|
||||
ulint size;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
switch (*str) {
|
||||
case 'G': case 'g':
|
||||
size *= 1024;
|
||||
/* fall through */
|
||||
case 'M': case 'm':
|
||||
str++;
|
||||
break;
|
||||
default:
|
||||
size /= 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
*megs = size;
|
||||
return(str);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reads the data files and their sizes from a character string given in
|
||||
the .cnf file. */
|
||||
|
@ -138,7 +171,6 @@ srv_parse_data_file_paths_and_sizes(
|
|||
last file if specified, 0 if not */
|
||||
{
|
||||
char* input_str;
|
||||
char* endp;
|
||||
char* path;
|
||||
ulint size;
|
||||
ulint i = 0;
|
||||
|
@ -168,18 +200,7 @@ srv_parse_data_file_paths_and_sizes(
|
|||
|
||||
str++;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if (*str != 'M' && *str != 'G') {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
str = srv_parse_megabytes(str, &size);
|
||||
|
||||
if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) {
|
||||
|
||||
|
@ -189,18 +210,7 @@ srv_parse_data_file_paths_and_sizes(
|
|||
|
||||
str += (sizeof ":max:") - 1;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if (*str != 'M' && *str != 'G') {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
str = srv_parse_megabytes(str, &size);
|
||||
}
|
||||
|
||||
if (*str != '\0') {
|
||||
|
@ -273,18 +283,7 @@ srv_parse_data_file_paths_and_sizes(
|
|||
str++;
|
||||
}
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if ((*str != 'M') && (*str != 'G')) {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
str = srv_parse_megabytes(str, &size);
|
||||
|
||||
(*data_file_names)[i] = path;
|
||||
(*data_file_sizes)[i] = size;
|
||||
|
@ -299,20 +298,8 @@ srv_parse_data_file_paths_and_sizes(
|
|||
|
||||
str += (sizeof ":max:") - 1;
|
||||
|
||||
size = strtoul(str, &endp, 10);
|
||||
|
||||
str = endp;
|
||||
|
||||
if (*str != 'M' && *str != 'G') {
|
||||
size = size / (1024 * 1024);
|
||||
} else if (*str == 'G') {
|
||||
size = size * 1024;
|
||||
str++;
|
||||
} else {
|
||||
str++;
|
||||
}
|
||||
|
||||
*max_auto_extend_size = size;
|
||||
str = srv_parse_megabytes(str,
|
||||
max_auto_extend_size);
|
||||
}
|
||||
|
||||
if (*str != '\0') {
|
||||
|
@ -934,8 +921,7 @@ skip_size_check:
|
|||
|
||||
ios = 0;
|
||||
|
||||
mutex_create(&ios_mutex);
|
||||
mutex_set_level(&ios_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&ios_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
@ -1167,8 +1153,8 @@ NetWare. */
|
|||
return((int) err);
|
||||
}
|
||||
|
||||
mutex_create(&srv_monitor_file_mutex);
|
||||
mutex_set_level(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
if (srv_innodb_status) {
|
||||
srv_monitor_file_name = mem_alloc(
|
||||
strlen(fil_path_to_mysql_datadir) +
|
||||
|
@ -1189,15 +1175,15 @@ NetWare. */
|
|||
}
|
||||
}
|
||||
|
||||
mutex_create(&srv_dict_tmpfile_mutex);
|
||||
mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
|
||||
mutex_create(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION);
|
||||
|
||||
srv_dict_tmpfile = os_file_create_tmpfile();
|
||||
if (!srv_dict_tmpfile) {
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
mutex_create(&srv_misc_tmpfile_mutex);
|
||||
mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
|
||||
mutex_create(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH);
|
||||
|
||||
srv_misc_tmpfile = os_file_create_tmpfile();
|
||||
if (!srv_misc_tmpfile) {
|
||||
return(DB_ERROR);
|
||||
|
|
|
@ -213,8 +213,7 @@ sync_array_create(
|
|||
if (protection == SYNC_ARRAY_OS_MUTEX) {
|
||||
arr->os_mutex = os_mutex_create(NULL);
|
||||
} else if (protection == SYNC_ARRAY_MUTEX) {
|
||||
mutex_create(&(arr->mutex));
|
||||
mutex_set_level(&(arr->mutex), SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
|
|
|
@ -89,19 +89,19 @@ void
|
|||
rw_lock_create_func(
|
||||
/*================*/
|
||||
rw_lock_t* lock, /* in: pointer to memory */
|
||||
ulint level, /* in: level */
|
||||
const char* cfile_name, /* in: file name where created */
|
||||
ulint cline, /* in: file line where created */
|
||||
const char* cmutex_name) /* in: mutex name */
|
||||
{
|
||||
/* If this is the very first time a synchronization
|
||||
object is created, then the following call initializes
|
||||
the sync system. */
|
||||
/* If this is the very first time a synchronization object is
|
||||
created, then the following call initializes the sync system. */
|
||||
|
||||
mutex_create(rw_lock_get_mutex(lock));
|
||||
mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
|
||||
|
||||
lock->mutex.cfile_name = cfile_name;
|
||||
lock->mutex.cline = cline;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
lock->mutex.cmutex_name = cmutex_name;
|
||||
lock->mutex.mutex_type = 1;
|
||||
|
@ -116,9 +116,10 @@ rw_lock_create_func(
|
|||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
UT_LIST_INIT(lock->debug_list);
|
||||
|
||||
lock->level = SYNC_LEVEL_NONE;
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
lock->level = level;
|
||||
|
||||
lock->magic_n = RW_LOCK_MAGIC_N;
|
||||
|
||||
lock->cfile_name = cfile_name;
|
||||
|
@ -669,18 +670,6 @@ rw_lock_remove_debug_info(
|
|||
}
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
/**********************************************************************
|
||||
Sets the rw-lock latching level field. */
|
||||
|
||||
void
|
||||
rw_lock_set_level(
|
||||
/*==============*/
|
||||
rw_lock_t* lock, /* in: rw-lock */
|
||||
ulint level) /* in: level */
|
||||
{
|
||||
lock->level = level;
|
||||
}
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
/**********************************************************************
|
||||
Checks if the thread has locked the rw-lock in the specified mode, with
|
||||
|
|
|
@ -202,6 +202,7 @@ void
|
|||
mutex_create_func(
|
||||
/*==============*/
|
||||
mutex_t* mutex, /* in: pointer to memory */
|
||||
ulint level, /* in: level */
|
||||
const char* cfile_name, /* in: file name where created */
|
||||
ulint cline, /* in: file line where created */
|
||||
const char* cmutex_name) /* in: mutex name */
|
||||
|
@ -218,7 +219,7 @@ mutex_create_func(
|
|||
mutex->line = 0;
|
||||
mutex->file_name = "not yet reserved";
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
mutex->level = SYNC_LEVEL_NONE;
|
||||
mutex->level = level;
|
||||
mutex->cfile_name = cfile_name;
|
||||
mutex->cline = cline;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
@ -598,19 +599,6 @@ mutex_get_debug_info(
|
|||
}
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
/**********************************************************************
|
||||
Sets the mutex latching level field. */
|
||||
|
||||
void
|
||||
mutex_set_level(
|
||||
/*============*/
|
||||
mutex_t* mutex, /* in: mutex */
|
||||
ulint level) /* in: level */
|
||||
{
|
||||
mutex->level = level;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
/**********************************************************************
|
||||
Checks that the current thread owns the mutex. Works only in the debug
|
||||
|
@ -979,8 +967,8 @@ void
|
|||
sync_thread_add_level(
|
||||
/*==================*/
|
||||
void* latch, /* in: pointer to a mutex or an rw-lock */
|
||||
ulint level) /* in: level in the latching order; if SYNC_LEVEL_NONE,
|
||||
nothing is done */
|
||||
ulint level) /* in: level in the latching order; if
|
||||
SYNC_LEVEL_VARYING, nothing is done */
|
||||
{
|
||||
sync_level_t* array;
|
||||
sync_level_t* slot;
|
||||
|
@ -1002,7 +990,7 @@ sync_thread_add_level(
|
|||
return;
|
||||
}
|
||||
|
||||
if (level == SYNC_LEVEL_NONE) {
|
||||
if (level == SYNC_LEVEL_VARYING) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1050,6 +1038,9 @@ sync_thread_add_level(
|
|||
case SYNC_RECV:
|
||||
ut_a(sync_thread_levels_g(array, SYNC_RECV));
|
||||
break;
|
||||
case SYNC_WORK_QUEUE:
|
||||
ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE));
|
||||
break;
|
||||
case SYNC_LOG:
|
||||
ut_a(sync_thread_levels_g(array, SYNC_LOG));
|
||||
break;
|
||||
|
@ -1290,21 +1281,17 @@ sync_init(void)
|
|||
/* Init the mutex list and create the mutex to protect it. */
|
||||
|
||||
UT_LIST_INIT(mutex_list);
|
||||
mutex_create(&mutex_list_mutex);
|
||||
mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
mutex_create(&sync_thread_mutex);
|
||||
mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
/* Init the rw-lock list and create the mutex to protect it. */
|
||||
|
||||
UT_LIST_INIT(rw_lock_list);
|
||||
mutex_create(&rw_lock_list_mutex);
|
||||
mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
mutex_create(&rw_lock_debug_mutex);
|
||||
mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
|
||||
mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
rw_lock_debug_event = os_event_create(NULL);
|
||||
rw_lock_debug_waiters = FALSE;
|
||||
|
|
|
@ -226,6 +226,5 @@ thr_local_init(void)
|
|||
|
||||
thr_local_hash = hash_create(OS_THREAD_MAX_N + 100);
|
||||
|
||||
mutex_create(&thr_local_mutex);
|
||||
mutex_set_level(&thr_local_mutex, SYNC_THR_LOCAL);
|
||||
mutex_create(&thr_local_mutex, SYNC_THR_LOCAL);
|
||||
}
|
||||
|
|
|
@ -211,11 +211,9 @@ trx_purge_sys_create(void)
|
|||
purge_sys->purge_undo_no = ut_dulint_zero;
|
||||
purge_sys->next_stored = FALSE;
|
||||
|
||||
rw_lock_create(&(purge_sys->latch));
|
||||
rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH);
|
||||
rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH);
|
||||
|
||||
mutex_create(&(purge_sys->mutex));
|
||||
mutex_set_level(&(purge_sys->mutex), SYNC_PURGE_SYS);
|
||||
mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS);
|
||||
|
||||
purge_sys->heap = mem_heap_create(256);
|
||||
|
||||
|
|
|
@ -843,7 +843,7 @@ trx_undo_update_rec_get_update(
|
|||
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n"
|
||||
"InnoDB: Run also CHECK TABLE ",
|
||||
(ulong) dict_index_get_n_fields(index));
|
||||
ut_print_name(stderr, trx, index->table_name);
|
||||
ut_print_name(stderr, trx, TRUE, index->table_name);
|
||||
fprintf(stderr, "\n"
|
||||
"InnoDB: n_fields = %lu, i = %lu, ptr %p\n",
|
||||
(ulong) n_fields, (ulong) i, ptr);
|
||||
|
|
|
@ -241,7 +241,7 @@ trx_rollback_to_savepoint_for_mysql(
|
|||
if (trx->conc_state == TRX_NOT_STARTED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Error: transaction has a savepoint ", stderr);
|
||||
ut_print_name(stderr, trx, savep->name);
|
||||
ut_print_name(stderr, trx, FALSE, savep->name);
|
||||
fputs(" though it is not started\n", stderr);
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
@ -540,11 +540,11 @@ loop:
|
|||
(ulong) ut_dulint_get_high(trx->table_id),
|
||||
(ulong) ut_dulint_get_low(trx->table_id));
|
||||
|
||||
table = dict_table_get_on_id_low(trx->table_id, trx);
|
||||
table = dict_table_get_on_id_low(trx->table_id);
|
||||
|
||||
if (table) {
|
||||
fputs("InnoDB: Table found: dropping table ", stderr);
|
||||
ut_print_name(stderr, trx, table->name);
|
||||
ut_print_name(stderr, trx, TRUE, table->name);
|
||||
fputs(" in recovery\n", stderr);
|
||||
|
||||
err = row_drop_table_for_mysql(table->name, trx, TRUE);
|
||||
|
|
|
@ -147,8 +147,7 @@ trx_rseg_mem_create(
|
|||
rseg->space = space;
|
||||
rseg->page_no = page_no;
|
||||
|
||||
mutex_create(&(rseg->mutex));
|
||||
mutex_set_level(&(rseg->mutex), SYNC_RSEG);
|
||||
mutex_create(&rseg->mutex, SYNC_RSEG);
|
||||
|
||||
UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg);
|
||||
|
||||
|
|
|
@ -101,8 +101,7 @@ trx_doublewrite_init(
|
|||
os_do_not_call_flush_at_each_write = TRUE;
|
||||
#endif /* UNIV_DO_FLUSH */
|
||||
|
||||
mutex_create(&(trx_doublewrite->mutex));
|
||||
mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE);
|
||||
mutex_create(&trx_doublewrite->mutex, SYNC_DOUBLEWRITE);
|
||||
|
||||
trx_doublewrite->first_free = 0;
|
||||
|
||||
|
|
|
@ -144,8 +144,7 @@ trx_create(
|
|||
trx->repl_wait_binlog_name = NULL;
|
||||
trx->repl_wait_binlog_pos = 0;
|
||||
|
||||
mutex_create(&(trx->undo_mutex));
|
||||
mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO);
|
||||
mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
|
||||
|
||||
trx->rseg = NULL;
|
||||
|
||||
|
|
|
@ -19,6 +19,6 @@ include ../include/Makefile.i
|
|||
|
||||
noinst_LIBRARIES = libut.a
|
||||
|
||||
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c
|
||||
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c ut0list.c ut0wqueue.c
|
||||
|
||||
EXTRA_PROGRAMS =
|
||||
|
|
|
@ -14,19 +14,21 @@ Created 1/30/1994 Heikki Tuuri
|
|||
ulint ut_dbg_zero = 0;
|
||||
#endif
|
||||
|
||||
#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
|
||||
/* If this is set to TRUE all threads will stop into the next assertion
|
||||
and assert */
|
||||
ibool ut_dbg_stop_threads = FALSE;
|
||||
#endif
|
||||
#ifdef __NETWARE__
|
||||
ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there
|
||||
happens an InnoDB assertion failure or other
|
||||
fatal error condition that requires an
|
||||
immediate shutdown. */
|
||||
#else /* __NETWARE__ */
|
||||
#elif !defined(UT_DBG_USE_ABORT)
|
||||
/* Null pointer used to generate memory trap */
|
||||
|
||||
ulint* ut_dbg_null_ptr = NULL;
|
||||
#endif /* __NETWARE__ */
|
||||
#endif
|
||||
|
||||
/*****************************************************************
|
||||
Report a failed assertion. */
|
||||
|
@ -56,7 +58,9 @@ ut_dbg_assertion_failed(
|
|||
"InnoDB: corruption in the InnoDB tablespace. Please refer to\n"
|
||||
"InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n"
|
||||
"InnoDB: about forcing recovery.\n", stderr);
|
||||
#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
|
||||
ut_dbg_stop_threads = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __NETWARE__
|
||||
|
@ -74,6 +78,7 @@ ut_dbg_panic(void)
|
|||
exit(1);
|
||||
}
|
||||
#else /* __NETWARE__ */
|
||||
# if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT)
|
||||
/*****************************************************************
|
||||
Stop a thread after assertion failure. */
|
||||
|
||||
|
@ -87,4 +92,5 @@ ut_dbg_stop_thread(
|
|||
os_thread_pf(os_thread_get_curr_id()), file, line);
|
||||
os_thread_sleep(1000000000);
|
||||
}
|
||||
# endif
|
||||
#endif /* __NETWARE__ */
|
||||
|
|
169
storage/innobase/ut/ut0list.c
Normal file
169
storage/innobase/ut/ut0list.c
Normal file
|
@ -0,0 +1,169 @@
|
|||
#include "ut0list.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "ut0list.ic"
|
||||
#endif
|
||||
|
||||
/********************************************************************
|
||||
Create a new list. */
|
||||
|
||||
ib_list_t*
|
||||
ib_list_create(void)
|
||||
/*=================*/
|
||||
/* out: list */
|
||||
{
|
||||
ib_list_t* list = mem_alloc(sizeof(ib_list_t));
|
||||
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
list->is_heap_list = FALSE;
|
||||
|
||||
return(list);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Create a new list using the given heap. ib_list_free MUST NOT BE CALLED for
|
||||
lists created with this function. */
|
||||
|
||||
ib_list_t*
|
||||
ib_list_create_heap(
|
||||
/*================*/
|
||||
/* out: list */
|
||||
mem_heap_t* heap) /* in: memory heap to use */
|
||||
{
|
||||
ib_list_t* list = mem_heap_alloc(heap, sizeof(ib_list_t));
|
||||
|
||||
list->first = NULL;
|
||||
list->last = NULL;
|
||||
list->is_heap_list = TRUE;
|
||||
|
||||
return(list);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Free a list. */
|
||||
|
||||
void
|
||||
ib_list_free(
|
||||
/*=========*/
|
||||
ib_list_t* list) /* in: list */
|
||||
{
|
||||
ut_a(!list->is_heap_list);
|
||||
|
||||
/* We don't check that the list is empty because it's entirely valid
|
||||
to e.g. have all the nodes allocated from a single heap that is then
|
||||
freed after the list itself is freed. */
|
||||
|
||||
mem_free(list);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add the data to the start of the list. */
|
||||
|
||||
ib_list_node_t*
|
||||
ib_list_add_first(
|
||||
/*==============*/
|
||||
/* out: new list node*/
|
||||
ib_list_t* list, /* in: list */
|
||||
void* data, /* in: data */
|
||||
mem_heap_t* heap) /* in: memory heap to use */
|
||||
{
|
||||
return(ib_list_add_after(list, ib_list_get_first(list), data, heap));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add the data to the end of the list. */
|
||||
|
||||
ib_list_node_t*
|
||||
ib_list_add_last(
|
||||
/*=============*/
|
||||
/* out: new list node*/
|
||||
ib_list_t* list, /* in: list */
|
||||
void* data, /* in: data */
|
||||
mem_heap_t* heap) /* in: memory heap to use */
|
||||
{
|
||||
return(ib_list_add_after(list, ib_list_get_last(list), data, heap));
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add the data after the indicated node. */
|
||||
|
||||
ib_list_node_t*
|
||||
ib_list_add_after(
|
||||
/*==============*/
|
||||
/* out: new list node*/
|
||||
ib_list_t* list, /* in: list */
|
||||
ib_list_node_t* prev_node, /* in: node preceding new node (can
|
||||
be NULL) */
|
||||
void* data, /* in: data */
|
||||
mem_heap_t* heap) /* in: memory heap to use */
|
||||
{
|
||||
ib_list_node_t* node = mem_heap_alloc(heap, sizeof(ib_list_node_t));
|
||||
|
||||
node->data = data;
|
||||
|
||||
if (!list->first) {
|
||||
/* Empty list. */
|
||||
|
||||
ut_a(!prev_node);
|
||||
|
||||
node->prev = NULL;
|
||||
node->next = NULL;
|
||||
|
||||
list->first = node;
|
||||
list->last = node;
|
||||
} else if (!prev_node) {
|
||||
/* Start of list. */
|
||||
|
||||
node->prev = NULL;
|
||||
node->next = list->first;
|
||||
|
||||
list->first->prev = node;
|
||||
|
||||
list->first = node;
|
||||
} else {
|
||||
/* Middle or end of list. */
|
||||
|
||||
node->prev = prev_node;
|
||||
node->next = prev_node->next;
|
||||
|
||||
prev_node->next = node;
|
||||
|
||||
if (node->next) {
|
||||
node->next->prev = node;
|
||||
} else {
|
||||
list->last = node;
|
||||
}
|
||||
}
|
||||
|
||||
return(node);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Remove the node from the list. */
|
||||
|
||||
void
|
||||
ib_list_remove(
|
||||
/*===========*/
|
||||
ib_list_t* list, /* in: list */
|
||||
ib_list_node_t* node) /* in: node to remove */
|
||||
{
|
||||
if (node->prev) {
|
||||
node->prev->next = node->next;
|
||||
} else {
|
||||
/* First item in list. */
|
||||
|
||||
ut_ad(list->first == node);
|
||||
|
||||
list->first = node->next;
|
||||
}
|
||||
|
||||
if (node->next) {
|
||||
node->next->prev = node->prev;
|
||||
} else {
|
||||
/* Last item in list. */
|
||||
|
||||
ut_ad(list->last == node);
|
||||
|
||||
list->last = node->prev;
|
||||
}
|
||||
}
|
|
@ -20,18 +20,20 @@ Created 5/11/1994 Heikki Tuuri
|
|||
|
||||
ibool ut_always_false = FALSE;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************
|
||||
Get the quote character to be used in SQL identifiers.
|
||||
Display an SQL identifier.
|
||||
This definition must match the one in sql/ha_innodb.cc! */
|
||||
extern
|
||||
int
|
||||
mysql_get_identifier_quote_char(
|
||||
/*============================*/
|
||||
/* out: quote character to be
|
||||
used in SQL identifiers; EOF if none */
|
||||
void
|
||||
innobase_print_identifier(
|
||||
/*======================*/
|
||||
FILE* f, /* in: output stream */
|
||||
trx_t* trx, /* in: transaction */
|
||||
ibool table_id,/* in: TRUE=decode table name */
|
||||
const char* name, /* in: name to print */
|
||||
ulint namelen);/* in: length of name */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/************************************************************
|
||||
Gets the high 32 bits in a ulint. That is makes a shift >> 32,
|
||||
|
@ -398,9 +400,10 @@ ut_print_name(
|
|||
/*==========*/
|
||||
FILE* f, /* in: output stream */
|
||||
trx_t* trx, /* in: transaction */
|
||||
ibool table_id,/* in: TRUE=decode table name */
|
||||
const char* name) /* in: name to print */
|
||||
{
|
||||
ut_print_namel(f, trx, name, strlen(name));
|
||||
ut_print_namel(f, trx, table_id, name, strlen(name));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -411,29 +414,27 @@ ut_print_namel(
|
|||
/*===========*/
|
||||
FILE* f, /* in: output stream */
|
||||
trx_t* trx, /* in: transaction (NULL=no quotes) */
|
||||
ibool table_id,/* in: TRUE=decode table name */
|
||||
const char* name, /* in: name to print */
|
||||
ulint namelen)/* in: length of name */
|
||||
{
|
||||
const char* s = name;
|
||||
const char* e = s + namelen;
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
int q = '"';
|
||||
#else
|
||||
int q = mysql_get_identifier_quote_char(trx, name, namelen);
|
||||
#endif
|
||||
if (q == EOF) {
|
||||
fwrite(name, 1, namelen, f);
|
||||
return;
|
||||
#else
|
||||
char* slash = strchr(name, '/');
|
||||
|
||||
if (UNIV_LIKELY_NULL(slash)) {
|
||||
/* Print the database name and table name separately. */
|
||||
ut_ad(table_id);
|
||||
|
||||
innobase_print_identifier(f, trx, TRUE, name, slash - name);
|
||||
putc('.', f);
|
||||
innobase_print_identifier(f, trx, TRUE, slash + 1,
|
||||
namelen - (slash - name) - 1);
|
||||
} else {
|
||||
innobase_print_identifier(f, trx, table_id, name, namelen);
|
||||
}
|
||||
putc(q, f);
|
||||
while (s < e) {
|
||||
int c = *s++;
|
||||
if (c == q) {
|
||||
putc(c, f);
|
||||
}
|
||||
putc(c, f);
|
||||
}
|
||||
putc(q, f);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
|
92
storage/innobase/ut/ut0wqueue.c
Normal file
92
storage/innobase/ut/ut0wqueue.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "ut0wqueue.h"
|
||||
|
||||
/********************************************************************
|
||||
Create a new work queue. */
|
||||
|
||||
ib_wqueue_t*
|
||||
ib_wqueue_create(void)
|
||||
/*===================*/
|
||||
/* out: work queue */
|
||||
{
|
||||
ib_wqueue_t* wq = mem_alloc(sizeof(ib_wqueue_t));
|
||||
|
||||
mutex_create(&wq->mutex, SYNC_WORK_QUEUE);
|
||||
|
||||
wq->items = ib_list_create();
|
||||
wq->event = os_event_create(NULL);
|
||||
|
||||
return(wq);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Free a work queue. */
|
||||
|
||||
void
|
||||
ib_wqueue_free(
|
||||
/*===========*/
|
||||
ib_wqueue_t* wq) /* in: work queue */
|
||||
{
|
||||
ut_a(!ib_list_get_first(wq->items));
|
||||
|
||||
mutex_free(&wq->mutex);
|
||||
ib_list_free(wq->items);
|
||||
os_event_free(wq->event);
|
||||
|
||||
mem_free(wq);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Add a work item to the queue. */
|
||||
|
||||
void
|
||||
ib_wqueue_add(
|
||||
/*==========*/
|
||||
ib_wqueue_t* wq, /* in: work queue */
|
||||
void* item, /* in: work item */
|
||||
mem_heap_t* heap) /* in: memory heap to use for allocating the
|
||||
list node */
|
||||
{
|
||||
mutex_enter(&wq->mutex);
|
||||
|
||||
ib_list_add_last(wq->items, item, heap);
|
||||
os_event_set(wq->event);
|
||||
|
||||
mutex_exit(&wq->mutex);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Wait for a work item to appear in the queue. */
|
||||
|
||||
void*
|
||||
ib_wqueue_wait(
|
||||
/* out: work item */
|
||||
ib_wqueue_t* wq) /* in: work queue */
|
||||
{
|
||||
ib_list_node_t* node;
|
||||
|
||||
for (;;) {
|
||||
os_event_wait(wq->event);
|
||||
|
||||
mutex_enter(&wq->mutex);
|
||||
|
||||
node = ib_list_get_first(wq->items);
|
||||
|
||||
if (node) {
|
||||
ib_list_remove(wq->items, node);
|
||||
|
||||
if (!ib_list_get_first(wq->items)) {
|
||||
/* We must reset the event when the list
|
||||
gets emptied. */
|
||||
os_event_reset(wq->event);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_exit(&wq->mutex);
|
||||
}
|
||||
|
||||
mutex_exit(&wq->mutex);
|
||||
|
||||
return(node->data);
|
||||
}
|
Loading…
Add table
Reference in a new issue