Commit ea2b425e authored by unknown's avatar unknown

Merge trift2.:/MySQL/M51/mysql-5.1

into  trift2.:/MySQL/M51/push-5.1

parents 10397af9 00a87190
......@@ -13,6 +13,8 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
CMAKE_MINIMUM_REQUIRED(VERSION 2.4.7 FATAL_ERROR)
PROJECT(MySql)
# This reads user configuration, generated by configure.js.
......
......@@ -691,6 +691,8 @@ extern WF_PACK *wf_comp(char * str);
extern int wf_test(struct wild_file_pack *wf_pack,const char *name);
extern void wf_end(struct wild_file_pack *buffer);
extern size_t strip_sp(char * str);
extern my_bool array_append_string_unique(const char *str,
const char **array, size_t size);
extern void get_date(char * to,int timeflag,time_t use_time);
extern void soundex(CHARSET_INFO *, char * out_pntr, char * in_pntr,
pbool remove_garbage);
......
......@@ -59,7 +59,7 @@ mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
mf_pack.lo my_messnc.lo mf_dirname.lo mf_fn_ext.lo\
mf_wcomp.lo typelib.lo safemalloc.lo my_alloc.lo \
mf_format.lo mf_path.lo mf_unixpath.lo my_fopen.lo \
my_symlink.lo my_fstream.lo \
my_symlink.lo my_fstream.lo mf_arr_appstr.lo \
mf_loadpath.lo my_pthread.lo my_thr_init.lo \
thr_mutex.lo mulalloc.lo string.lo \
default.lo default_modify.lo \
......
set session transaction isolation level read committed;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
set autocommit=0;
select * from t1 where a=3 lock in share mode;
a
3
set session transaction isolation level read committed;
set autocommit=0;
update t1 set a=10 where a=5;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
update t1 set a=10 where a=5;
select * from t1 where a=2 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
select * from t1 where a=2 limit 1 for update;
a
2
update t1 set a=11 where a=6;
update t1 set a=12 where a=2;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
update t1 set a=13 where a=1;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
update t1 set a=14 where a=1;
commit;
select * from t1;
a
14
2
3
4
10
11
7
drop table t1;
......@@ -472,43 +472,6 @@ a b
3 3
drop table t1,t2;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
insert into t1 (ggid,passwd) values ('test2','this will fail');
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
insert into t1 (ggid,id) values ('this will fail',1);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
select * from t1 where passwd='xxx';
id ggid email passwd
1 test1 xxx
select * from t1 where id=2;
id ggid email passwd
2 test2 yyy
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
update t1 set id=100,ggid='test2' where id=1;
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
select * from t1;
id ggid email passwd
1 this will work
4 test2 this will work
select * from t1 where id=1;
id ggid email passwd
1 this will work
select * from t1 where id=999;
id ggid email passwd
drop table t1;
CREATE TABLE t1 (
user_name varchar(12),
password text,
subscribed char(1),
......@@ -1751,13 +1714,13 @@ Variable_name Value
Innodb_page_size 16384
show status like "Innodb_rows_deleted";
Variable_name Value
Innodb_rows_deleted 70
Innodb_rows_deleted 69
show status like "Innodb_rows_inserted";
Variable_name Value
Innodb_rows_inserted 1083
Innodb_rows_inserted 1080
show status like "Innodb_rows_updated";
Variable_name Value
Innodb_rows_updated 886
Innodb_rows_updated 885
show status like "Innodb_row_lock_waits";
Variable_name Value
Innodb_row_lock_waits 0
......@@ -3189,3 +3152,52 @@ c25 CHAR(255), c26 CHAR(255), c27 CHAR(255), c28 CHAR(255),
c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255)
) ENGINE = InnoDB;
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs
DROP TABLE IF EXISTS t1;
Warnings:
Note 1051 Unknown table 't1'
CREATE TABLE t1(
id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-10);
SELECT * FROM t1;
id
-10
INSERT INTO t1 VALUES(NULL);
SELECT * FROM t1;
id
-10
1
DROP TABLE t1;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
DROP TABLE IF EXISTS t1, t2;
Warnings:
Note 1051 Unknown table 't1'
Note 1051 Unknown table 't2'
CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
CREATE TABLE t2 LIKE t1;
SELECT * FROM t2;
a
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1);
COMMIT;
SELECT * FROM t1 WHERE a=1;
a
1
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
SELECT * FROM t2;
a
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (2);
COMMIT;
SELECT * FROM t1 WHERE a=2;
a
2
SELECT * FROM t1 WHERE a=2;
a
2
DROP TABLE t1;
DROP TABLE t2;
drop table if exists t1;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
insert into t1 (ggid,passwd) values ('test2','this will fail');
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
insert into t1 (ggid,id) values ('this will fail',1);
ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
select * from t1 where ggid='test1';
id ggid email passwd
1 test1 xxx
select * from t1 where passwd='xxx';
id ggid email passwd
1 test1 xxx
select * from t1 where id=2;
id ggid email passwd
2 test2 yyy
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
update t1 set id=100,ggid='test2' where id=1;
ERROR 23000: Duplicate entry 'test2' for key 'ggid'
select * from t1;
id ggid email passwd
1 this will work
3 test2 this will work
select * from t1 where id=1;
id ggid email passwd
1 this will work
select * from t1 where id=999;
id ggid email passwd
drop table t1;
End of tests
--innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=2
-- source include/not_embedded.inc
-- source include/have_innodb.inc
# basic tests of semi-consistent reads
connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
set session transaction isolation level read committed;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
set autocommit=0;
# this should lock the entire table
select * from t1 where a=3 lock in share mode;
connection b;
set session transaction isolation level read committed;
set autocommit=0;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=10 where a=5;
connection a;
commit;
connection b;
update t1 set a=10 where a=5;
connection a;
-- error ER_LOCK_WAIT_TIMEOUT
select * from t1 where a=2 for update;
# this should lock the records (1),(2)
select * from t1 where a=2 limit 1 for update;
connection b;
update t1 set a=11 where a=6;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=12 where a=2;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=13 where a=1;
connection a;
commit;
connection b;
update t1 set a=14 where a=1;
commit;
connection a;
select * from t1;
drop table t1;
connection default;
disconnect a;
disconnect b;
......@@ -326,39 +326,6 @@ select * from t1;
select * from t2;
drop table t1,t2;
#
# Search on unique key
#
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
-- error ER_DUP_ENTRY
insert into t1 (ggid,passwd) values ('test2','this will fail');
-- error ER_DUP_ENTRY
insert into t1 (ggid,id) values ('this will fail',1);
select * from t1 where ggid='test1';
select * from t1 where passwd='xxx';
select * from t1 where id=2;
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
-- error ER_DUP_ENTRY
update t1 set id=100,ggid='test2' where id=1;
select * from t1;
select * from t1 where id=1;
select * from t1 where id=999;
drop table t1;
#
# ORDER BY on not primary key
#
......@@ -2323,6 +2290,67 @@ CREATE TABLE t1 (
c29 CHAR(255), c30 CHAR(255), c31 CHAR(255), c32 CHAR(255)
) ENGINE = InnoDB;
#
# Bug #31860 InnoDB assumes AUTOINC values can only be positive.
#
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(
id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=InnoDB;
INSERT INTO t1 VALUES(-10);
SELECT * FROM t1;
#
# NOTE: The server really needs to be restarted at this point
# for the test to be useful.
#
# Without the fix InnoDB would trip over an assertion here.
INSERT INTO t1 VALUES(NULL);
# The next value should be 1 and not -9 or a -ve number
SELECT * FROM t1;
DROP TABLE t1;
#
# Bug #21409 Incorrect result returned when in READ-COMMITTED with
# query_cache ON
#
CONNECT (c1,localhost,root,,);
CONNECT (c2,localhost,root,,);
CONNECTION c1;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
CREATE TABLE t2 LIKE t1;
SELECT * FROM t2;
CONNECTION c2;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (1);
COMMIT;
CONNECTION c1;
SELECT * FROM t1 WHERE a=1;
DISCONNECT c1;
DISCONNECT c2;
CONNECT (c1,localhost,root,,);
CONNECT (c2,localhost,root,,);
CONNECTION c1;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
SELECT * FROM t2;
CONNECTION c2;
SET TX_ISOLATION='read-committed';
SET AUTOCOMMIT=0;
INSERT INTO t1 VALUES (2);
COMMIT;
CONNECTION c1;
# The result set below should be the same for both selects
SELECT * FROM t1 WHERE a=2;
SELECT * FROM t1 WHERE a=2;
DROP TABLE t1;
DROP TABLE t2;
DISCONNECT c1;
DISCONNECT c2;
#######################################################################
# #
# Please, DO NOT TOUCH this file as well as the innodb.result file. #
......
# This test runs with old-style locking, as:
# --innodb-autoinc-lock-mode=0
-- source include/have_innodb.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Search on unique key
#
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
ggid varchar(32) binary DEFAULT '' NOT NULL,
email varchar(64) DEFAULT '' NOT NULL,
passwd varchar(32) binary DEFAULT '' NOT NULL,
PRIMARY KEY (id),
UNIQUE ggid (ggid)
) ENGINE=innodb;
insert into t1 (ggid,passwd) values ('test1','xxx');
insert into t1 (ggid,passwd) values ('test2','yyy');
-- error ER_DUP_ENTRY
insert into t1 (ggid,passwd) values ('test2','this will fail');
-- error ER_DUP_ENTRY
insert into t1 (ggid,id) values ('this will fail',1);
select * from t1 where ggid='test1';
select * from t1 where passwd='xxx';
select * from t1 where id=2;
replace into t1 (ggid,id) values ('this will work',1);
replace into t1 (ggid,passwd) values ('test2','this will work');
-- error ER_DUP_ENTRY
update t1 set id=100,ggid='test2' where id=1;
select * from t1;
select * from t1 where id=1;
select * from t1 where id=999;
drop table t1;
--echo End of tests
......@@ -155,13 +155,13 @@ set @@sql_mode='ansi,traditional';
insert into t1 values ('2007-03-23 13:49:38','2007-03-23 13:49:38');
insert into t1 set dt='2007-03-23 13:49:38',da=dt;
# Test error handling
--error 1292
--error ER_TRUNCATED_WRONG_VALUE
insert into t1 values ('2007-03-32','2007-03-23 13:49:38');
select * from t1;
drop table t1;
--error 1067
--error ER_INVALID_DEFAULT
create table t1 (da date default '1962-03-32 23:33:34', dt datetime default '1962-03-03');
--error 1067
--error ER_INVALID_DEFAULT
create table t1 (t time default '916:00:00 a');
set @@sql_mode= @org_mode;
......@@ -169,6 +169,19 @@ set @@sql_mode= @org_mode;
#
# Bug#27590: Wrong DATE/DATETIME comparison.
#
## The following sub test will fail (difference to expected result) if the
## select curdate() < now(), f1 < now(), cast(f1 as date) < now() from t1;
## runs exact at midnight ('00:00:00').
## ( Bug#29290 type_datetime.test failure in 5.1 )
## Therefore we sleep a bit if we are too close to midnight.
## The complete test itself needs around 1 second.
## Therefore a time_distance to midnight of 5 seconds should be sufficient.
if (`SELECT CURTIME() > SEC_TO_TIME(24 * 3600 - 5)`)
{
# We are here when CURTIME() is between '23:59:56' and '23:59:59'.
# So a sleep time of 5 seconds brings us between '00:00:01' and '00:00:04'.
--real_sleep 5
}
create table t1 (f1 date, f2 datetime, f3 timestamp);
insert into t1(f1) values(curdate());
select curdate() < now(), f1 < now(), cast(f1 as date) < now() from t1;
......
......@@ -29,7 +29,7 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_
errors.c hash.c list.c md5.c mf_brkhant.c mf_cache.c mf_dirname.c mf_fn_ext.c
mf_format.c mf_getdate.c mf_iocache.c mf_iocache2.c mf_keycache.c
mf_keycaches.c mf_loadpath.c mf_pack.c mf_path.c mf_qsort.c mf_qsort2.c
mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_tempdir.c
mf_radix.c mf_same.c mf_sort.c mf_soundex.c mf_strip.c mf_arr_appstr.c mf_tempdir.c
mf_tempfile.c mf_unixpath.c mf_wcomp.c mf_wfile.c mulalloc.c my_access.c
my_aes.c my_alarm.c my_alloc.c my_append.c my_bit.c my_bitmap.c my_chsize.c
my_clock.c my_compress.c my_conio.c my_copy.c my_crc32.c my_create.c my_delete.c
......
......@@ -35,7 +35,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
my_error.c errors.c my_div.c my_messnc.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
mf_pack.c mf_unixpath.c mf_strip.c \
mf_pack.c mf_unixpath.c mf_strip.c mf_arr_appstr.c \
mf_wcomp.c mf_wfile.c my_gethwaddr.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c my_getncpus.c \
......
......@@ -47,7 +47,7 @@ char *my_defaults_extra_file=0;
/* Which directories are searched for options (and in which order) */
#define MAX_DEFAULT_DIRS 7
#define MAX_DEFAULT_DIRS 6
const char *default_directories[MAX_DEFAULT_DIRS + 1];
#ifdef __WIN__
......@@ -83,7 +83,22 @@ static int search_default_file_with_ext(Process_option_func func,
void *func_ctx,
const char *dir, const char *ext,
const char *config_file, int recursion_level);
static void init_default_directories();
/**
Create the list of default directories.
@details
On all systems, if a directory is already in the list, it will be moved
to the end of the list. This avoids reading defaults files multiple times,
while ensuring the correct precedence.
@return void
*/
static void (*init_default_directories)();
static char *remove_end_comment(char *ptr);
......@@ -922,6 +937,25 @@ void print_defaults(const char *conf_file, const char **groups)
#include <help_end.h>
#define ADD_DIRECTORY(DIR) \
do { \
my_bool rc= \
array_append_string_unique((DIR), default_directories, \
array_elements(default_directories)); \
DBUG_ASSERT(rc == FALSE); /* Success */ \
} while (0)
#define ADD_COMMON_DIRECTORIES() \
do { \
char *env; \
if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV)))) \
ADD_DIRECTORY(env); \
/* Placeholder for --defaults-extra-file=<path> */ \
ADD_DIRECTORY(""); \
} while (0)
#ifdef __WIN__
/*
This wrapper for GetSystemWindowsDirectory() will dynamically bind to the
......@@ -956,71 +990,33 @@ static size_t my_get_system_windows_directory(char *buffer, size_t size)
}
return count;
}
#endif
/*
Create the list of default directories.
/**
Initialize default directories for Microsoft Windows
On Microsoft Windows, this is:
1. C:/
@details
1. GetSystemWindowsDirectory()
2. GetWindowsDirectory()
3. GetSystemWindowsDirectory()
4. getenv(DEFAULT_HOME_ENV)
5. Directory above where the executable is located
6. ""
7. --sysconfdir=<path>
On Novell NetWare, this is:
1. sys:/etc/
2. getenv(DEFAULT_HOME_ENV)
3. ""
4. --sysconfdir=<path>
On OS/2, this is:
1. getenv(ETC)
2. /etc/
3. getenv(DEFAULT_HOME_ENV)
4. ""
5. "~/"
6. --sysconfdir=<path>
Everywhere else, this is:
1. /etc/
2. /etc/mysql/
3. getenv(DEFAULT_HOME_ENV)
4. ""
5. "~/"
6. --sysconfdir=<path>
*/
3. C:/
4. Directory above where the executable is located
5. getenv(DEFAULT_HOME_ENV)
6. --defaults-extra-file=<path> (run-time option)
*/
static void init_default_directories()
static void init_default_directories_win()
{
const char *env, **ptr= default_directories;
bzero(default_directories, sizeof(default_directories));
#ifdef __WIN__
*ptr++= "C:/";
if (my_get_system_windows_directory(shared_system_dir,
sizeof(shared_system_dir)))
ADD_DIRECTORY(&shared_system_dir);
if (GetWindowsDirectory(system_dir,sizeof(system_dir)))
*ptr++= (char*)&system_dir;
if (my_get_system_windows_directory(shared_system_dir,
sizeof(shared_system_dir)) &&
strcmp(system_dir, shared_system_dir))
*ptr++= (char *)&shared_system_dir;
ADD_DIRECTORY(&system_dir);
ADD_DIRECTORY("C:/");
#elif defined(__NETWARE__)
*ptr++= "sys:/etc/";
#else
*ptr++= "/etc/";
*ptr++= "/etc/mysql/";
#endif
if ((env= getenv(STRINGIFY_ARG(DEFAULT_HOME_ENV))))
*ptr++= env;
*ptr++= ""; /* Place for defaults_extra_file */
#if !defined(__WIN__) && !defined(__NETWARE__)
*ptr++= "~/";;
#elif defined(__WIN__)
if (GetModuleFileName(NULL, config_dir, sizeof(config_dir)))
{
char *last= NULL, *end= strend(config_dir);
......@@ -1050,12 +1046,61 @@ static void init_default_directories()
last= end;
}
}
*ptr++= (char *)&config_dir;
ADD_DIRECTORY(&config_dir);
}
#endif
ADD_COMMON_DIRECTORIES();
}
static void (*init_default_directories)()= init_default_directories_win;
#elif defined(__NETWARE__)
/**
Initialize default directories for Novell Netware
@details
1. sys:/etc/
2. getenv(DEFAULT_HOME_ENV)
3. --defaults-extra-file=<path> (run-time option)
*/
static void init_default_directories_netware()
{
bzero(default_directories, sizeof(default_directories));
ADD_DIRECTORY("sys:/etc/");
ADD_COMMON_DIRECTORIES();
}
static void (*init_default_directories)()= init_default_directories_netware;
#else
/**
Initialize default directories for Unix
@details
1. /etc/
2. /etc/mysql/
3. --sysconfdir=<path> (compile-time option)
4. getenv(DEFAULT_HOME_ENV)
5. --defaults-extra-file=<path> (run-time option)
6. "~/"
*/
static void init_default_directories_unix()
{
bzero(default_directories, sizeof(default_directories));
ADD_DIRECTORY("/etc/");
ADD_DIRECTORY("/etc/mysql/");
#ifdef DEFAULT_SYSCONFDIR
if (DEFAULT_SYSCONFDIR != "")
*ptr++= DEFAULT_SYSCONFDIR;
ADD_DIRECTORY(DEFAULT_SYSCONFDIR);
#endif
*ptr= 0; /* end marker */
ADD_COMMON_DIRECTORIES();
ADD_DIRECTORY("~/");
}
static void (*init_default_directories)()= init_default_directories_unix;
#endif
/* Copyright (C) 2007 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "mysys_priv.h"
#include <m_string.h> /* strcmp() */
/**
Append str to array, or move to the end if it already exists
@param str String to be appended
@param array The array, terminated by a NULL element, all unused elements
pre-initialized to NULL
@param size Size of the array; array must be terminated by a NULL
pointer, so can hold size - 1 elements
@retval FALSE Success
@retval TRUE Failure, array is full
*/
my_bool array_append_string_unique(const char *str,
const char **array, size_t size)
{
const char **p;
/* end points at the terminating NULL element */
const char **end= array + size - 1;
DBUG_ASSERT(*end == NULL);
for (p= array; *p; ++p)
{
if (strcmp(*p, str) == 0)
break;
}
if (p >= end)
return TRUE; /* Array is full */
DBUG_ASSERT(*p == NULL || strcmp(*p, str) == 0);
while (*(p + 1))
{
*p= *(p + 1);
++p;
}
DBUG_ASSERT(p < end);
*p= str;
return FALSE; /* Success */
}
......@@ -90,13 +90,6 @@ TARGET_LINK_LIBRARIES(mysqld
SET_TARGET_PROPERTIES(mysqld PROPERTIES OUTPUT_NAME mysqld${MYSQLD_EXE_SUFFIX})
# Work around for 2.4.6 bug, OUTPUT_NAME will not set the right .PDB
# file name. Note that COMPILE_FLAGS set some temporary pdb during build,
# LINK_FLAGS sets the real one.
SET_TARGET_PROPERTIES(mysqld PROPERTIES
COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb"
LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb")
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("mysqld" "asInvoker")
ENDIF(EMBED_MANIFESTS)
......
......@@ -881,7 +881,7 @@ buf_LRU_block_free_non_file_page(
UT_LIST_ADD_FIRST(free, buf_pool->free, block);
block->in_free_list = TRUE;
UNIV_MEM_FREE(block->frame, UNIV_PAGE_SIZE);
UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE);
if (srv_use_awe && block->frame) {
/* Add to the list of mapped pages */
......
......@@ -441,6 +441,8 @@ dict_table_autoinc_initialize(
dict_table_t* table, /* in: table */
ib_longlong value) /* in: next value to assign to a row */
{
ut_ad(mutex_own(&table->autoinc_mutex));
table->autoinc_inited = TRUE;
table->autoinc = value;
}
......@@ -457,6 +459,8 @@ dict_table_autoinc_read(
{
ib_longlong value;
ut_ad(mutex_own(&table->autoinc_mutex));
if (!table->autoinc_inited) {
value = 0;
......
......@@ -551,11 +551,13 @@ dict_load_fields(
Loads definitions for table indexes. Adds them to the data dictionary
cache. */
static
ibool
ulint
dict_load_indexes(
/*==============*/
/* out: TRUE if ok, FALSE if corruption
of dictionary table */
/* out: DB_SUCCESS if ok, DB_CORRUPTION
if corruption of dictionary table or
DB_UNSUPPORTED if table has unknown index
type */
dict_table_t* table, /* in: table */
mem_heap_t* heap) /* in: memory heap for temporary storage */
{
......@@ -578,6 +580,7 @@ dict_load_indexes(
ibool is_sys_table;
dulint id;
mtr_t mtr;
ulint error = DB_SUCCESS;
ut_ad(mutex_own(&(dict_sys->mutex)));
......@@ -624,10 +627,8 @@ dict_load_indexes(
dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
return(FALSE);
error = DB_CORRUPTION;
goto func_exit;
}
field = rec_get_nth_field_old(rec, 1, &len);
......@@ -653,7 +654,18 @@ dict_load_indexes(
field = rec_get_nth_field_old(rec, 8, &len);
page_no = mach_read_from_4(field);
if (page_no == FIL_NULL) {
/* We check for unsupported types first, so that the
subsequent checks are relevant for the supported types. */
if (type & ~(DICT_CLUSTERED | DICT_UNIQUE)) {
fprintf(stderr,
"InnoDB: Error: unknown type %lu"
" of index %s of table %s\n",
(ulong) type, name_buf, table->name);
error = DB_UNSUPPORTED;
goto func_exit;
} else if (page_no == FIL_NULL) {
fprintf(stderr,
"InnoDB: Error: trying to load index %s"
......@@ -661,14 +673,10 @@ dict_load_indexes(
"InnoDB: but the index tree has been freed!\n",
name_buf, table->name);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
return(FALSE);
}
if ((type & DICT_CLUSTERED) == 0
&& NULL == dict_table_get_first_index(table)) {
error = DB_CORRUPTION;
goto func_exit;
} else if ((type & DICT_CLUSTERED) == 0
&& NULL == dict_table_get_first_index(table)) {
fprintf(stderr,
"InnoDB: Error: trying to load index %s"
......@@ -677,18 +685,14 @@ dict_load_indexes(
" is not clustered!\n",
name_buf, table->name);
btr_pcur_close(&pcur);
mtr_commit(&mtr);
return(FALSE);
}
if (is_sys_table
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == (sizeof "ID_IND") - 1)
&& (0 == ut_memcmp(name_buf, "ID_IND",
name_len))))) {
error = DB_CORRUPTION;
goto func_exit;
} else if (is_sys_table
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == (sizeof "ID_IND") - 1)
&& (0 == ut_memcmp(name_buf,
"ID_IND", name_len))))) {
/* The index was created in memory already at booting
of the database server */
......@@ -704,10 +708,11 @@ dict_load_indexes(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
}
func_exit:
btr_pcur_close(&pcur);
mtr_commit(&mtr);
return(TRUE);
return(error);
}
/************************************************************************
......@@ -857,11 +862,20 @@ err_exit:
mem_heap_empty(heap);
dict_load_indexes(table, heap);
err = dict_load_foreigns(table->name, TRUE);
err = dict_load_indexes(table, heap);
/* If the force recovery flag is set, we open the table irrespective
of the error condition, since the user may want to dump data from the
clustered index. However we load the foreign key information only if
all indexes were loaded. */
if (err != DB_SUCCESS && !srv_force_recovery) {
dict_mem_table_free(table);
table = NULL;
} else if (err == DB_SUCCESS) {
err = dict_load_foreigns(table->name, TRUE);
}
#if 0
if (err != DB_SUCCESS) {
if (err != DB_SUCCESS && table != NULL) {
mutex_enter(&dict_foreign_err_mutex);
......
......@@ -129,6 +129,7 @@ static my_bool innobase_locks_unsafe_for_binlog = FALSE;
static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE;
static my_bool innobase_use_adaptive_hash_indexes = TRUE;
static char* internal_innobase_data_file_path = NULL;
......@@ -1143,7 +1144,6 @@ innobase_query_caching_of_table_permitted(
}
if (trx->has_search_latch) {
ut_print_timestamp(stderr);
sql_print_error("The calling thread is holding the adaptive "
"search, latch though calling "
"innobase_query_caching_of_table_permitted.");
......@@ -1246,8 +1246,7 @@ innobase_invalidate_query_cache(
}
/*********************************************************************
Display an SQL identifier.
This definition must match the one in innobase/ut/ut0ut.c! */
Display an SQL identifier. */
extern "C"
void
innobase_print_identifier(
......@@ -1635,6 +1634,9 @@ innobase_init(
srv_stats_on_metadata = (ibool) innobase_stats_on_metadata;
srv_use_adaptive_hash_indexes =
(ibool) innobase_use_adaptive_hash_indexes;
srv_print_verbose_log = mysqld_embedded ? 0 : 1;
/* Store the default charset-collation number of this MySQL
......@@ -2319,14 +2321,18 @@ ha_innobase::open(
ib_table = dict_table_get(norm_name, TRUE);
if (NULL == ib_table) {
ut_print_timestamp(stderr);
sql_print_error("Cannot find table %s from the internal data "
"dictionary\nof InnoDB though the .frm file "
"for the table exists. Maybe you\nhave "
"deleted and recreated InnoDB data files but "
"have forgotten\nto delete the corresponding "
".frm files of InnoDB tables, or you\n"
"have moved .frm files to another database?\n"
sql_print_error("Cannot find or open table %s from\n"
"the internal data dictionary of InnoDB "
"though the .frm file for the\n"
"table exists. Maybe you have deleted and "
"recreated InnoDB data\n"
"files but have forgotten to delete the "
"corresponding .frm files\n"
"of InnoDB tables, or you have moved .frm "
"files to another database?\n"
"or, the table contains indexes that this "
"version of the engine\n"
"doesn't support.\n"
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"how you can resolve the problem.\n",
norm_name);
......@@ -2338,7 +2344,6 @@ ha_innobase::open(
}
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
ut_print_timestamp(stderr);
sql_print_error("MySQL is trying to open a table handle but "
"the .ibd file for\ntable %s does not exist.\n"
"Have you deleted the .ibd file from the "
......@@ -3412,7 +3417,7 @@ no_commit:
/*
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB error: ALTER TABLE is holding lock"
" InnoDB: ALTER TABLE is holding lock"
" on %lu tables!\n",
prebuilt->trx->mysql_n_tables_locked);
*/
......@@ -3476,6 +3481,7 @@ no_commit:
/* Handle duplicate key errors */
if (auto_inc_used) {
ulint err;
ulonglong auto_inc;
/* Note the number of rows processed for this statement, used
......@@ -3529,7 +3535,11 @@ set_max_autoinc:
ut_a(prebuilt->table->autoinc_increment > 0);
auto_inc += prebuilt->table->autoinc_increment;
innobase_set_max_autoinc(auto_inc);
err = innobase_set_max_autoinc(auto_inc);
if (err != DB_SUCCESS) {
error = (int) err;
}
}
break;
}
......@@ -3765,7 +3775,7 @@ ha_innobase::update_row(
if (auto_inc != 0) {
auto_inc += prebuilt->table->autoinc_increment;
innobase_set_max_autoinc(auto_inc);
error = innobase_set_max_autoinc(auto_inc);
}
}
......@@ -5710,7 +5720,6 @@ ha_innobase::info(
for (i = 0; i < table->s->keys; i++) {
if (index == NULL) {
ut_print_timestamp(stderr);
sql_print_error("Table %s contains fewer "
"indexes inside InnoDB than "
"are defined in the MySQL "
......@@ -5726,7 +5735,6 @@ ha_innobase::info(
for (j = 0; j < table->key_info[i].key_parts; j++) {
if (j + 1 > index->n_uniq) {
ut_print_timestamp(stderr);
sql_print_error(
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
"statistics for %lu columns. Have you mixed up .frm files from different "
......@@ -5791,7 +5799,6 @@ ha_innobase::info(
ret = innobase_read_and_init_auto_inc(&auto_inc);
if (ret != 0) {
ut_print_timestamp(stderr);
sql_print_error("Cannot get table %s auto-inc"
"counter value in ::info\n",
ib_table->name);
......@@ -6304,6 +6311,9 @@ ha_innobase::start_stmt(
innobase_release_stat_resources(trx);
/* Reset the AUTOINC statement level counter for multi-row INSERTs. */
trx->n_autoinc_rows = 0;
prebuilt->sql_stat_start = TRUE;
prebuilt->hint_need_to_fetch_extra_cols = 0;
reset_template(prebuilt);
......@@ -6446,9 +6456,6 @@ ha_innobase::external_lock(
innobase_register_stmt(ht, thd);
}
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
if (trx->isolation_level == TRX_ISO_SERIALIZABLE
&& prebuilt->select_lock_type == LOCK_NONE
&& thd_test_options(thd,
......@@ -6497,6 +6504,9 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked++;
}
trx->n_mysql_tables_in_use++;
prebuilt->mysql_has_locked = TRUE;
DBUG_RETURN(0);
}
......@@ -6562,14 +6572,17 @@ ha_innobase::transactional_table_lock(
if (prebuilt->table->ibd_file_missing && !thd_tablespace_op(thd)) {
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB error:\n"
"MySQL is trying to use a table handle but the .ibd file for\n"
"table %s does not exist.\n"
"Have you deleted the .ibd file from the database directory under\n"
"the MySQL datadir?"
"See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"how you can resolve the problem.\n",
prebuilt->table->name);
fprintf(stderr,
" InnoDB: MySQL is trying to use a table handle"
" but the .ibd file for\n"
"InnoDB: table %s does not exist.\n"
"InnoDB: Have you deleted the .ibd file"
" from the database directory under\n"
"InnoDB: the MySQL datadir?"
"InnoDB: See"
" http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html\n"
"InnoDB: how you can resolve the problem.\n",
prebuilt->table->name);
DBUG_RETURN(HA_ERR_CRASHED);
}
......@@ -7120,8 +7133,8 @@ the value of the auto-inc counter. */
int
ha_innobase::innobase_read_and_init_auto_inc(
/*=========================================*/
/* out: 0 or error code:
deadlock or lock wait timeout */
/* out: 0 or generic MySQL
error code */
longlong* value) /* out: the autoinc value */
{
longlong auto_inc;
......@@ -7178,9 +7191,10 @@ ha_innobase::innobase_read_and_init_auto_inc(
++auto_inc;
dict_table_autoinc_initialize(innodb_table, auto_inc);
} else {
fprintf(stderr, " InnoDB error: Couldn't read the "
"max AUTOINC value from index (%s).\n",
index->name);
ut_print_timestamp(stderr);
fprintf(stderr, " InnoDB: Error: (%lu) Couldn't read "
"the max AUTOINC value from the index (%s).\n",
error, index->name);
mysql_error = 1;
}
......@@ -7217,6 +7231,11 @@ ha_innobase::innobase_get_auto_increment(
{
ulong error;
*value = 0;
/* Note: If the table is not initialized when we attempt the
read below. We initialize the table's auto-inc counter and
always do a reread of the AUTOINC value. */
do {
error = innobase_autoinc_lock();
......@@ -7256,7 +7275,15 @@ ha_innobase::innobase_get_auto_increment(
} else {
*value = (ulonglong) autoinc;
}
/* A deadlock error during normal processing is OK
and can be ignored. */
} else if (error != DB_DEADLOCK) {
sql_print_error("InnoDB: Error: %lu in "
"::innobase_get_auto_increment()",
error);
}
} while (*value == 0 && error == DB_SUCCESS);
return(error);
......@@ -7272,7 +7299,7 @@ we have a table-level lock). offset, increment, nb_desired_values are ignored.
void
ha_innobase::get_auto_increment(
/*=================================*/
/*============================*/
ulonglong offset, /* in: */
ulonglong increment, /* in: table autoinc increment */
ulonglong nb_desired_values, /* in: number of values reqd */
......@@ -7289,13 +7316,6 @@ ha_innobase::get_auto_increment(
error = innobase_get_auto_increment(&autoinc);
if (error != DB_SUCCESS) {
/* This should never happen in the code > ver 5.0.6,
since we call this function only after the counter
has been initialized. */
ut_print_timestamp(stderr);
sql_print_error("Error %lu in ::get_auto_increment()", error);
*first_value = (~(ulonglong) 0);
return;
}
......@@ -7310,6 +7330,11 @@ ha_innobase::get_auto_increment(
trx = prebuilt->trx;
/* Note: We can't rely on *first_value since some MySQL engines,
in particular the partition engine, don't initialize it to 0 when
invoking this method. So we are not sure if it's guaranteed to
be 0 or not. */
/* Called for the first time ? */
if (trx->n_autoinc_rows == 0) {
......@@ -7318,16 +7343,16 @@ ha_innobase::get_auto_increment(
/* It's possible for nb_desired_values to be 0:
e.g., INSERT INTO T1(C) SELECT C FROM T2; */
if (nb_desired_values == 0) {
trx->n_autoinc_rows = 1;
}
set_if_bigger(*first_value, autoinc);
/* Not in the middle of a mult-row INSERT. */
} else if (prebuilt->last_value == 0) {
set_if_bigger(*first_value, autoinc);
}
*nb_reserved_values = trx->n_autoinc_rows;
/* With old style AUTOINC locking we only update the table's
......@@ -7359,7 +7384,9 @@ ha_innobase::get_auto_increment(
/* See comment in handler.h */
int
ha_innobase::reset_auto_increment(ulonglong value)
ha_innobase::reset_auto_increment(
/*==============================*/
ulonglong value) /* in: new value for table autoinc */
{
DBUG_ENTER("ha_innobase::reset_auto_increment");
......@@ -7923,6 +7950,11 @@ static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata,
"Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_BOOL(use_adaptive_hash_indexes, innobase_use_adaptive_hash_indexes,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
"Enable the InnoDB adaptive hash indexes (enabled by default)",
NULL, NULL, TRUE);
static MYSQL_SYSVAR_LONG(additional_mem_pool_size, innobase_additional_mem_pool_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Size of a memory pool InnoDB uses to store data dictionary information and other internal data structures.",
......@@ -8051,6 +8083,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(open_files),
MYSQL_SYSVAR(rollback_on_timeout),
MYSQL_SYSVAR(stats_on_metadata),
MYSQL_SYSVAR(use_adaptive_hash_indexes),
MYSQL_SYSVAR(status_file),
MYSQL_SYSVAR(support_xa),
MYSQL_SYSVAR(sync_spin_loops),
......
......@@ -250,17 +250,3 @@ int thd_binlog_format(const MYSQL_THD thd);
*/
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
}
/*
don't delete it - it may be re-enabled later
as an optimization for the most common case InnoDB+binlog
*/
#if 0
int innobase_report_binlog_offset_and_commit(
THD* thd,
void* trx_handle,
char* log_file_name,
my_off_t end_offset);
int innobase_commit_complete(void* trx_handle);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
#endif
......@@ -2900,7 +2900,7 @@ dump:
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: Insert buffer insert"
" InnoDB: Error: Insert buffer insert"
" fails; page free %lu,"
" dtuple size %lu\n",
(ulong) page_get_max_insert_size(
......@@ -2925,7 +2925,7 @@ dump:
buf_frame_get_page_no(page),
IBUF_BITMAP_FREE, mtr);
fprintf(stderr, "Bitmap bits %lu\n",
fprintf(stderr, "InnoDB: Bitmap bits %lu\n",
(ulong) old_bits);
fputs("InnoDB: Submit a detailed bug report"
......
......@@ -61,12 +61,14 @@ Created 5/24/1996 Heikki Tuuri
activated by the operation would
lead to a duplicate key in some
table */
#define DB_TOO_MANY_CONCURRENT_TRXS 47 /* when InnoDB runs out of the
preconfigured undo slots, this can
only happen when there are too many
concurrent transactions */
#define DB_UNSUPPORTED 48 /* when InnoDB sees any artefact or
a feature that it can't recoginize or
work with e.g., FT indexes created by
a later version of the engine. */
/* The following are partial failure codes */
#define DB_FAIL 1000
#define DB_OVERFLOW 1001
......
#ifndef HA_INNODB_PROTOTYPES_H
#define HA_INNODB_PROTOTYPES_H
#ifndef UNIV_HOTBACKUP
#include "univ.i" /* ulint, uint */
#include "m_ctype.h" /* CHARSET_INFO */
......@@ -22,6 +24,19 @@ innobase_convert_string(
CHARSET_INFO* from_cs,
uint* errors);
/*********************************************************************
Display an SQL identifier. */
void
innobase_print_identifier(
/*======================*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
ibool table_id,/* in: TRUE=print a table name,
FALSE=print other identifier */
const char* name, /* in: name to print */
ulint namelen);/* in: length of name */
/**********************************************************************
Returns true if the thread is the replication thread on the slave
server. Used in srv_conc_enter_innodb() to determine if the thread
......@@ -49,3 +64,4 @@ thd_has_edited_nontrans_tables(
void* thd); /* in: thread handle (THD*) */
#endif
#endif
......@@ -327,6 +327,17 @@ mach_write_to_2_little_endian(
byte* dest, /* in: where to write */
ulint n); /* in: unsigned long int to write */
/*************************************************************
Convert integral type from storage byte order (big endian) to
host byte order. */
UNIV_INLINE
void
mach_read_int_type(
/*===============*/
byte* dest, /* out: where to write */
const byte* src, /* in: where to read from */
ulint len, /* in: length of src */
ibool unsigned_type); /* in: signed or unsigned flag */
#ifndef UNIV_NONINL
#include "mach0data.ic"
#endif
......
......@@ -7,6 +7,8 @@ to the machine format.
Created 11/28/1995 Heikki Tuuri
***********************************************************************/
#include "ut0mem.h"
/***********************************************************
The following function is used to store data in one byte. */
UNIV_INLINE
......@@ -689,3 +691,38 @@ mach_write_to_2_little_endian(
*dest = (byte)(n & 0xFFUL);
}
/*************************************************************
Convert integral type from storage byte order (big endian) to
host byte order. */
UNIV_INLINE
void
mach_read_int_type(
/*===============*/
byte* dest, /* out: where to write */
const byte* src, /* in: where to read from */
ulint len, /* in: length of src */
ibool unsigned_type) /* in: signed or unsigned flag */
{
#ifdef WORDS_BIGENDIAN
memcpy(dest, src, len);
if (!unsigned_type) {
dest[0] ^= 128;
}
#else
byte* ptr;
/* Convert integer data from Innobase to a little-endian format,
sign bit restored to normal. */
for (ptr = dest + len; ptr != dest; ++src) {
--ptr;
*ptr = *src;
}
if (!unsigned_type) {
dest[len - 1] ^= 128;
}
#endif
}
......@@ -60,6 +60,14 @@ mem_heap_validate_or_print(
ulint* n_blocks); /* out: number of blocks in the heap,
if a NULL pointer is passed as this
argument, it is ignored */
/******************************************************************
Validates the contents of a memory heap. */
ibool
mem_heap_validate(
/*==============*/
/* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
#ifdef UNIV_DEBUG
/******************************************************************
......@@ -71,14 +79,6 @@ mem_heap_check(
/* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */
#endif /* UNIV_DEBUG */
/******************************************************************
Validates the contents of a memory heap. */
ibool
mem_heap_validate(
/*==============*/
/* out: TRUE if ok */
mem_heap_t* heap); /* in: memory heap */
#ifdef UNIV_MEM_DEBUG
/*********************************************************************
TRUE if no memory is currently allocated. */
......
......@@ -271,19 +271,16 @@ mem_heap_free_heap_top(
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
/* In the debug version erase block from top up */
{
ulint len = (byte*)block + block->len - old_top;
mem_erase_buf(old_top, len);
UNIV_MEM_FREE(old_top, len);
}
mem_erase_buf(old_top, (byte*)block + block->len - old_top);
/* Update allocated memory count */
mutex_enter(&mem_hash_mutex);
mem_current_allocated_memory -= (total_size - size);
mutex_exit(&mem_hash_mutex);
#else /* UNIV_MEM_DEBUG */
UNIV_MEM_FREE(old_top, (byte*)block + block->len - old_top);
UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
#endif /* UNIV_MEM_DEBUG */
UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
/* If free == start, we may free the block if it is not the first
one */
......@@ -363,6 +360,7 @@ mem_heap_free_top(
/* Subtract the free field of block */
mem_block_set_free(block, mem_block_get_free(block)
- MEM_SPACE_NEEDED(n));
UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
#ifdef UNIV_MEM_DEBUG
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
......@@ -378,7 +376,11 @@ mem_heap_free_top(
== mem_block_get_start(block))) {
mem_heap_block_free(heap, block);
} else {
UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n);
/* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
subsequent invocation of mem_heap_free_top().
Originally, this was UNIV_MEM_FREE(), to catch writes
to freed memory. */
UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
}
}
......
......@@ -801,6 +801,7 @@ rec_offs_set_n_alloc(
{
ut_ad(offsets);
ut_ad(n_alloc > 0);
UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets);
offsets[0] = n_alloc;
}
......
......@@ -319,9 +319,11 @@ row_mysql_unfreeze_data_dictionary(
/*===============================*/
trx_t* trx); /* in: transaction */
/*************************************************************************
Does a table creation operation for MySQL. If the name of the created
table ends to characters INNODB_MONITOR, then this also starts
printing of monitor output by the master thread. */
Drops a table for MySQL. If the name of the table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also start the printing of monitor
output by the master thread. If the table name ends in "innodb_mem_validate",
InnoDB will try to invoke mem_validate(). */
int
row_create_table_for_mysql(
......@@ -399,8 +401,9 @@ row_truncate_table_for_mysql(
dict_table_t* table, /* in: table handle */
trx_t* trx); /* in: transaction handle */
/*************************************************************************
Drops a table for MySQL. If the name of the dropped table ends to
characters INNODB_MONITOR, then this also stops printing of monitor
Drops a table for MySQL. If the name of the dropped table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of monitor
output by the master thread. */
int
......
......@@ -101,6 +101,7 @@ void
rw_lock_free(
/*=========*/
rw_lock_t* lock); /* in: rw-lock */
#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */
......@@ -109,6 +110,7 @@ ibool
rw_lock_validate(
/*=============*/
rw_lock_t* lock);
#endif /* UNIV_DEBUG */
/******************************************************************
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
......
......@@ -308,11 +308,39 @@ typedef void* os_thread_ret_t;
# define UNIV_MEM_INVALID(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
# define UNIV_MEM_FREE(addr, size) VALGRIND_MAKE_MEM_NOACCESS(addr, size)
# define UNIV_MEM_ALLOC(addr, size) VALGRIND_MAKE_MEM_UNDEFINED(addr, size)
# define UNIV_MEM_ASSERT_RW(addr, size) do { \
const void* _p = (const void*) (ulint) \
VALGRIND_CHECK_MEM_IS_DEFINED(addr, size); \
if (UNIV_LIKELY_NULL(_p)) \
fprintf(stderr, "%s:%d: %p[%u] undefined at %ld\n", \
__FILE__, __LINE__, \
(const void*) (addr), (unsigned) (size), (long) \
(((const char*) _p) - ((const char*) (addr)))); \
} while (0)
# define UNIV_MEM_ASSERT_W(addr, size) do { \
const void* _p = (const void*) (ulint) \
VALGRIND_CHECK_MEM_IS_ADDRESSABLE(addr, size); \
if (UNIV_LIKELY_NULL(_p)) \
fprintf(stderr, "%s:%d: %p[%u] unwritable at %ld\n", \
__FILE__, __LINE__, \
(const void*) (addr), (unsigned) (size), (long) \
(((const char*) _p) - ((const char*) (addr)))); \
} while (0)
#else
# define UNIV_MEM_VALID(addr, size) do {} while(0)
# define UNIV_MEM_INVALID(addr, size) do {} while(0)
# define UNIV_MEM_FREE(addr, size) do {} while(0)
# define UNIV_MEM_ALLOC(addr, size) do {} while(0)
# define UNIV_MEM_ASSERT_RW(addr, size) do {} while(0)
# define UNIV_MEM_ASSERT_W(addr, size) do {} while(0)
#endif
#define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \
UNIV_MEM_ASSERT_W(addr, size); \
UNIV_MEM_FREE(addr, size); \
} while (0)
#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size) do { \
UNIV_MEM_ASSERT_W(addr, size); \
UNIV_MEM_ALLOC(addr, size); \
} while (0)
#endif
......@@ -263,6 +263,24 @@ ut_copy_file(
FILE* dest, /* in: output file */
FILE* src); /* in: input file to be appended to output */
/**************************************************************************
snprintf(). */
#ifdef __WIN__
int
ut_snprintf(
/* out: number of characters that would
have been printed if the size were
unlimited, not including the terminating
'\0'. */
char* str, /* out: string */
size_t size, /* in: str size */
const char* fmt, /* in: format */
...); /* in: format values */
#else
#define ut_snprintf snprintf
#endif /* __WIN__ */
#ifndef UNIV_NONINL
#include "ut0ut.ic"
#endif
......
......@@ -223,6 +223,8 @@ mem_init_buf(
{
byte* ptr;
UNIV_MEM_ASSERT_W(buf, n);
for (ptr = buf; ptr < buf + n; ptr++) {
if (ut_rnd_gen_ibool()) {
......@@ -231,6 +233,8 @@ mem_init_buf(
*ptr = 0xBE;
}
}
UNIV_MEM_INVALID(buf, n);
}
/*******************************************************************
......@@ -245,6 +249,8 @@ mem_erase_buf(
{
byte* ptr;
UNIV_MEM_ASSERT_W(buf, n);
for (ptr = buf; ptr < buf + n; ptr++) {
if (ut_rnd_gen_ibool()) {
*ptr = 0xDE;
......@@ -252,6 +258,8 @@ mem_erase_buf(
*ptr = 0xAD;
}
}
UNIV_MEM_FREE(buf, n);
}
/*******************************************************************
......@@ -546,9 +554,7 @@ completed:
}
*error = FALSE;
}
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
#ifdef UNIV_DEBUG
/******************************************************************
Prints the contents of a memory heap. */
static
......@@ -574,20 +580,6 @@ mem_heap_print(
ut_a(!error);
}
/******************************************************************
Checks that an object is a memory heap (or a block of it). */
ibool
mem_heap_check(
/*===========*/
/* out: TRUE if ok */
mem_heap_t* heap) /* in: memory heap */
{
ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
return(TRUE);
}
/******************************************************************
Validates the contents of a memory heap. */
......@@ -614,6 +606,22 @@ mem_heap_validate(
return(TRUE);
}
#endif /* UNIV_MEM_DEBUG || UNIV_DEBUG */
#ifdef UNIV_DEBUG
/******************************************************************
Checks that an object is a memory heap (or a block of it). */
ibool
mem_heap_check(
/*===========*/
/* out: TRUE if ok */
mem_heap_t* heap) /* in: memory heap */
{
ut_a(heap->magic_n == MEM_BLOCK_MAGIC_N);
return(TRUE);
}
#endif /* UNIV_DEBUG */
#ifdef UNIV_MEM_DEBUG
......
......@@ -512,9 +512,9 @@ mem_heap_block_free(
of hex 0xDE and 0xAD. */
mem_erase_buf((byte*)block, len);
#endif
UNIV_MEM_FREE(block, len);
#else /* UNIV_MEM_DEBUG */
UNIV_MEM_ASSERT_AND_FREE(block, len);
#endif /* UNIV_MEM_DEBUG */
if (init_block) {
/* Do not have to free: do nothing */
......
......@@ -1728,10 +1728,11 @@ row_mysql_unlock_data_dictionary(
}
/*************************************************************************
Does a table creation operation for MySQL. If the name of the table
to be created is equal with one of the predefined magic table names,
then this also starts printing the corresponding monitor output by
the master thread. */
Drops a table for MySQL. If the name of the table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also start the printing of monitor
output by the master thread. If the table name ends in "innodb_mem_validate",
InnoDB will try to invoke mem_validate(). */
int
row_create_table_for_mysql(
......@@ -1756,13 +1757,11 @@ row_create_table_for_mysql(
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
if (srv_created_new_raw) {
fputs("InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw"
" is replaced\n"
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
fputs("InnoDB: A new raw disk partition was initialized:\n"
"InnoDB: we do not allow database modifications"
" by the user.\n"
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced with raw.\n", stderr);
dict_mem_table_free(table);
trx_commit_for_mysql(trx);
......@@ -2703,13 +2702,11 @@ row_truncate_table_for_mysql(
ut_ad(table);
if (srv_created_new_raw) {
fputs("InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw"
" is replaced\n"
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
fputs("InnoDB: A new raw disk partition was initialized:\n"
"InnoDB: we do not allow database modifications"
" by the user.\n"
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced with raw.\n", stderr);
return(DB_ERROR);
}
......@@ -2898,7 +2895,9 @@ next_rec:
/* MySQL calls ha_innobase::reset_auto_increment() which does
the same thing. */
dict_table_autoinc_lock(table);
dict_table_autoinc_initialize(table, 0);
dict_table_autoinc_unlock(table);
dict_update_statistics(table);
trx_commit_for_mysql(trx);
......@@ -2916,9 +2915,10 @@ funct_exit:
#endif /* !UNIV_HOTBACKUP */
/*************************************************************************
Drops a table for MySQL. If the name of the table to be dropped is equal
with one of the predefined magic table names, then this also stops printing
the corresponding monitor output by the master thread. */
Drops a table for MySQL. If the name of the dropped table ends in
one of "innodb_monitor", "innodb_lock_monitor", "innodb_tablespace_monitor",
"innodb_table_monitor", then this will also stop the printing of monitor
output by the master thread. */
int
row_drop_table_for_mysql(
......@@ -2934,21 +2934,17 @@ row_drop_table_for_mysql(
ulint err;
const char* table_name;
ulint namelen;
char* dir_path_of_temp_table = NULL;
ibool success;
ibool locked_dictionary = FALSE;
pars_info_t* info = NULL;
ut_a(name != NULL);
if (srv_created_new_raw) {
fputs("InnoDB: A new raw disk partition was initialized or\n"
"InnoDB: innodb_force_recovery is on: we do not allow\n"
"InnoDB: database modifications by the user. Shut down\n"
"InnoDB: mysqld and edit my.cnf so that newraw"
" is replaced\n"
"InnoDB: with raw, and innodb_force_... is removed.\n",
stderr);
fputs("InnoDB: A new raw disk partition was initialized:\n"
"InnoDB: we do not allow database modifications"
" by the user.\n"
"InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced with raw.\n", stderr);
return(DB_ERROR);
}
......@@ -3232,14 +3228,20 @@ check_next_foreign:
} else {
ibool is_path;
const char* name_or_path;
mem_heap_t* heap;
heap = mem_heap_create(200);
/* Clone the name, in case it has been allocated
from table->heap, which will be freed by
dict_table_remove_from_cache(table) below. */
name = mem_heap_strdup(heap, name);
space_id = table->space;
if (table->dir_path_of_temp_table != NULL) {
dir_path_of_temp_table = mem_strdup(
table->dir_path_of_temp_table);
is_path = TRUE;
name_or_path = dir_path_of_temp_table;
name_or_path = mem_heap_strdup(
heap, table->dir_path_of_temp_table);
} else {
is_path = FALSE;
name_or_path = name;
......@@ -3272,13 +3274,7 @@ check_next_foreign:
"InnoDB: of table ");
ut_print_name(stderr, trx, TRUE, name);
fprintf(stderr, ".\n");
goto funct_exit;
}
success = fil_delete_tablespace(space_id);
if (!success) {
} else if (!fil_delete_tablespace(space_id)) {
fprintf(stderr,
"InnoDB: We removed now the InnoDB"
" internal data dictionary entry\n"
......@@ -3296,6 +3292,8 @@ check_next_foreign:
err = DB_ERROR;
}
}
mem_heap_free(heap);
}
funct_exit:
......@@ -3305,10 +3303,6 @@ funct_exit:
row_mysql_unlock_data_dictionary(trx);
}
if (dir_path_of_temp_table) {
mem_free(dir_path_of_temp_table);
}
trx->op_info = "";
#ifndef UNIV_HOTBACKUP
......
......@@ -531,12 +531,13 @@ row_sel_build_prev_vers(
/*====================*/
/* out: DB_SUCCESS or error code */
read_view_t* read_view, /* in: read view */
plan_t* plan, /* in: plan node for table */
dict_index_t* index, /* in: plan node for table */
rec_t* rec, /* in: record in a clustered index */
ulint** offsets, /* in/out: offsets returned by
rec_get_offsets(rec, plan->index) */
mem_heap_t** offset_heap, /* in/out: memory heap from which
the offsets are allocated */
mem_heap_t** old_vers_heap, /* out: old version heap to use */
rec_t** old_vers, /* out: old version, or NULL if the
record does not exist in the view:
i.e., it was freshly inserted
......@@ -545,15 +546,15 @@ row_sel_build_prev_vers(
{
ulint err;
if (plan->old_vers_heap) {
mem_heap_empty(plan->old_vers_heap);
if (*old_vers_heap) {
mem_heap_empty(*old_vers_heap);
} else {
plan->old_vers_heap = mem_heap_create(512);
*old_vers_heap = mem_heap_create(512);
}
err = row_vers_build_for_consistent_read(
rec, mtr, plan->index, offsets, read_view, offset_heap,
plan->old_vers_heap, old_vers);
rec, mtr, index, offsets, read_view, offset_heap,
*old_vers_heap, old_vers);
return(err);
}
......@@ -765,9 +766,11 @@ row_sel_get_clust_rec(
if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, plan,
clust_rec, &offsets,
&heap, &old_vers, mtr);
err = row_sel_build_prev_vers(
node->read_view, index, clust_rec,
&offsets, &heap, &plan->old_vers_heap,
&old_vers, mtr);
if (err != DB_SUCCESS) {
goto err_exit;
......@@ -1490,10 +1493,11 @@ skip_lock:
if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view,
plan, rec,
&offsets, &heap,
&old_vers, &mtr);
err = row_sel_build_prev_vers(
node->read_view, index, rec,
&offsets, &heap, &plan->old_vers_heap,
&old_vers, &mtr);
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
......@@ -3999,6 +4003,7 @@ no_gap_lock:
mutex_enter(&kernel_mutex);
if (trx->was_chosen_as_deadlock_victim) {
mutex_exit(&kernel_mutex);
err = DB_DEADLOCK;
goto lock_wait_or_error;
}
......@@ -4521,7 +4526,8 @@ row_search_check_if_query_cache_permitted(
}
/***********************************************************************
Read the AUTOINC column from the current row. */
Read the AUTOINC column from the current row. If the value is less than
0 and the type is not unsigned then we reset the value to 0. */
static
ib_longlong
row_search_autoinc_read_column(
......@@ -4536,6 +4542,7 @@ row_search_autoinc_read_column(
const byte* data;
ib_longlong value;
mem_heap_t* heap = NULL;
/* Our requirement is that dest should be word aligned. */
byte dest[sizeof(value)];
ulint offsets_[REC_OFFS_NORMAL_SIZE];
ulint* offsets = offsets_;
......@@ -4554,26 +4561,43 @@ row_search_autoinc_read_column(
ut_a(len != UNIV_SQL_NULL);
ut_a(len <= sizeof value);
/* Copy integer data and restore sign bit */
if (unsigned_type || (data[0] & 128))
memset(dest, 0x00, sizeof(dest));
else
memset(dest, 0xff, sizeof(dest));
mach_read_int_type(dest, data, len, unsigned_type);
/* The assumption here is that the AUTOINC value can't be negative
and that dest is word aligned. */
switch (len) {
case 8:
value = *(ib_longlong*) dest;
break;
case 4:
value = *(ib_uint32_t*) dest;
break;
memcpy(dest + (sizeof(value) - len), data, len);
case 3:
value = *(ib_uint32_t*) dest;
value &= 0xFFFFFF;
break;
if (!unsigned_type)
dest[sizeof(value) - len] ^= 128;
case 2:
value = *(uint16 *) dest;
break;
/* The assumption here is that the AUTOINC value can't be negative.*/
value = (((ib_longlong) mach_read_from_4(dest)) << 32) |
((ib_longlong) mach_read_from_4(dest + 4));
case 1:
value = *dest;
break;
default:
ut_error;
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
ut_a(value >= 0);
if (!unsigned_type && value < 0) {
value = 0;
}
return(value);
}
......
......@@ -174,9 +174,7 @@ rw_lock_free(
/*=========*/
rw_lock_t* lock) /* in: rw-lock */
{
#ifdef UNIV_DEBUG
ut_a(rw_lock_validate(lock));
#endif /* UNIV_DEBUG */
ut_ad(rw_lock_validate(lock));
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
ut_a(rw_lock_get_waiters(lock) == 0);
ut_a(rw_lock_get_reader_count(lock) == 0);
......@@ -199,6 +197,7 @@ rw_lock_free(
mutex_exit(&rw_lock_list_mutex);
}
#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the rw-lock has been initialized and that there are no
simultaneous shared and exclusive locks. */
......@@ -226,6 +225,7 @@ rw_lock_validate(
return(TRUE);
}
#endif /* UNIV_DEBUG */
/**********************************************************************
Lock an rw-lock in shared mode for the current thread. If the rw-lock is
......
......@@ -830,7 +830,7 @@ sync_thread_levels_g(
mutex = slot->latch;
fprintf(stderr,
"InnoDB error: sync levels should be"
"InnoDB: sync levels should be"
" > %lu but a level is %lu\n",
(ulong) limit, (ulong) slot->level);
......
......@@ -18,6 +18,7 @@ Created 5/11/1994 Heikki Tuuri
#include "ut0sort.h"
#include "trx0trx.h"
#include "ha_prototypes.h"
ibool ut_always_false = FALSE;
......@@ -70,22 +71,6 @@ ut_gettimeofday(
#define ut_gettimeofday gettimeofday
#endif
#ifndef UNIV_HOTBACKUP
/*********************************************************************
Display an SQL identifier.
This definition must match the one in sql/ha_innodb.cc! */
extern
void
innobase_print_identifier(
/*======================*/
FILE* f, /* in: output stream */
trx_t* trx, /* in: transaction */
ibool table_id,/* in: TRUE=print a table name,
FALSE=print other identifier */
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,
but since there seem to be compiler bugs in both gcc and Visual C++,
......@@ -360,6 +345,8 @@ ut_print_buf(
const byte* data;
ulint i;
UNIV_MEM_ASSERT_RW(buf, len);
fprintf(file, " len %lu; hex ", len);
for (data = (const byte*)buf, i = 0; i < len; i++) {
......@@ -474,17 +461,20 @@ ut_print_namel(
#ifdef UNIV_HOTBACKUP
fwrite(name, 1, namelen, f);
#else
char* slash = memchr(name, '/', namelen);
if (table_id) {
char* slash = memchr(name, '/', namelen);
if (!slash) {
if (UNIV_LIKELY_NULL(slash)) {
/* Print the database name and table name separately. */
ut_ad(table_id);
goto no_db_name;
}
/* Print the database name and table name separately. */
innobase_print_identifier(f, trx, TRUE, name, slash - name);
putc('.', f);
innobase_print_identifier(f, trx, TRUE, slash + 1,
namelen - (slash - name) - 1);
} else {
no_db_name:
innobase_print_identifier(f, trx, table_id, name, namelen);
}
#endif
......@@ -515,3 +505,44 @@ ut_copy_file(
}
} while (len > 0);
}
/**************************************************************************
snprintf(). */
#ifdef __WIN__
#include <stdarg.h>
int
ut_snprintf(
/* out: number of characters that would
have been printed if the size were
unlimited, not including the terminating
'\0'. */
char* str, /* out: string */
size_t size, /* in: str size */
const char* fmt, /* in: format */
...) /* in: format values */
{
int res;
va_list ap1;
va_list ap2;
va_start(ap1, fmt);
va_start(ap2, fmt);
res = _vscprintf(fmt, ap1);
ut_a(res != -1);
if (size > 0) {
_vsnprintf(str, size, fmt, ap2);
if ((size_t) res >= size) {
str[size - 1] = '\0';
}
}
va_end(ap1);
va_end(ap2);
return(res);
}
#endif /* __WIN__ */
......@@ -314,7 +314,7 @@ case "$mode" in
fi
exit $return_value
else
log_failure_msg "Couldn't find MySQL manager or server"
log_failure_msg "Couldn't find MySQL manager ($manager) or server ($bindir/mysqld_safe)"
fi
;;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment