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:
mats@mysql.com 2006-06-02 16:11:17 +02:00
commit 3666d79d35
78 changed files with 2440 additions and 1247 deletions

View file

@ -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

View file

@ -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). #
# #
#######################################################################

View file

@ -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);
}
my_free(temp_name, MYF(0));
}
}
return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
name, (int) namelen));
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 */

View file

@ -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)

View file

@ -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

View file

@ -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,11 +2289,11 @@ 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(
page_get_infimum_rec(merge_page)), page);
page_get_infimum_rec(merge_page)), page);
}
/* Free the file page */
@ -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;
}

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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);
}
/*********************************************************************

View file

@ -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);
}
/*************************************************************************

View file

@ -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,\

View file

@ -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);
}

View file

@ -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);

View file

@ -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
@ -3434,15 +3471,18 @@ dict_create_foreign_constraints(
code DB_CANNOT_ADD_CONSTRAINT if
any foreign keys are found. */
{
char* str;
ulint err;
mem_heap_t* heap;
char* str;
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);
@ -3469,12 +3509,17 @@ dict_foreign_parse_drop_constraints(
const char*** constraints_to_drop) /* out: id's of the
constraints to drop */
{
dict_foreign_t* foreign;
ibool success;
char* str;
const char* ptr;
const char* id;
FILE* ef = dict_foreign_err_file;
dict_foreign_t* foreign;
ibool success;
char* str;
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);
}

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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);
}
}
ibuf_counts_inited = TRUE;
}
#endif
mutex_create(&ibuf_pessimistic_insert_mutex);
mutex_create(&ibuf_pessimistic_insert_mutex,
SYNC_IBUF_PESS_INSERT_MUTEX);
mutex_set_level(&ibuf_pessimistic_insert_mutex,
SYNC_IBUF_PESS_INSERT_MUTEX);
mutex_create(&ibuf_mutex);
mutex_create(&ibuf_mutex, SYNC_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);
mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX);
fil_ibuf_init_at_db_start();
ibuf_counts_inited = TRUE;
}
/**********************************************************************
@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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,...,

View file

@ -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

View 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

View file

@ -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. */

View file

@ -297,8 +297,8 @@ char*
mem_heap_strdup(
/*============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str); /* in: string to be copied */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str); /* in: string to be copied */
/**************************************************************************
Makes a NUL-terminated copy of a nonterminated string,
allocated from a memory heap. */
@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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,

View file

@ -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

View file

@ -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 */

View file

@ -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;

View file

@ -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,9 +74,10 @@ 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 */
ulint cline, /* in: file line where created */
const char* cmutex_name); /* in: mutex name */
/**********************************************************************
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
@ -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 */

View file

@ -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;

View file

@ -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

View file

@ -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,15 +65,23 @@ ut_dbg_stop_thread(
/*===============*/
const char* file,
ulint line);
# endif
# ifdef UT_DBG_USE_ABORT
/* Abort the execution. */
# define UT_DBG_PANIC \
# 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
/* Stop threads in ut_a(). */
# define UT_DBG_STOP do \
# define UT_DBG_STOP do \
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. */

View 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

View 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);
}

View file

@ -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 */

View 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

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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));

View file

@ -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
@ -107,11 +108,45 @@ char*
mem_heap_strdup(
/*============*/
/* out, own: a copy of the string */
mem_heap_t* heap, /* in: memory heap where string is allocated */
const char* str) /* in: string to be copied */
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. */

View file

@ -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 */

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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) {

View file

@ -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)) {

View file

@ -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));

View file

@ -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;
}

View file

@ -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");
ut_print_buf(stderr, dfield_get_data(dfield),
dfield_get_len(dfield));
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) {

View file

@ -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) {

View file

@ -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 */

View file

@ -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);

View file

@ -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;
}

View file

@ -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 */
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

View file

@ -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;

View file

@ -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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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 =

View file

@ -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__ */

View 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;
}
}

View file

@ -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 = '"';
fwrite(name, 1, namelen, f);
#else
int q = mysql_get_identifier_quote_char(trx, name, namelen);
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);
}
#endif
if (q == EOF) {
fwrite(name, 1, namelen, f);
return;
}
putc(q, f);
while (s < e) {
int c = *s++;
if (c == q) {
putc(c, f);
}
putc(c, f);
}
putc(q, f);
}
/**************************************************************************

View 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);
}