mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge of Percona XtraDB into MariaDB.
This commit is contained in:
15
.bzrignore
15
.bzrignore
@ -1444,6 +1444,21 @@ storage/innobase/ib_config.h
|
||||
storage/innobase/ib_config.h.in
|
||||
storage/innobase/mkinstalldirs
|
||||
storage/innobase/stamp-h1
|
||||
storage/xtradb/autom4te-2.53.cache/*
|
||||
storage/xtradb/autom4te-2.53.cache/output.0
|
||||
storage/xtradb/autom4te-2.53.cache/requests
|
||||
storage/xtradb/autom4te-2.53.cache/traces.0
|
||||
storage/xtradb/autom4te.cache/*
|
||||
storage/xtradb/autom4te.cache/output.0
|
||||
storage/xtradb/autom4te.cache/requests
|
||||
storage/xtradb/autom4te.cache/traces.0
|
||||
storage/xtradb/configure.lineno
|
||||
storage/xtradb/conftest.s1
|
||||
storage/xtradb/conftest.subs
|
||||
storage/xtradb/ib_config.h
|
||||
storage/xtradb/ib_config.h.in
|
||||
storage/xtradb/mkinstalldirs
|
||||
storage/xtradb/stamp-h1
|
||||
storage/maria/*.MAD
|
||||
storage/maria/*.MAI
|
||||
storage/maria/ma_rt_test
|
||||
|
24
BUILD/compile-innodb
Executable file
24
BUILD/compile-innodb
Executable file
@ -0,0 +1,24 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
path=`dirname $0`
|
||||
. "$path/SETUP.sh"
|
||||
|
||||
extra_flags="$pentium_cflags $fast_cflags -g"
|
||||
extra_configs="$pentium_configs $static_link --with-plugins=innobase"
|
||||
|
||||
. "$path/FINISH.sh"
|
24
BUILD/compile-innodb-debug
Executable file
24
BUILD/compile-innodb-debug
Executable file
@ -0,0 +1,24 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
path=`dirname $0`
|
||||
. "$path/SETUP.sh" $@ --with-debug=full
|
||||
|
||||
extra_flags="$pentium_cflags $debug_cflags"
|
||||
extra_configs="$pentium_configs $debug_configs --with-plugins=innobase"
|
||||
|
||||
. "$path/FINISH.sh"
|
@ -263,7 +263,7 @@ IF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/federated)
|
||||
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
IF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/innobase)
|
||||
ADD_SUBDIRECTORY(storage/xtradb)
|
||||
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
IF(WITH_MARIA_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/maria)
|
||||
|
49
configure.in
49
configure.in
@ -1729,6 +1729,30 @@ then
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CACHE_CHECK([whether the compiler provides atomic builtins],
|
||||
[mysql_cv_gcc_atomic_builtins], [AC_TRY_RUN([
|
||||
int main()
|
||||
{
|
||||
int foo= -10; int bar= 10;
|
||||
if (!__sync_fetch_and_add(&foo, bar) || foo)
|
||||
return -1;
|
||||
bar= __sync_lock_test_and_set(&foo, bar);
|
||||
if (bar || foo != 10)
|
||||
return -1;
|
||||
bar= __sync_val_compare_and_swap(&bar, foo, 15);
|
||||
if (bar)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
], [mysql_cv_gcc_atomic_builtins=yes],
|
||||
[mysql_cv_gcc_atomic_builtins=no],
|
||||
[mysql_cv_gcc_atomic_builtins=no])])
|
||||
|
||||
if test "x$mysql_cv_gcc_atomic_builtins" = xyes; then
|
||||
AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS, 1,
|
||||
[Define to 1 if compiler provides atomic builtins.])
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([atomic-ops],
|
||||
AC_HELP_STRING([--with-atomic-ops=rwlocks|smp|up],
|
||||
[Implement atomic operations using pthread rwlocks or atomic CPU
|
||||
@ -1742,28 +1766,9 @@ case "$with_atomic_ops" in
|
||||
[Use pthread rwlocks for atomic ops]) ;;
|
||||
"smp") ;;
|
||||
"")
|
||||
AC_CACHE_CHECK([whether the compiler provides atomic builtins],
|
||||
[mysql_cv_gcc_atomic_builtins], [AC_TRY_RUN([
|
||||
int main()
|
||||
{
|
||||
int foo= -10; int bar= 10;
|
||||
if (!__sync_fetch_and_add(&foo, bar) || foo)
|
||||
return -1;
|
||||
bar= __sync_lock_test_and_set(&foo, bar);
|
||||
if (bar || foo != 10)
|
||||
return -1;
|
||||
bar= __sync_val_compare_and_swap(&bar, foo, 15);
|
||||
if (bar)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
], [mysql_cv_gcc_atomic_builtins=yes_but_disabled],
|
||||
[mysql_cv_gcc_atomic_builtins=no],
|
||||
[mysql_cv_gcc_atomic_builtins=no])])
|
||||
|
||||
if test "x$mysql_cv_gcc_atomic_builtins" = xyes; then
|
||||
AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS, 1,
|
||||
[Define to 1 if compiler provides atomic builtins.])
|
||||
if test "x$mysql_cv_gcc_atomic_builtins" = xyes_but_disabled; then
|
||||
AC_DEFINE([MY_ATOMIC_MODE_GCC_BUILTINS], [1],
|
||||
[Use GCC atomic builtins for atomic ops])
|
||||
fi
|
||||
;;
|
||||
*) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;;
|
||||
|
@ -14,7 +14,7 @@
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#if defined(__i386__) || defined(_MSC_VER) || \
|
||||
defined(__x86_64__) || defined(HAVE_GCC_ATOMIC_BUILTINS)
|
||||
defined(__x86_64__) || defined(MY_ATOMIC_MODE_GCC_BUILTINS)
|
||||
|
||||
# ifdef MY_ATOMIC_MODE_DUMMY
|
||||
# define LOCK_prefix ""
|
||||
@ -22,7 +22,7 @@
|
||||
# define LOCK_prefix "lock"
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_GCC_ATOMIC_BUILTINS
|
||||
# ifdef MY_ATOMIC_MODE_GCC_BUILTINS
|
||||
# include "gcc_builtins.h"
|
||||
# elif __GNUC__
|
||||
# include "x86-gcc.h"
|
||||
|
@ -791,6 +791,9 @@ extern size_t my_b_gets(IO_CACHE *info, char *to, size_t max_length);
|
||||
extern my_off_t my_b_filelength(IO_CACHE *info);
|
||||
extern size_t my_b_printf(IO_CACHE *info, const char* fmt, ...);
|
||||
extern size_t my_b_vprintf(IO_CACHE *info, const char* fmt, va_list ap);
|
||||
extern int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||
const char *default_val);
|
||||
extern int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
|
||||
extern my_bool open_cached_file(IO_CACHE *cache,const char *dir,
|
||||
const char *prefix, size_t cache_size,
|
||||
myf cache_myflags);
|
||||
|
@ -132,9 +132,9 @@ IF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
|
||||
IF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/innobase/CMakeLists.txt)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/xtradb/CMakeLists.txt)
|
||||
FOREACH(rpath ${INNOBASE_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/innobase/${rpath})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/xtradb/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
|
||||
|
26
mysql-test/include/innodb-index.inc
Normal file
26
mysql-test/include/innodb-index.inc
Normal file
@ -0,0 +1,26 @@
|
||||
--eval create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb default charset=$charset
|
||||
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
|
||||
commit;
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (b);
|
||||
insert into t1 values(8,9,'fff','fff');
|
||||
select * from t1;
|
||||
show create table t1;
|
||||
alter table t1 add index (b);
|
||||
insert into t1 values(10,10,'kkk','iii');
|
||||
select * from t1;
|
||||
select * from t1 force index(b) order by b;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
show create table t1;
|
||||
alter table t1 add unique index (c), add index (d);
|
||||
insert into t1 values(11,11,'aaa','mmm');
|
||||
select * from t1;
|
||||
select * from t1 force index(b) order by b;
|
||||
select * from t1 force index(c) order by c;
|
||||
select * from t1 force index(d) order by d;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
explain select * from t1 force index(d) order by d;
|
||||
show create table t1;
|
||||
check table t1;
|
||||
drop table t1;
|
@ -111,7 +111,7 @@ count(*)
|
||||
explain select count(*) from t1 where
|
||||
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 4 Using intersect(i1,i2); Using where; Using index
|
||||
1 SIMPLE t1 index_merge i1,i2 i1,i2 10,10 NULL 3 Using intersect(i1,i2); Using where; Using index
|
||||
select count(*) from t1 where
|
||||
key1a = 2 and key1b is null and key2a = 2 and key2b is null;
|
||||
count(*)
|
||||
@ -119,7 +119,7 @@ count(*)
|
||||
explain select count(*) from t1 where
|
||||
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 4 Using intersect(i1,i3); Using where; Using index
|
||||
1 SIMPLE t1 index_merge i1,i3 i1,i3 10,10 NULL 3 Using intersect(i1,i3); Using where; Using index
|
||||
select count(*) from t1 where
|
||||
key1a = 2 and key1b is null and key3a = 2 and key3b is null;
|
||||
count(*)
|
||||
|
@ -42,7 +42,7 @@ WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND
|
||||
table_name<>'ndb_binlog_index' AND
|
||||
table_name<>'ndb_apply_status' AND
|
||||
NOT (table_schema = 'INFORMATION_SCHEMA' AND table_name LIKE 'PBXT_%');
|
||||
select * from v1;
|
||||
select * from v1 ORDER BY c COLLATE utf8_bin;
|
||||
c
|
||||
CHARACTER_SETS
|
||||
COLLATIONS
|
||||
@ -54,6 +54,17 @@ EVENTS
|
||||
FILES
|
||||
GLOBAL_STATUS
|
||||
GLOBAL_VARIABLES
|
||||
INNODB_BUFFER_POOL_PAGES
|
||||
INNODB_BUFFER_POOL_PAGES_BLOB
|
||||
INNODB_BUFFER_POOL_PAGES_INDEX
|
||||
INNODB_CMP
|
||||
INNODB_CMPMEM
|
||||
INNODB_CMPMEM_RESET
|
||||
INNODB_CMP_RESET
|
||||
INNODB_LOCKS
|
||||
INNODB_LOCK_WAITS
|
||||
INNODB_RSEG
|
||||
INNODB_TRX
|
||||
KEY_COLUMN_USAGE
|
||||
PARTITIONS
|
||||
PLUGINS
|
||||
@ -72,6 +83,7 @@ TABLE_PRIVILEGES
|
||||
TRIGGERS
|
||||
USER_PRIVILEGES
|
||||
VIEWS
|
||||
XTRADB_ENHANCEMENTS
|
||||
columns_priv
|
||||
db
|
||||
event
|
||||
@ -87,6 +99,11 @@ proc
|
||||
procs_priv
|
||||
servers
|
||||
slow_log
|
||||
t1
|
||||
t2
|
||||
t3
|
||||
t4
|
||||
t5
|
||||
tables_priv
|
||||
time_zone
|
||||
time_zone_leap_second
|
||||
@ -94,11 +111,6 @@ time_zone_name
|
||||
time_zone_transition
|
||||
time_zone_transition_type
|
||||
user
|
||||
t1
|
||||
t4
|
||||
t2
|
||||
t3
|
||||
t5
|
||||
v1
|
||||
select c,table_name from v1
|
||||
inner join information_schema.TABLES v2 on (v1.c=v2.table_name)
|
||||
@ -800,6 +812,8 @@ TABLES CREATE_TIME datetime
|
||||
TABLES UPDATE_TIME datetime
|
||||
TABLES CHECK_TIME datetime
|
||||
TRIGGERS CREATED datetime
|
||||
INNODB_TRX trx_started datetime
|
||||
INNODB_TRX trx_wait_started datetime
|
||||
event execute_at datetime
|
||||
event last_executed datetime
|
||||
event starts datetime
|
||||
@ -848,6 +862,7 @@ TABLES TABLE_NAME select
|
||||
TABLE_CONSTRAINTS TABLE_NAME select
|
||||
TABLE_PRIVILEGES TABLE_NAME select
|
||||
VIEWS TABLE_NAME select
|
||||
INNODB_BUFFER_POOL_PAGES_INDEX table_name select
|
||||
delete from mysql.user where user='mysqltest_4';
|
||||
delete from mysql.db where user='mysqltest_4';
|
||||
flush privileges;
|
||||
@ -1223,12 +1238,12 @@ DROP PROCEDURE p1;
|
||||
DROP USER mysql_bug20230@localhost;
|
||||
SELECT MAX(table_name) FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test');
|
||||
MAX(table_name)
|
||||
VIEWS
|
||||
XTRADB_ENHANCEMENTS
|
||||
SELECT table_name from information_schema.tables
|
||||
WHERE table_name=(SELECT MAX(table_name)
|
||||
FROM information_schema.tables WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test'));
|
||||
table_name
|
||||
VIEWS
|
||||
XTRADB_ENHANCEMENTS
|
||||
DROP TABLE IF EXISTS bug23037;
|
||||
DROP FUNCTION IF EXISTS get_value;
|
||||
SELECT COLUMN_NAME, MD5(COLUMN_DEFAULT), LENGTH(COLUMN_DEFAULT) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='bug23037';
|
||||
|
@ -29,7 +29,19 @@ TABLE_PRIVILEGES
|
||||
TRIGGERS
|
||||
USER_PRIVILEGES
|
||||
VIEWS
|
||||
INNODB_BUFFER_POOL_PAGES
|
||||
PBXT_STATISTICS
|
||||
INNODB_CMP
|
||||
INNODB_RSEG
|
||||
XTRADB_ENHANCEMENTS
|
||||
INNODB_BUFFER_POOL_PAGES_INDEX
|
||||
INNODB_BUFFER_POOL_PAGES_BLOB
|
||||
INNODB_TRX
|
||||
INNODB_CMP_RESET
|
||||
INNODB_LOCK_WAITS
|
||||
INNODB_CMPMEM_RESET
|
||||
INNODB_LOCKS
|
||||
INNODB_CMPMEM
|
||||
SELECT t.table_name, c1.column_name
|
||||
FROM information_schema.tables t
|
||||
INNER JOIN
|
||||
@ -73,7 +85,19 @@ TABLE_PRIVILEGES TABLE_SCHEMA
|
||||
TRIGGERS TRIGGER_SCHEMA
|
||||
USER_PRIVILEGES GRANTEE
|
||||
VIEWS TABLE_SCHEMA
|
||||
INNODB_BUFFER_POOL_PAGES page_type
|
||||
PBXT_STATISTICS ID
|
||||
INNODB_CMP page_size
|
||||
INNODB_RSEG rseg_id
|
||||
XTRADB_ENHANCEMENTS name
|
||||
INNODB_BUFFER_POOL_PAGES_INDEX schema_name
|
||||
INNODB_BUFFER_POOL_PAGES_BLOB space_id
|
||||
INNODB_TRX trx_id
|
||||
INNODB_CMP_RESET page_size
|
||||
INNODB_LOCK_WAITS requesting_trx_id
|
||||
INNODB_CMPMEM_RESET page_size
|
||||
INNODB_LOCKS lock_id
|
||||
INNODB_CMPMEM page_size
|
||||
SELECT t.table_name, c1.column_name
|
||||
FROM information_schema.tables t
|
||||
INNER JOIN
|
||||
@ -117,7 +141,19 @@ TABLE_PRIVILEGES TABLE_SCHEMA
|
||||
TRIGGERS TRIGGER_SCHEMA
|
||||
USER_PRIVILEGES GRANTEE
|
||||
VIEWS TABLE_SCHEMA
|
||||
INNODB_BUFFER_POOL_PAGES page_type
|
||||
PBXT_STATISTICS ID
|
||||
INNODB_CMP page_size
|
||||
INNODB_RSEG rseg_id
|
||||
XTRADB_ENHANCEMENTS name
|
||||
INNODB_BUFFER_POOL_PAGES_INDEX schema_name
|
||||
INNODB_BUFFER_POOL_PAGES_BLOB space_id
|
||||
INNODB_TRX trx_id
|
||||
INNODB_CMP_RESET page_size
|
||||
INNODB_LOCK_WAITS requesting_trx_id
|
||||
INNODB_CMPMEM_RESET page_size
|
||||
INNODB_LOCKS lock_id
|
||||
INNODB_CMPMEM page_size
|
||||
select 1 as f1 from information_schema.tables where "CHARACTER_SETS"=
|
||||
(select cast(table_name as char) from information_schema.tables
|
||||
order by table_name limit 1) limit 1;
|
||||
@ -149,6 +185,17 @@ EVENTS information_schema.EVENTS 1
|
||||
FILES information_schema.FILES 1
|
||||
GLOBAL_STATUS information_schema.GLOBAL_STATUS 1
|
||||
GLOBAL_VARIABLES information_schema.GLOBAL_VARIABLES 1
|
||||
INNODB_BUFFER_POOL_PAGES information_schema.INNODB_BUFFER_POOL_PAGES 1
|
||||
INNODB_BUFFER_POOL_PAGES_BLOB information_schema.INNODB_BUFFER_POOL_PAGES_BLOB 1
|
||||
INNODB_BUFFER_POOL_PAGES_INDEX information_schema.INNODB_BUFFER_POOL_PAGES_INDEX 1
|
||||
INNODB_CMP information_schema.INNODB_CMP 1
|
||||
INNODB_CMPMEM information_schema.INNODB_CMPMEM 1
|
||||
INNODB_CMPMEM_RESET information_schema.INNODB_CMPMEM_RESET 1
|
||||
INNODB_CMP_RESET information_schema.INNODB_CMP_RESET 1
|
||||
INNODB_LOCKS information_schema.INNODB_LOCKS 1
|
||||
INNODB_LOCK_WAITS information_schema.INNODB_LOCK_WAITS 1
|
||||
INNODB_RSEG information_schema.INNODB_RSEG 1
|
||||
INNODB_TRX information_schema.INNODB_TRX 1
|
||||
KEY_COLUMN_USAGE information_schema.KEY_COLUMN_USAGE 1
|
||||
PARTITIONS information_schema.PARTITIONS 1
|
||||
PBXT_STATISTICS information_schema.PBXT_STATISTICS 1
|
||||
@ -168,6 +215,7 @@ TABLE_PRIVILEGES information_schema.TABLE_PRIVILEGES 1
|
||||
TRIGGERS information_schema.TRIGGERS 1
|
||||
USER_PRIVILEGES information_schema.USER_PRIVILEGES 1
|
||||
VIEWS information_schema.VIEWS 1
|
||||
XTRADB_ENHANCEMENTS information_schema.XTRADB_ENHANCEMENTS 1
|
||||
Database: information_schema
|
||||
+---------------------------------------+
|
||||
| Tables |
|
||||
@ -200,7 +248,19 @@ Database: information_schema
|
||||
| TRIGGERS |
|
||||
| USER_PRIVILEGES |
|
||||
| VIEWS |
|
||||
| INNODB_BUFFER_POOL_PAGES |
|
||||
| PBXT_STATISTICS |
|
||||
| INNODB_CMP |
|
||||
| INNODB_RSEG |
|
||||
| XTRADB_ENHANCEMENTS |
|
||||
| INNODB_BUFFER_POOL_PAGES_INDEX |
|
||||
| INNODB_BUFFER_POOL_PAGES_BLOB |
|
||||
| INNODB_TRX |
|
||||
| INNODB_CMP_RESET |
|
||||
| INNODB_LOCK_WAITS |
|
||||
| INNODB_CMPMEM_RESET |
|
||||
| INNODB_LOCKS |
|
||||
| INNODB_CMPMEM |
|
||||
+---------------------------------------+
|
||||
Database: INFORMATION_SCHEMA
|
||||
+---------------------------------------+
|
||||
@ -234,7 +294,19 @@ Database: INFORMATION_SCHEMA
|
||||
| TRIGGERS |
|
||||
| USER_PRIVILEGES |
|
||||
| VIEWS |
|
||||
| INNODB_BUFFER_POOL_PAGES |
|
||||
| PBXT_STATISTICS |
|
||||
| INNODB_CMP |
|
||||
| INNODB_RSEG |
|
||||
| XTRADB_ENHANCEMENTS |
|
||||
| INNODB_BUFFER_POOL_PAGES_INDEX |
|
||||
| INNODB_BUFFER_POOL_PAGES_BLOB |
|
||||
| INNODB_TRX |
|
||||
| INNODB_CMP_RESET |
|
||||
| INNODB_LOCK_WAITS |
|
||||
| INNODB_CMPMEM_RESET |
|
||||
| INNODB_LOCKS |
|
||||
| INNODB_CMPMEM |
|
||||
+---------------------------------------+
|
||||
Wildcard: inf_rmation_schema
|
||||
+--------------------+
|
||||
@ -244,5 +316,5 @@ Wildcard: inf_rmation_schema
|
||||
+--------------------+
|
||||
SELECT table_schema, count(*) FROM information_schema.TABLES WHERE table_schema IN ('mysql', 'INFORMATION_SCHEMA', 'test', 'mysqltest') AND table_name<>'ndb_binlog_index' AND table_name<>'ndb_apply_status' GROUP BY TABLE_SCHEMA;
|
||||
table_schema count(*)
|
||||
information_schema 29
|
||||
information_schema 41
|
||||
mysql 22
|
||||
|
2
mysql-test/r/innodb-analyze.result
Normal file
2
mysql-test/r/innodb-analyze.result
Normal file
@ -0,0 +1,2 @@
|
||||
Variable_name Value
|
||||
innodb_stats_sample_pages 1
|
@ -581,11 +581,10 @@ c1
|
||||
DROP TABLE t1;
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
SHOW VARIABLES LIKE "auto_inc%";
|
||||
Variable_name Value
|
||||
auto_increment_increment 1
|
||||
auto_increment_offset 1
|
||||
pbxt_auto_increment_mode 0
|
||||
CREATE TABLE t1 (c1 DOUBLE NOT NULL AUTO_INCREMENT, c2 INT, PRIMARY KEY (c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL, 1);
|
||||
INSERT INTO t1 VALUES(NULL, 2);
|
||||
|
1137
mysql-test/r/innodb-index.result
Normal file
1137
mysql-test/r/innodb-index.result
Normal file
File diff suppressed because it is too large
Load Diff
116
mysql-test/r/innodb-index_ucs2.result
Normal file
116
mysql-test/r/innodb-index_ucs2.result
Normal file
@ -0,0 +1,116 @@
|
||||
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb default charset=ucs2;
|
||||
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
|
||||
commit;
|
||||
alter table t1 add unique index (b);
|
||||
ERROR 23000: Duplicate entry '2' for key 'b'
|
||||
insert into t1 values(8,9,'fff','fff');
|
||||
select * from t1;
|
||||
a b c d
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`d` varchar(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=ucs2
|
||||
alter table t1 add index (b);
|
||||
insert into t1 values(10,10,'kkk','iii');
|
||||
select * from t1;
|
||||
a b c d
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
10 10 kkk iii
|
||||
select * from t1 force index(b) order by b;
|
||||
a b c d
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
10 10 kkk iii
|
||||
explain select * from t1 force index(b) order by b;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL b 5 NULL 6
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`d` varchar(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`),
|
||||
KEY `b` (`b`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=ucs2
|
||||
alter table t1 add unique index (c), add index (d);
|
||||
insert into t1 values(11,11,'aaa','mmm');
|
||||
select * from t1;
|
||||
a b c d
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
10 10 kkk iii
|
||||
11 11 aaa mmm
|
||||
select * from t1 force index(b) order by b;
|
||||
a b c d
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
10 10 kkk iii
|
||||
11 11 aaa mmm
|
||||
select * from t1 force index(c) order by c;
|
||||
a b c d
|
||||
11 11 aaa mmm
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
10 10 kkk iii
|
||||
select * from t1 force index(d) order by d;
|
||||
a b c d
|
||||
1 1 ab ab
|
||||
2 2 ac ac
|
||||
3 2 ad ad
|
||||
4 4 afe afe
|
||||
8 9 fff fff
|
||||
10 10 kkk iii
|
||||
11 11 aaa mmm
|
||||
explain select * from t1 force index(b) order by b;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL b 5 NULL 7
|
||||
explain select * from t1 force index(c) order by c;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL c 21 NULL 7
|
||||
explain select * from t1 force index(d) order by d;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index NULL d 43 NULL 7
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL,
|
||||
`b` int(11) DEFAULT NULL,
|
||||
`c` char(10) DEFAULT NULL,
|
||||
`d` varchar(20) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`),
|
||||
UNIQUE KEY `c` (`c`),
|
||||
KEY `b` (`b`),
|
||||
KEY `d` (`d`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=ucs2
|
||||
check table t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
drop table t1;
|
38
mysql-test/r/innodb-timeout.result
Normal file
38
mysql-test/r/innodb-timeout.result
Normal file
@ -0,0 +1,38 @@
|
||||
set global innodb_lock_wait_timeout=42;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
@@innodb_lock_wait_timeout
|
||||
42
|
||||
set innodb_lock_wait_timeout=1;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
@@innodb_lock_wait_timeout
|
||||
1
|
||||
select @@innodb_lock_wait_timeout;
|
||||
@@innodb_lock_wait_timeout
|
||||
42
|
||||
set global innodb_lock_wait_timeout=347;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
@@innodb_lock_wait_timeout
|
||||
42
|
||||
set innodb_lock_wait_timeout=1;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
@@innodb_lock_wait_timeout
|
||||
1
|
||||
select @@innodb_lock_wait_timeout;
|
||||
@@innodb_lock_wait_timeout
|
||||
347
|
||||
create table t1(a int primary key)engine=innodb;
|
||||
begin;
|
||||
insert into t1 values(1),(2),(3);
|
||||
select * from t1 for update;
|
||||
commit;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
begin;
|
||||
insert into t1 values(4);
|
||||
select * from t1 for update;
|
||||
commit;
|
||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||
drop table t1;
|
||||
set global innodb_lock_wait_timeout=50;
|
48
mysql-test/r/innodb-use-sys-malloc.result
Normal file
48
mysql-test/r/innodb-use-sys-malloc.result
Normal file
@ -0,0 +1,48 @@
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
@@GLOBAL.innodb_use_sys_malloc
|
||||
1
|
||||
1 Expected
|
||||
SET @@GLOBAL.innodb_use_sys_malloc=0;
|
||||
ERROR HY000: Variable 'innodb_use_sys_malloc' is a read only variable
|
||||
Expected error 'Read only variable'
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
@@GLOBAL.innodb_use_sys_malloc
|
||||
1
|
||||
1 Expected
|
||||
drop table if exists t1;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
drop table t1;
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
@@GLOBAL.innodb_use_sys_malloc
|
||||
1
|
||||
1 Expected
|
||||
SET @@GLOBAL.innodb_use_sys_malloc=0;
|
||||
ERROR HY000: Variable 'innodb_use_sys_malloc' is a read only variable
|
||||
Expected error 'Read only variable'
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
@@GLOBAL.innodb_use_sys_malloc
|
||||
1
|
||||
1 Expected
|
||||
drop table if exists t1;
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
|
||||
select * from t1;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
drop table t1;
|
421
mysql-test/r/innodb-zip.result
Normal file
421
mysql-test/r/innodb-zip.result
Normal file
@ -0,0 +1,421 @@
|
||||
set global innodb_file_per_table=off;
|
||||
set global innodb_file_format=`0`;
|
||||
create table t0(a int primary key) engine=innodb row_format=compressed;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
create table t00(a int primary key) engine=innodb
|
||||
key_block_size=4 row_format=compressed;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=4.
|
||||
Warning 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
create table t1(a int primary key) engine=innodb row_format=dynamic;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
create table t2(a int primary key) engine=innodb row_format=redundant;
|
||||
create table t3(a int primary key) engine=innodb row_format=compact;
|
||||
create table t4(a int primary key) engine=innodb key_block_size=9;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=9.
|
||||
create table t5(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=redundant;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1.
|
||||
set global innodb_file_per_table=on;
|
||||
create table t6(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=redundant;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1.
|
||||
set global innodb_file_format=`1`;
|
||||
create table t7(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=redundant;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED.
|
||||
create table t8(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=fixed;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED.
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
create table t9(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=compact;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED.
|
||||
create table t10(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=dynamic;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=1 unless ROW_FORMAT=COMPRESSED.
|
||||
create table t11(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=compressed;
|
||||
create table t12(a int primary key) engine=innodb
|
||||
key_block_size=1;
|
||||
create table t13(a int primary key) engine=innodb
|
||||
row_format=compressed;
|
||||
create table t14(a int primary key) engine=innodb key_block_size=9;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=9.
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t0 Compact
|
||||
test t00 Compact
|
||||
test t1 Compact
|
||||
test t10 Dynamic
|
||||
test t11 Compressed
|
||||
test t12 Compressed
|
||||
test t13 Compressed
|
||||
test t14 Compact
|
||||
test t2 Redundant
|
||||
test t3 Compact
|
||||
test t4 Compact
|
||||
test t5 Redundant
|
||||
test t6 Redundant
|
||||
test t7 Redundant
|
||||
test t8 Compact
|
||||
test t9 Compact
|
||||
drop table t0,t00,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14;
|
||||
alter table t1 key_block_size=0;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=0.
|
||||
alter table t1 row_format=dynamic;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t1 Dynamic
|
||||
alter table t1 row_format=compact;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t1 Compact
|
||||
alter table t1 row_format=redundant;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t1 Redundant
|
||||
drop table t1;
|
||||
create table t1(a int not null, b text, index(b(10))) engine=innodb
|
||||
key_block_size=1;
|
||||
create table t2(b text)engine=innodb;
|
||||
insert into t2 values(concat('1abcdefghijklmnopqrstuvwxyz', repeat('A',5000)));
|
||||
insert into t1 select 1, b from t2;
|
||||
commit;
|
||||
begin;
|
||||
update t1 set b=repeat('B',100);
|
||||
select a,left(b,40) from t1 natural join t2;
|
||||
a left(b,40)
|
||||
1 1abcdefghijklmnopqrstuvwxyzAAAAAAAAAAAAA
|
||||
rollback;
|
||||
select a,left(b,40) from t1 natural join t2;
|
||||
a left(b,40)
|
||||
1 1abcdefghijklmnopqrstuvwxyzAAAAAAAAAAAAA
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t1 Compressed
|
||||
test t2 Compact
|
||||
drop table t1,t2;
|
||||
SET SESSION innodb_strict_mode = off;
|
||||
CREATE TABLE t1(
|
||||
c TEXT NOT NULL, d TEXT NOT NULL,
|
||||
PRIMARY KEY (c(767),d(767)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
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
|
||||
CREATE TABLE t1(
|
||||
c TEXT NOT NULL, d TEXT NOT NULL,
|
||||
PRIMARY KEY (c(767),d(767)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2 CHARSET=ASCII;
|
||||
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
|
||||
CREATE TABLE t1(
|
||||
c TEXT NOT NULL, d TEXT NOT NULL,
|
||||
PRIMARY KEY (c(767),d(767)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 CHARSET=ASCII;
|
||||
drop table t1;
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
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
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
|
||||
DROP TABLE t1;
|
||||
create table t1( c1 int not null, c2 blob, c3 blob, c4 blob,
|
||||
primary key(c1, c2(22), c3(22)))
|
||||
engine = innodb row_format = dynamic;
|
||||
begin;
|
||||
insert into t1 values(1, repeat('A', 20000), repeat('B', 20000),
|
||||
repeat('C', 20000));
|
||||
update t1 set c3 = repeat('D', 20000) where c1 = 1;
|
||||
commit;
|
||||
select count(*) from t1 where c2 = repeat('A', 20000);
|
||||
count(*)
|
||||
1
|
||||
select count(*) from t1 where c3 = repeat('D', 20000);
|
||||
count(*)
|
||||
1
|
||||
select count(*) from t1 where c4 = repeat('C', 20000);
|
||||
count(*)
|
||||
1
|
||||
update t1 set c3 = repeat('E', 20000) where c1 = 1;
|
||||
drop table t1;
|
||||
set global innodb_file_format=`0`;
|
||||
select @@innodb_file_format;
|
||||
@@innodb_file_format
|
||||
Antelope
|
||||
set global innodb_file_format=`1`;
|
||||
select @@innodb_file_format;
|
||||
@@innodb_file_format
|
||||
Barracuda
|
||||
set global innodb_file_format=`2`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=`-1`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=`Antelope`;
|
||||
set global innodb_file_format=`Barracuda`;
|
||||
set global innodb_file_format=`Cheetah`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=`abc`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=`1a`;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=``;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_per_table = on;
|
||||
set global innodb_file_format = `1`;
|
||||
set innodb_strict_mode = off;
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 0;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: ignoring KEY_BLOCK_SIZE=0.
|
||||
drop table t1;
|
||||
set innodb_strict_mode = on;
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 0;
|
||||
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 0. Valid values are [1, 2, 4, 8, 16]
|
||||
Error 1005 Can't create table 'test.t1' (errno: 1478)
|
||||
create table t2 (id int primary key) engine = innodb key_block_size = 9;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
|
||||
Error 1005 Can't create table 'test.t2' (errno: 1478)
|
||||
create table t3 (id int primary key) engine = innodb key_block_size = 1;
|
||||
create table t4 (id int primary key) engine = innodb key_block_size = 2;
|
||||
create table t5 (id int primary key) engine = innodb key_block_size = 4;
|
||||
create table t6 (id int primary key) engine = innodb key_block_size = 8;
|
||||
create table t7 (id int primary key) engine = innodb key_block_size = 16;
|
||||
create table t8 (id int primary key) engine = innodb row_format = compressed;
|
||||
create table t9 (id int primary key) engine = innodb row_format = dynamic;
|
||||
create table t10(id int primary key) engine = innodb row_format = compact;
|
||||
create table t11(id int primary key) engine = innodb row_format = redundant;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t10 Compact
|
||||
test t11 Redundant
|
||||
test t3 Compressed
|
||||
test t4 Compressed
|
||||
test t5 Compressed
|
||||
test t6 Compressed
|
||||
test t7 Compressed
|
||||
test t8 Compressed
|
||||
test t9 Dynamic
|
||||
drop table t3, t4, t5, t6, t7, t8, t9, t10, t11;
|
||||
create table t1 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = compressed;
|
||||
create table t2 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = redundant;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t2' (errno: 1478)
|
||||
create table t3 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = compact;
|
||||
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t3' (errno: 1478)
|
||||
create table t4 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = dynamic;
|
||||
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t4' (errno: 1478)
|
||||
create table t5 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = default;
|
||||
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t5' (errno: 1478)
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t1 Compressed
|
||||
drop table t1;
|
||||
create table t1 (id int primary key) engine = innodb
|
||||
key_block_size = 9 row_format = redundant;
|
||||
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = REDUNDANT with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t1' (errno: 1478)
|
||||
create table t2 (id int primary key) engine = innodb
|
||||
key_block_size = 9 row_format = compact;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = COMPACT with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t2' (errno: 1478)
|
||||
create table t2 (id int primary key) engine = innodb
|
||||
key_block_size = 9 row_format = dynamic;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: invalid KEY_BLOCK_SIZE = 9. Valid values are [1, 2, 4, 8, 16]
|
||||
Error 1478 InnoDB: cannot specify ROW_FORMAT = DYNAMIC with KEY_BLOCK_SIZE.
|
||||
Error 1005 Can't create table 'test.t2' (errno: 1478)
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
set global innodb_file_per_table = off;
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 1;
|
||||
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t1' (errno: 1478)
|
||||
create table t2 (id int primary key) engine = innodb key_block_size = 2;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t2' (errno: 1478)
|
||||
create table t3 (id int primary key) engine = innodb key_block_size = 4;
|
||||
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t3' (errno: 1478)
|
||||
create table t4 (id int primary key) engine = innodb key_block_size = 8;
|
||||
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t4' (errno: 1478)
|
||||
create table t5 (id int primary key) engine = innodb key_block_size = 16;
|
||||
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t5' (errno: 1478)
|
||||
create table t6 (id int primary key) engine = innodb row_format = compressed;
|
||||
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t6' (errno: 1478)
|
||||
create table t7 (id int primary key) engine = innodb row_format = dynamic;
|
||||
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_per_table.
|
||||
Error 1005 Can't create table 'test.t7' (errno: 1478)
|
||||
create table t8 (id int primary key) engine = innodb row_format = compact;
|
||||
create table t9 (id int primary key) engine = innodb row_format = redundant;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t8 Compact
|
||||
test t9 Redundant
|
||||
drop table t8, t9;
|
||||
set global innodb_file_per_table = on;
|
||||
set global innodb_file_format = `0`;
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 1;
|
||||
ERROR HY000: Can't create table 'test.t1' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t1' (errno: 1478)
|
||||
create table t2 (id int primary key) engine = innodb key_block_size = 2;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t2' (errno: 1478)
|
||||
create table t3 (id int primary key) engine = innodb key_block_size = 4;
|
||||
ERROR HY000: Can't create table 'test.t3' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t3' (errno: 1478)
|
||||
create table t4 (id int primary key) engine = innodb key_block_size = 8;
|
||||
ERROR HY000: Can't create table 'test.t4' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t4' (errno: 1478)
|
||||
create table t5 (id int primary key) engine = innodb key_block_size = 16;
|
||||
ERROR HY000: Can't create table 'test.t5' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t5' (errno: 1478)
|
||||
create table t6 (id int primary key) engine = innodb row_format = compressed;
|
||||
ERROR HY000: Can't create table 'test.t6' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t6' (errno: 1478)
|
||||
create table t7 (id int primary key) engine = innodb row_format = dynamic;
|
||||
ERROR HY000: Can't create table 'test.t7' (errno: 1478)
|
||||
show errors;
|
||||
Level Code Message
|
||||
Error 1478 InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope.
|
||||
Error 1005 Can't create table 'test.t7' (errno: 1478)
|
||||
create table t8 (id int primary key) engine = innodb row_format = compact;
|
||||
create table t9 (id int primary key) engine = innodb row_format = redundant;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
table_schema table_name row_format
|
||||
test t8 Compact
|
||||
test t9 Redundant
|
||||
drop table t8, t9;
|
||||
set global innodb_file_per_table=0;
|
||||
set global innodb_file_format=Antelope;
|
||||
set global innodb_file_per_table=on;
|
||||
set global innodb_file_format=`Barracuda`;
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
create table normal_table (
|
||||
c1 int
|
||||
) engine = innodb;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Antelope
|
||||
create table zip_table (
|
||||
c1 int
|
||||
) engine = innodb key_block_size = 8;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Antelope
|
||||
show table status;
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
drop table normal_table, zip_table;
|
@ -1508,7 +1508,7 @@ t2 CREATE TABLE `t2` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop index id2 on t2;
|
||||
drop index id on t2;
|
||||
Got one of the listed errors
|
||||
ERROR HY000: Cannot drop index 'id': needed in a foreign key constraint
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
t2 CREATE TABLE `t2` (
|
||||
@ -1738,7 +1738,7 @@ count(*)
|
||||
drop table t1;
|
||||
show status like "Innodb_buffer_pool_pages_total";
|
||||
Variable_name Value
|
||||
Innodb_buffer_pool_pages_total 512
|
||||
Innodb_buffer_pool_pages_total 511
|
||||
show status like "Innodb_page_size";
|
||||
Variable_name Value
|
||||
Innodb_page_size 16384
|
||||
@ -1784,7 +1784,7 @@ innodb_sync_spin_loops 20
|
||||
SET @old_innodb_thread_concurrency= @@global.innodb_thread_concurrency;
|
||||
show variables like "innodb_thread_concurrency";
|
||||
Variable_name Value
|
||||
innodb_thread_concurrency 8
|
||||
innodb_thread_concurrency 0
|
||||
set global innodb_thread_concurrency=1001;
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect thread_concurrency value: '1001'
|
||||
@ -1970,7 +1970,7 @@ explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a '
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref v v 13 const # Using where; Using index
|
||||
alter table t1 add unique(v);
|
||||
ERROR 23000: Duplicate entry '{ ' for key 'v_2'
|
||||
ERROR 23000: Duplicate entry 'v' for key 'v_2'
|
||||
alter table t1 add key(v);
|
||||
select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
|
||||
qq
|
||||
@ -2377,6 +2377,8 @@ t1 CREATE TABLE `t1` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t1;
|
||||
create table t1 (v varchar(10), c char(10)) row_format=fixed;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
@ -3190,6 +3192,7 @@ t1 CREATE TABLE `t1` (
|
||||
CONSTRAINT `t1_t2` FOREIGN KEY (`id`) REFERENCES `t2` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=349 DEFAULT CHARSET=latin1
|
||||
DROP TABLE t1,t2;
|
||||
set innodb_strict_mode=on;
|
||||
CREATE TABLE t1 (
|
||||
c01 CHAR(255), c02 CHAR(255), c03 CHAR(255), c04 CHAR(255),
|
||||
c05 CHAR(255), c06 CHAR(255), c07 CHAR(255), c08 CHAR(255),
|
||||
|
@ -1,8 +1,4 @@
|
||||
SELECT f4, f8 FROM bug34300;
|
||||
f4 f8
|
||||
xxx zzz
|
||||
ALTER TABLE bug34300 ADD COLUMN (f10 INT);
|
||||
SELECT f4, f8 FROM bug34300;
|
||||
f4 f8
|
||||
xxx zzz
|
||||
DROP TABLE bug34300;
|
||||
|
5
mysql-test/r/innodb_bug36169.result
Normal file
5
mysql-test/r/innodb_bug36169.result
Normal file
@ -0,0 +1,5 @@
|
||||
SET @save_innodb_file_format=@@global.innodb_file_format;
|
||||
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
|
||||
SET @save_innodb_file_per_table=@@global.innodb_file_per_table;
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
1
mysql-test/r/innodb_bug36172.result
Normal file
1
mysql-test/r/innodb_bug36172.result
Normal file
@ -0,0 +1 @@
|
||||
SET storage_engine=InnoDB;
|
4
mysql-test/r/innodb_bug40360.result
Normal file
4
mysql-test/r/innodb_bug40360.result
Normal file
@ -0,0 +1,4 @@
|
||||
SET TX_ISOLATION='READ-COMMITTED';
|
||||
CREATE TABLE bug40360 (a INT) engine=innodb;
|
||||
INSERT INTO bug40360 VALUES (1);
|
||||
DROP TABLE bug40360;
|
4
mysql-test/r/innodb_bug41904.result
Normal file
4
mysql-test/r/innodb_bug41904.result
Normal file
@ -0,0 +1,4 @@
|
||||
CREATE TABLE bug41904 (id INT PRIMARY KEY, uniquecol CHAR(15)) ENGINE=InnoDB;
|
||||
INSERT INTO bug41904 VALUES (1,NULL), (2,NULL);
|
||||
CREATE UNIQUE INDEX ui ON bug41904 (uniquecol);
|
||||
DROP TABLE bug41904;
|
23
mysql-test/r/innodb_information_schema.result
Normal file
23
mysql-test/r/innodb_information_schema.result
Normal file
@ -0,0 +1,23 @@
|
||||
lock_mode lock_type lock_table lock_index lock_rec lock_data
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 2 '1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 2 '1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc'''''
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 3 '2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 3 '2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""'
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 4 '3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 4 '3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\'
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 5 '4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0'
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 5 '4', 'abc', '\0abc', 'abc\0', 'a\0bc', 'a\0bc\0', 'a\0bc\0\0'
|
||||
X RECORD `test`.`t_min` `PRIMARY` 2 -128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0
|
||||
X RECORD `test`.`t_min` `PRIMARY` 2 -128, 0, -32768, 0, -8388608, 0, -2147483648, 0, -9223372036854775808, 0
|
||||
X RECORD `test`.`t_max` `PRIMARY` 2 127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615
|
||||
X RECORD `test`.`t_max` `PRIMARY` 2 127, 255, 32767, 65535, 8388607, 16777215, 2147483647, 4294967295, 9223372036854775807, 18446744073709551615
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 1 supremum pseudo-record
|
||||
X RECORD `test`.```t'\"_str` `PRIMARY` 1 supremum pseudo-record
|
||||
lock_table COUNT(*)
|
||||
`test`.`t_max` 2
|
||||
`test`.`t_min` 2
|
||||
`test`.```t'\"_str` 10
|
||||
lock_table COUNT(*)
|
||||
"test"."t_max" 2
|
||||
"test"."t_min" 2
|
||||
"test"."`t'\""_str" 10
|
5
mysql-test/r/innodb_xtradb_bug317074.result
Normal file
5
mysql-test/r/innodb_xtradb_bug317074.result
Normal file
@ -0,0 +1,5 @@
|
||||
SET @save_innodb_file_format=@@global.innodb_file_format;
|
||||
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
|
||||
SET @save_innodb_file_per_table=@@global.innodb_file_per_table;
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
@ -1,4 +1,9 @@
|
||||
#
|
||||
# We need big packets.
|
||||
#
|
||||
SET @old_global_max_allowed_packet=@@global.max_allowed_packet;
|
||||
SET @@global.max_allowed_packet= 1024*1024*1024;
|
||||
#
|
||||
# Preparatory cleanup.
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
@ -7,10 +12,6 @@ DROP TABLE IF EXISTS t1;
|
||||
#
|
||||
SET timestamp=1000000000;
|
||||
#
|
||||
# We need big packets.
|
||||
#
|
||||
SET @@global.max_allowed_packet= 1024*1024*1024;
|
||||
#
|
||||
# Delete all existing binary logs.
|
||||
#
|
||||
RESET MASTER;
|
||||
@ -71,4 +72,5 @@ FLUSH LOGS;
|
||||
# Cleanup.
|
||||
#
|
||||
DROP TABLE t1;
|
||||
SET @@global.max_allowed_packet=@old_global_max_allowed_packet;
|
||||
remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_big_1.out
|
||||
|
@ -72,6 +72,8 @@ Table Checksum
|
||||
test.t1 4108368782
|
||||
drop table if exists t1;
|
||||
create table t1 (a int null, v varchar(100)) engine=innodb checksum=0 row_format=fixed;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
insert into t1 values(null, null), (1, "hello");
|
||||
checksum table t1;
|
||||
Table Checksum
|
||||
|
@ -72,6 +72,8 @@ Table Checksum
|
||||
test.t1 3885665021
|
||||
drop table if exists t1;
|
||||
create table t1 (a int null, v varchar(100)) engine=innodb checksum=0 row_format=fixed;
|
||||
Warnings:
|
||||
Warning 1478 InnoDB: assuming ROW_FORMAT=COMPACT.
|
||||
insert into t1 values(null, null), (1, "hello");
|
||||
checksum table t1;
|
||||
Table Checksum
|
||||
|
@ -1,20 +1,20 @@
|
||||
set session transaction_prealloc_size=1024*1024*1024*1;
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query 0 NULL show processlist
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
TRUE
|
||||
1
|
||||
set session transaction_prealloc_size=1024*1024*1024*2;
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query 0 NULL show processlist
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
TRUE
|
||||
1
|
||||
set session transaction_prealloc_size=1024*1024*1024*3;
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query 0 NULL show processlist
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
TRUE
|
||||
1
|
||||
set session transaction_prealloc_size=1024*1024*1024*4;
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query 0 NULL show processlist
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
TRUE
|
||||
1
|
||||
set session transaction_prealloc_size=1024*1024*1024*5;
|
||||
show processlist;
|
||||
Id User Host db Command Time State Info
|
||||
# root localhost test Query 0 NULL show processlist
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
TRUE
|
||||
1
|
||||
|
@ -47,7 +47,7 @@ create view v1 (c) as
|
||||
table_name<>'ndb_binlog_index' AND
|
||||
table_name<>'ndb_apply_status' AND
|
||||
NOT (table_schema = 'INFORMATION_SCHEMA' AND table_name LIKE 'PBXT_%');
|
||||
select * from v1;
|
||||
select * from v1 ORDER BY c COLLATE utf8_bin;
|
||||
|
||||
select c,table_name from v1
|
||||
inner join information_schema.TABLES v2 on (v1.c=v2.table_name)
|
||||
|
65
mysql-test/t/innodb-analyze.test
Normal file
65
mysql-test/t/innodb-analyze.test
Normal file
@ -0,0 +1,65 @@
|
||||
#
|
||||
# Test that mysqld does not crash when running ANALYZE TABLE with
|
||||
# different values of the parameter innodb_stats_sample_pages.
|
||||
#
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
# we care only that the following SQL commands do not produce errors
|
||||
# and do not crash the server
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
-- enable_warnings
|
||||
|
||||
SET @save_innodb_stats_sample_pages=@@innodb_stats_sample_pages;
|
||||
SET GLOBAL innodb_stats_sample_pages=0;
|
||||
|
||||
# check that the value has been adjusted to 1
|
||||
-- enable_result_log
|
||||
SHOW VARIABLES LIKE 'innodb_stats_sample_pages';
|
||||
-- disable_result_log
|
||||
|
||||
CREATE TABLE innodb_analyze (
|
||||
a INT,
|
||||
b INT,
|
||||
KEY(a),
|
||||
KEY(b,a)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
# test with empty table
|
||||
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=2;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=4;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=8;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=16;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
INSERT INTO innodb_analyze VALUES
|
||||
(1,1), (1,1), (1,2), (1,3), (1,4), (1,5),
|
||||
(8,1), (8,8), (8,2), (7,1), (1,4), (3,5);
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=1;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=2;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=4;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=8;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=16;
|
||||
ANALYZE TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=@save_innodb_stats_sample_pages;
|
||||
DROP TABLE innodb_analyze;
|
@ -396,7 +396,7 @@ DROP TABLE t1;
|
||||
#
|
||||
SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
|
||||
SET @@INSERT_ID=1;
|
||||
SHOW VARIABLES LIKE "%auto_inc%";
|
||||
SHOW VARIABLES LIKE "auto_inc%";
|
||||
CREATE TABLE t1 (c1 DOUBLE NOT NULL AUTO_INCREMENT, c2 INT, PRIMARY KEY (c1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES(NULL, 1);
|
||||
INSERT INTO t1 VALUES(NULL, 2);
|
||||
|
516
mysql-test/t/innodb-index.test
Normal file
516
mysql-test/t/innodb-index.test
Normal file
@ -0,0 +1,516 @@
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
|
||||
|
||||
create table t1(a int not null, b int, c char(10) not null, d varchar(20)) engine = innodb;
|
||||
insert into t1 values (5,5,'oo','oo'),(4,4,'tr','tr'),(3,4,'ad','ad'),(2,3,'ak','ak');
|
||||
commit;
|
||||
--error ER_DUP_KEYNAME
|
||||
alter table t1 add index b (b), add index b (b);
|
||||
--error ER_DUP_FIELDNAME
|
||||
alter table t1 add index (b,b);
|
||||
alter table t1 add index d2 (d);
|
||||
show create table t1;
|
||||
explain select * from t1 force index(d2) order by d;
|
||||
select * from t1 force index (d2) order by d;
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (b);
|
||||
show create table t1;
|
||||
alter table t1 add index (b);
|
||||
show create table t1;
|
||||
|
||||
# Check how existing tables interfere with temporary tables.
|
||||
CREATE TABLE `t1#1`(a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||
|
||||
call mtr.add_suppression(" table `test`\\.`t1#[12]` already exists in InnoDB internal");
|
||||
|
||||
--error 156
|
||||
alter table t1 add unique index (c), add index (d);
|
||||
rename table `t1#1` to `t1#2`;
|
||||
--error 156
|
||||
alter table t1 add unique index (c), add index (d);
|
||||
drop table `t1#2`;
|
||||
|
||||
alter table t1 add unique index (c), add index (d);
|
||||
show create table t1;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
alter table t1 add primary key (a), drop index c;
|
||||
show create table t1;
|
||||
--error ER_MULTIPLE_PRI_KEY
|
||||
alter table t1 add primary key (c);
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 drop primary key, add primary key (b);
|
||||
create unique index c on t1 (c);
|
||||
show create table t1;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
select * from t1 force index(c) order by c;
|
||||
alter table t1 drop index b, add index (b);
|
||||
show create table t1;
|
||||
insert into t1 values(6,1,'ggg','ggg');
|
||||
select * from t1;
|
||||
select * from t1 force index(b) order by b;
|
||||
select * from t1 force index(c) order by c;
|
||||
select * from t1 force index(d) order by d;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
explain select * from t1 force index(d) order by d;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb;
|
||||
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,3,'ad','ad'),(4,4,'afe','afe');
|
||||
commit;
|
||||
alter table t1 add index (c(2));
|
||||
show create table t1;
|
||||
alter table t1 add unique index (d(10));
|
||||
show create table t1;
|
||||
insert into t1 values(5,1,'ggg','ggg');
|
||||
select * from t1;
|
||||
select * from t1 force index(c) order by c;
|
||||
select * from t1 force index(d) order by d;
|
||||
explain select * from t1 order by b;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
explain select * from t1 force index(d) order by d;
|
||||
show create table t1;
|
||||
alter table t1 drop index d;
|
||||
insert into t1 values(8,9,'fff','fff');
|
||||
select * from t1;
|
||||
select * from t1 force index(c) order by c;
|
||||
explain select * from t1 order by b;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
explain select * from t1 order by d;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb;
|
||||
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,2,'ad','ad'),(4,4,'afe','afe');
|
||||
commit;
|
||||
alter table t1 add unique index (b,c);
|
||||
insert into t1 values(8,9,'fff','fff');
|
||||
select * from t1;
|
||||
select * from t1 force index(b) order by b;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
show create table t1;
|
||||
alter table t1 add index (b,c);
|
||||
insert into t1 values(11,11,'kkk','kkk');
|
||||
select * from t1;
|
||||
select * from t1 force index(b) order by b;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
show create table t1;
|
||||
alter table t1 add unique index (c,d);
|
||||
insert into t1 values(13,13,'yyy','aaa');
|
||||
select * from t1;
|
||||
select * from t1 force index(b) order by b;
|
||||
select * from t1 force index(c) order by c;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int not null, c int, primary key (a), key (b)) engine = innodb;
|
||||
create table t3(a int not null, c int not null, d int, primary key (a), key (c)) engine = innodb;
|
||||
create table t4(a int not null, d int not null, e int, primary key (a), key (d)) engine = innodb;
|
||||
create table t2(a int not null, b int not null, c int not null, d int not null, e int,
|
||||
foreign key (b) references t1(b) on delete cascade,
|
||||
foreign key (c) references t3(c), foreign key (d) references t4(d))
|
||||
engine = innodb;
|
||||
--error ER_DROP_INDEX_FK
|
||||
alter table t1 drop index b;
|
||||
--error ER_DROP_INDEX_FK
|
||||
alter table t3 drop index c;
|
||||
--error ER_DROP_INDEX_FK
|
||||
alter table t4 drop index d;
|
||||
--error ER_DROP_INDEX_FK
|
||||
alter table t2 drop index b;
|
||||
--error ER_DROP_INDEX_FK
|
||||
alter table t2 drop index b, drop index c, drop index d;
|
||||
# Apparently, the following makes mysql_alter_table() drop index d.
|
||||
create unique index dc on t2 (d,c);
|
||||
create index dc on t1 (b,c);
|
||||
# This should preserve the foreign key constraints.
|
||||
alter table t2 add primary key (a);
|
||||
insert into t1 values (1,1,1);
|
||||
insert into t3 values (1,1,1);
|
||||
insert into t4 values (1,1,1);
|
||||
insert into t2 values (1,1,1,1,1);
|
||||
commit;
|
||||
alter table t4 add constraint dc foreign key (a) references t1(a);
|
||||
show create table t4;
|
||||
--replace_regex /'test\.#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
# a foreign key 'test/dc' already exists
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
alter table t3 add constraint dc foreign key (a) references t1(a);
|
||||
show create table t3;
|
||||
alter table t2 drop index b, add index (b);
|
||||
show create table t2;
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
delete from t1;
|
||||
--error ER_CANT_DROP_FIELD_OR_KEY
|
||||
drop index dc on t4;
|
||||
# there is no foreign key dc on t3
|
||||
--replace_regex /'\.\/test\/#sql2-[0-9a-f-]*'/'#sql2-temporary'/
|
||||
--error ER_ERROR_ON_RENAME
|
||||
alter table t3 drop foreign key dc;
|
||||
alter table t4 drop foreign key dc;
|
||||
select * from t2;
|
||||
delete from t1;
|
||||
select * from t2;
|
||||
|
||||
drop table t2,t4,t3,t1;
|
||||
|
||||
-- let charset = utf8
|
||||
-- source include/innodb-index.inc
|
||||
|
||||
create table t1(a int not null, b int) engine = innodb;
|
||||
insert into t1 values (1,1),(1,1),(1,1),(1,1);
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (a);
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (b);
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (a), add unique index(b);
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, c int not null,b int, primary key(a), unique key(c), key(b)) engine = innodb;
|
||||
alter table t1 drop index c, drop index b;
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int, primary key(a)) engine = innodb;
|
||||
alter table t1 add index (b);
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int, c char(10), d varchar(20), primary key (a)) engine = innodb;
|
||||
insert into t1 values (1,1,'ab','ab'),(2,2,'ac','ac'),(3,3,'ac','ac'),(4,4,'afe','afe'),(5,4,'affe','affe');
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (b), add unique index (c), add unique index (d);
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique index (c), add unique index (b), add index (d);
|
||||
show create table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int not null, c int, primary key (a), key(c)) engine=innodb;
|
||||
insert into t1 values (5,1,5),(4,2,4),(3,3,3),(2,4,2),(1,5,1);
|
||||
alter table t1 add unique index (b);
|
||||
insert into t1 values (10,20,20),(11,19,19),(12,18,18),(13,17,17);
|
||||
show create table t1;
|
||||
check table t1;
|
||||
explain select * from t1 force index(c) order by c;
|
||||
explain select * from t1 order by a;
|
||||
explain select * from t1 force index(b) order by b;
|
||||
select * from t1 order by a;
|
||||
select * from t1 force index(b) order by b;
|
||||
select * from t1 force index(c) order by c;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b int not null) engine=innodb;
|
||||
insert into t1 values (1,1);
|
||||
alter table t1 add primary key(b);
|
||||
insert into t1 values (2,2);
|
||||
show create table t1;
|
||||
check table t1;
|
||||
select * from t1;
|
||||
explain select * from t1;
|
||||
explain select * from t1 order by a;
|
||||
explain select * from t1 order by b;
|
||||
checksum table t1;
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null) engine=innodb;
|
||||
insert into t1 values (1);
|
||||
alter table t1 add primary key(a);
|
||||
insert into t1 values (2);
|
||||
show create table t1;
|
||||
check table t1;
|
||||
commit;
|
||||
select * from t1;
|
||||
explain select * from t1;
|
||||
explain select * from t1 order by a;
|
||||
drop table t1;
|
||||
|
||||
create table t2(d varchar(17) primary key) engine=innodb default charset=utf8;
|
||||
create table t3(a int primary key) engine=innodb;
|
||||
|
||||
insert into t3 values(22),(44),(33),(55),(66);
|
||||
|
||||
insert into t2 values ('jejdkrun87'),('adfd72nh9k'),
|
||||
('adfdpplkeock'),('adfdijnmnb78k'),('adfdijn0loKNHJik');
|
||||
|
||||
create table t1(a int, b blob, c text, d text not null)
|
||||
engine=innodb default charset = utf8;
|
||||
|
||||
# r2667 The following test is disabled because MySQL behavior changed.
|
||||
# r2667 The test was added with this comment:
|
||||
# r2667
|
||||
# r2667 ------------------------------------------------------------------------
|
||||
# r2667 r1699 | marko | 2007-08-10 19:53:19 +0300 (Fri, 10 Aug 2007) | 5 lines
|
||||
# r2667
|
||||
# r2667 branches/zip: Add changes that accidentally omitted from r1698:
|
||||
# r2667
|
||||
# r2667 innodb-index.test, innodb-index.result: Add a test for creating
|
||||
# r2667 a PRIMARY KEY on a column that contains a NULL value.
|
||||
# r2667 ------------------------------------------------------------------------
|
||||
# r2667
|
||||
# r2667 but in BZR-r2667:
|
||||
# r2667 http://bazaar.launchpad.net/~mysql/mysql-server/mysql-5.1/revision/davi%40mysql.com-20080617141221-8yre8ys9j4uw3xx5?start_revid=joerg%40mysql.com-20080630105418-7qoe5ehomgrcdb89
|
||||
# r2667 MySQL changed the behavior to do full table copy when creating PRIMARY INDEX
|
||||
# r2667 on a non-NULL column instead of calling ::add_index() which would fail (and
|
||||
# r2667 this is what we were testing here). Before r2667 the code execution path was
|
||||
# r2667 like this (when adding PRIMARY INDEX on a non-NULL column with ALTER TABLE):
|
||||
# r2667
|
||||
# r2667 mysql_alter_table()
|
||||
# r2667 compare_tables() // would return ALTER_TABLE_INDEX_CHANGED
|
||||
# r2667 ::add_index() // would fail with "primary index cannot contain NULL"
|
||||
# r2667
|
||||
# r2667 after r2667 the code execution path is the following:
|
||||
# r2667
|
||||
# r2667 mysql_alter_table()
|
||||
# r2667 compare_tables() // returns ALTER_TABLE_DATA_CHANGED
|
||||
# r2667 full copy is done, without calling ::add_index()
|
||||
# r2667
|
||||
# r2667 To enable, remove "# r2667: " below.
|
||||
# r2667
|
||||
# r2667: insert into t1 values (null,null,null,'null');
|
||||
insert into t1
|
||||
select a,left(repeat(d,100*a),65535),repeat(d,20*a),d from t2,t3;
|
||||
drop table t2, t3;
|
||||
select count(*) from t1 where a=44;
|
||||
select a,
|
||||
length(b),b=left(repeat(d,100*a),65535),length(c),c=repeat(d,20*a),d from t1;
|
||||
# r2667: --error ER_PRIMARY_CANT_HAVE_NULL
|
||||
# r2667: alter table t1 add primary key (a), add key (b(20));
|
||||
# r2667: delete from t1 where d='null';
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add primary key (a), add key (b(20));
|
||||
delete from t1 where a%2;
|
||||
check table t1;
|
||||
alter table t1 add primary key (a,b(255),c(255)), add key (b(767));
|
||||
select count(*) from t1 where a=44;
|
||||
select a,
|
||||
length(b),b=left(repeat(d,100*a),65535),length(c),c=repeat(d,20*a),d from t1;
|
||||
show create table t1;
|
||||
check table t1;
|
||||
explain select * from t1 where b like 'adfd%';
|
||||
|
||||
#
|
||||
# Test locking
|
||||
#
|
||||
|
||||
create table t2(a int, b varchar(255), primary key(a,b)) engine=innodb;
|
||||
insert into t2 select a,left(b,255) from t1;
|
||||
drop table t1;
|
||||
rename table t2 to t1;
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
set innodb_lock_wait_timeout=1;
|
||||
begin;
|
||||
# Obtain an IX lock on the table
|
||||
select a from t1 limit 1 for update;
|
||||
connection b;
|
||||
set innodb_lock_wait_timeout=1;
|
||||
# This would require an S lock on the table, conflicting with the IX lock.
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
create index t1ba on t1 (b,a);
|
||||
connection a;
|
||||
commit;
|
||||
begin;
|
||||
# Obtain an IS lock on the table
|
||||
select a from t1 limit 1 lock in share mode;
|
||||
connection b;
|
||||
# This will require an S lock on the table. No conflict with the IS lock.
|
||||
create index t1ba on t1 (b,a);
|
||||
# This would require an X lock on the table, conflicting with the IS lock.
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
drop index t1ba on t1;
|
||||
connection a;
|
||||
commit;
|
||||
explain select a from t1 order by b;
|
||||
--send
|
||||
select a,sleep(2+a/100) from t1 order by b limit 3;
|
||||
|
||||
# The following DROP INDEX will succeed, altough the SELECT above has
|
||||
# opened a read view. However, during the execution of the SELECT,
|
||||
# MySQL should hold a table lock that should block the execution
|
||||
# of the DROP INDEX below.
|
||||
|
||||
connection b;
|
||||
select sleep(1);
|
||||
drop index t1ba on t1;
|
||||
|
||||
# After the index was dropped, subsequent SELECTs will use the same
|
||||
# read view, but they should not be accessing the dropped index any more.
|
||||
|
||||
connection a;
|
||||
reap;
|
||||
explain select a from t1 order by b;
|
||||
select a from t1 order by b limit 3;
|
||||
commit;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
drop table t1;
|
||||
|
||||
let $per_table=`select @@innodb_file_per_table`;
|
||||
let $format=`select @@innodb_file_format`;
|
||||
set global innodb_file_per_table=on;
|
||||
set global innodb_file_format='Barracuda';
|
||||
# Test creating a table that could lead to undo log overflow.
|
||||
# In the undo log, we write a 768-byte prefix (REC_MAX_INDEX_COL_LEN)
|
||||
# of each externally stored column that appears as a column prefix in an index.
|
||||
# For this test case, it would suffice to write 1 byte, though.
|
||||
create table t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob,h blob,
|
||||
i blob,j blob,k blob,l blob,m blob,n blob,o blob,p blob,
|
||||
q blob,r blob,s blob,t blob,u blob)
|
||||
engine=innodb row_format=dynamic;
|
||||
create index t1a on t1 (a(1));
|
||||
create index t1b on t1 (b(1));
|
||||
create index t1c on t1 (c(1));
|
||||
create index t1d on t1 (d(1));
|
||||
create index t1e on t1 (e(1));
|
||||
create index t1f on t1 (f(1));
|
||||
create index t1g on t1 (g(1));
|
||||
create index t1h on t1 (h(1));
|
||||
create index t1i on t1 (i(1));
|
||||
create index t1j on t1 (j(1));
|
||||
create index t1k on t1 (k(1));
|
||||
create index t1l on t1 (l(1));
|
||||
create index t1m on t1 (m(1));
|
||||
create index t1n on t1 (n(1));
|
||||
create index t1o on t1 (o(1));
|
||||
create index t1p on t1 (p(1));
|
||||
create index t1q on t1 (q(1));
|
||||
create index t1r on t1 (r(1));
|
||||
create index t1s on t1 (s(1));
|
||||
create index t1t on t1 (t(1));
|
||||
--error 139
|
||||
create index t1u on t1 (u(1));
|
||||
--error 139
|
||||
create index t1ut on t1 (u(1), t(1));
|
||||
create index t1st on t1 (s(1), t(1));
|
||||
show create table t1;
|
||||
--error 139
|
||||
create index t1u on t1 (u(1));
|
||||
alter table t1 row_format=compact;
|
||||
create index t1u on t1 (u(1));
|
||||
|
||||
drop table t1;
|
||||
eval set global innodb_file_per_table=$per_table;
|
||||
eval set global innodb_file_format=$format;
|
||||
|
||||
#
|
||||
# Test to check whether CREATE INDEX handles implicit foreign key
|
||||
# constraint modifications (Issue #70, Bug #38786)
|
||||
#
|
||||
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
|
||||
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
|
||||
|
||||
CREATE TABLE t1(
|
||||
c1 BIGINT(12) NOT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE t2(
|
||||
c1 BIGINT(16) NOT NULL,
|
||||
c2 BIGINT(12) NOT NULL,
|
||||
c3 BIGINT(12) NOT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3) REFERENCES t1(c1);
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
||||
|
||||
SHOW CREATE TABLE t2;
|
||||
|
||||
CREATE INDEX i_t2_c3_c2 ON t2(c3, c2);
|
||||
|
||||
SHOW CREATE TABLE t2;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
|
||||
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
|
||||
|
||||
--error ER_NO_REFERENCED_ROW_2
|
||||
INSERT INTO t2 VALUES(0,0,0);
|
||||
INSERT INTO t1 VALUES(0);
|
||||
INSERT INTO t2 VALUES(0,0,0);
|
||||
|
||||
DROP TABLE t2;
|
||||
|
||||
CREATE TABLE t2(
|
||||
c1 BIGINT(16) NOT NULL,
|
||||
c2 BIGINT(12) NOT NULL,
|
||||
c3 BIGINT(12) NOT NULL,
|
||||
PRIMARY KEY (c1,c2,c3)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3) REFERENCES t1(c1);
|
||||
|
||||
SHOW CREATE TABLE t2;
|
||||
|
||||
CREATE INDEX i_t2_c3_c2 ON t2(c3, c2);
|
||||
|
||||
SHOW CREATE TABLE t2;
|
||||
--error ER_NO_REFERENCED_ROW_2
|
||||
INSERT INTO t2 VALUES(0,0,1);
|
||||
INSERT INTO t2 VALUES(0,0,0);
|
||||
--error ER_ROW_IS_REFERENCED_2
|
||||
DELETE FROM t1;
|
||||
DELETE FROM t2;
|
||||
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
|
||||
CREATE TABLE t1(
|
||||
c1 BIGINT(12) NOT NULL,
|
||||
c2 INT(4) NOT NULL,
|
||||
PRIMARY KEY (c2,c1)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
CREATE TABLE t2(
|
||||
c1 BIGINT(16) NOT NULL,
|
||||
c2 BIGINT(12) NOT NULL,
|
||||
c3 BIGINT(12) NOT NULL,
|
||||
PRIMARY KEY (c1)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
|
||||
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3,c2) REFERENCES t1(c1,c1);
|
||||
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3,c2) REFERENCES t1(c1,c2);
|
||||
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3,c2) REFERENCES t1(c2,c1);
|
||||
ALTER TABLE t1 MODIFY COLUMN c2 BIGINT(12) NOT NULL;
|
||||
--replace_regex /'test\.#sql-[0-9_a-f-]*'/'#sql-temporary'/
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3,c2) REFERENCES t1(c1,c2);
|
||||
|
||||
ALTER TABLE t2 ADD CONSTRAINT fk_t2_ca
|
||||
FOREIGN KEY (c3,c2) REFERENCES t1(c2,c1);
|
||||
SHOW CREATE TABLE t1;
|
||||
SHOW CREATE TABLE t2;
|
||||
CREATE INDEX i_t2_c2_c1 ON t2(c2, c1);
|
||||
SHOW CREATE TABLE t2;
|
||||
CREATE INDEX i_t2_c3_c1_c2 ON t2(c3, c1, c2);
|
||||
SHOW CREATE TABLE t2;
|
||||
CREATE INDEX i_t2_c3_c2 ON t2(c3, c2);
|
||||
SHOW CREATE TABLE t2;
|
||||
|
||||
DROP TABLE t2;
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL innodb_file_format_check=@save_innodb_file_format_check;
|
5
mysql-test/t/innodb-index_ucs2.test
Normal file
5
mysql-test/t/innodb-index_ucs2.test
Normal file
@ -0,0 +1,5 @@
|
||||
-- source include/have_innodb.inc
|
||||
-- source include/have_ucs2.inc
|
||||
|
||||
-- let charset = ucs2
|
||||
-- source include/innodb-index.inc
|
64
mysql-test/t/innodb-timeout.test
Normal file
64
mysql-test/t/innodb-timeout.test
Normal file
@ -0,0 +1,64 @@
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
let $timeout=`select @@innodb_lock_wait_timeout`;
|
||||
set global innodb_lock_wait_timeout=42;
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
|
||||
connection a;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
set innodb_lock_wait_timeout=1;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
|
||||
connection b;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
set global innodb_lock_wait_timeout=347;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
set innodb_lock_wait_timeout=1;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
|
||||
connect (c,localhost,root,,);
|
||||
connection c;
|
||||
select @@innodb_lock_wait_timeout;
|
||||
connection default;
|
||||
disconnect c;
|
||||
|
||||
connection a;
|
||||
create table t1(a int primary key)engine=innodb;
|
||||
begin;
|
||||
insert into t1 values(1),(2),(3);
|
||||
|
||||
connection b;
|
||||
--send
|
||||
select * from t1 for update;
|
||||
|
||||
connection a;
|
||||
commit;
|
||||
|
||||
connection b;
|
||||
reap;
|
||||
|
||||
connection a;
|
||||
begin;
|
||||
insert into t1 values(4);
|
||||
|
||||
connection b;
|
||||
--send
|
||||
select * from t1 for update;
|
||||
|
||||
connection a;
|
||||
sleep 2;
|
||||
commit;
|
||||
|
||||
connection b;
|
||||
--error ER_LOCK_WAIT_TIMEOUT
|
||||
reap;
|
||||
drop table t1;
|
||||
|
||||
connection default;
|
||||
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
eval set global innodb_lock_wait_timeout=$timeout;
|
2
mysql-test/t/innodb-use-sys-malloc-master.opt
Normal file
2
mysql-test/t/innodb-use-sys-malloc-master.opt
Normal file
@ -0,0 +1,2 @@
|
||||
--innodb-use-sys-malloc=true
|
||||
--innodb-use-sys-malloc=true
|
48
mysql-test/t/innodb-use-sys-malloc.test
Normal file
48
mysql-test/t/innodb-use-sys-malloc.test
Normal file
@ -0,0 +1,48 @@
|
||||
--source include/have_innodb.inc
|
||||
|
||||
#display current value of innodb_use_sys_malloc
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
--echo 1 Expected
|
||||
|
||||
#try changing it. Should fail.
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
SET @@GLOBAL.innodb_use_sys_malloc=0;
|
||||
--echo Expected error 'Read only variable'
|
||||
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
--echo 1 Expected
|
||||
|
||||
|
||||
#do some stuff to see if it works.
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
--source include/have_innodb.inc
|
||||
|
||||
#display current value of innodb_use_sys_malloc
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
--echo 1 Expected
|
||||
|
||||
#try changing it. Should fail.
|
||||
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||
SET @@GLOBAL.innodb_use_sys_malloc=0;
|
||||
--echo Expected error 'Read only variable'
|
||||
|
||||
SELECT @@GLOBAL.innodb_use_sys_malloc;
|
||||
--echo 1 Expected
|
||||
|
||||
|
||||
#do some stuff to see if it works.
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
|
||||
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
|
||||
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
|
||||
select * from t1;
|
||||
drop table t1;
|
347
mysql-test/t/innodb-zip.test
Normal file
347
mysql-test/t/innodb-zip.test
Normal file
@ -0,0 +1,347 @@
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
let $per_table=`select @@innodb_file_per_table`;
|
||||
let $format=`select @@innodb_file_format`;
|
||||
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
|
||||
set global innodb_file_per_table=off;
|
||||
set global innodb_file_format=`0`;
|
||||
|
||||
create table t0(a int primary key) engine=innodb row_format=compressed;
|
||||
create table t00(a int primary key) engine=innodb
|
||||
key_block_size=4 row_format=compressed;
|
||||
create table t1(a int primary key) engine=innodb row_format=dynamic;
|
||||
create table t2(a int primary key) engine=innodb row_format=redundant;
|
||||
create table t3(a int primary key) engine=innodb row_format=compact;
|
||||
create table t4(a int primary key) engine=innodb key_block_size=9;
|
||||
create table t5(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=redundant;
|
||||
|
||||
set global innodb_file_per_table=on;
|
||||
create table t6(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=redundant;
|
||||
set global innodb_file_format=`1`;
|
||||
create table t7(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=redundant;
|
||||
create table t8(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=fixed;
|
||||
create table t9(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=compact;
|
||||
create table t10(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=dynamic;
|
||||
create table t11(a int primary key) engine=innodb
|
||||
key_block_size=1 row_format=compressed;
|
||||
create table t12(a int primary key) engine=innodb
|
||||
key_block_size=1;
|
||||
create table t13(a int primary key) engine=innodb
|
||||
row_format=compressed;
|
||||
create table t14(a int primary key) engine=innodb key_block_size=9;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
|
||||
drop table t0,t00,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14;
|
||||
alter table t1 key_block_size=0;
|
||||
alter table t1 row_format=dynamic;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
alter table t1 row_format=compact;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
alter table t1 row_format=redundant;
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
drop table t1;
|
||||
|
||||
create table t1(a int not null, b text, index(b(10))) engine=innodb
|
||||
key_block_size=1;
|
||||
|
||||
create table t2(b text)engine=innodb;
|
||||
insert into t2 values(concat('1abcdefghijklmnopqrstuvwxyz', repeat('A',5000)));
|
||||
|
||||
insert into t1 select 1, b from t2;
|
||||
commit;
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
|
||||
connection a;
|
||||
begin;
|
||||
update t1 set b=repeat('B',100);
|
||||
|
||||
connection b;
|
||||
select a,left(b,40) from t1 natural join t2;
|
||||
|
||||
connection a;
|
||||
rollback;
|
||||
|
||||
connection b;
|
||||
select a,left(b,40) from t1 natural join t2;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
drop table t1,t2;
|
||||
|
||||
# The following should fail even in non-strict mode.
|
||||
SET SESSION innodb_strict_mode = off;
|
||||
--error ER_TOO_BIG_ROWSIZE
|
||||
CREATE TABLE t1(
|
||||
c TEXT NOT NULL, d TEXT NOT NULL,
|
||||
PRIMARY KEY (c(767),d(767)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
--error ER_TOO_BIG_ROWSIZE
|
||||
CREATE TABLE t1(
|
||||
c TEXT NOT NULL, d TEXT NOT NULL,
|
||||
PRIMARY KEY (c(767),d(767)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2 CHARSET=ASCII;
|
||||
CREATE TABLE t1(
|
||||
c TEXT NOT NULL, d TEXT NOT NULL,
|
||||
PRIMARY KEY (c(767),d(767)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 CHARSET=ASCII;
|
||||
drop table t1;
|
||||
--error ER_TOO_BIG_ROWSIZE
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(440)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
# The maximum key size for a compressed row actually depends on the
|
||||
# version of libz used, as account must be taken for the maximum
|
||||
# compressed size of a key, and this differs between libz
|
||||
# versions. Some libz versions allow a size of 439, some only 438.
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(438)))
|
||||
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
|
||||
INSERT INTO t1 VALUES(REPEAT('A',512)),(REPEAT('B',512));
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# Test blob column inheritance (mantis issue#36)
|
||||
#
|
||||
|
||||
create table t1( c1 int not null, c2 blob, c3 blob, c4 blob,
|
||||
primary key(c1, c2(22), c3(22)))
|
||||
engine = innodb row_format = dynamic;
|
||||
begin;
|
||||
insert into t1 values(1, repeat('A', 20000), repeat('B', 20000),
|
||||
repeat('C', 20000));
|
||||
|
||||
update t1 set c3 = repeat('D', 20000) where c1 = 1;
|
||||
commit;
|
||||
|
||||
# one blob column which is unchanged in update and part of PK
|
||||
# one blob column which is changed and part of of PK
|
||||
# one blob column which is not part of PK and is unchanged
|
||||
select count(*) from t1 where c2 = repeat('A', 20000);
|
||||
select count(*) from t1 where c3 = repeat('D', 20000);
|
||||
select count(*) from t1 where c4 = repeat('C', 20000);
|
||||
|
||||
update t1 set c3 = repeat('E', 20000) where c1 = 1;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
#
|
||||
# Test innodb_file_format
|
||||
#
|
||||
set global innodb_file_format=`0`;
|
||||
select @@innodb_file_format;
|
||||
set global innodb_file_format=`1`;
|
||||
select @@innodb_file_format;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=`2`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=`-1`;
|
||||
set global innodb_file_format=`Antelope`;
|
||||
set global innodb_file_format=`Barracuda`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=`Cheetah`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=`abc`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=`1a`;
|
||||
-- error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=``;
|
||||
|
||||
#test strict mode.
|
||||
# this does not work anymore, has been removed from mysqltest
|
||||
# -- enable_errors
|
||||
set global innodb_file_per_table = on;
|
||||
set global innodb_file_format = `1`;
|
||||
|
||||
set innodb_strict_mode = off;
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 0;
|
||||
drop table t1;
|
||||
|
||||
#set strict_mode
|
||||
set innodb_strict_mode = on;
|
||||
|
||||
#Test different values of KEY_BLOCK_SIZE
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 0;
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t2 (id int primary key) engine = innodb key_block_size = 9;
|
||||
show errors;
|
||||
|
||||
|
||||
create table t3 (id int primary key) engine = innodb key_block_size = 1;
|
||||
create table t4 (id int primary key) engine = innodb key_block_size = 2;
|
||||
create table t5 (id int primary key) engine = innodb key_block_size = 4;
|
||||
create table t6 (id int primary key) engine = innodb key_block_size = 8;
|
||||
create table t7 (id int primary key) engine = innodb key_block_size = 16;
|
||||
|
||||
#check various ROW_FORMAT values.
|
||||
create table t8 (id int primary key) engine = innodb row_format = compressed;
|
||||
create table t9 (id int primary key) engine = innodb row_format = dynamic;
|
||||
create table t10(id int primary key) engine = innodb row_format = compact;
|
||||
create table t11(id int primary key) engine = innodb row_format = redundant;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
drop table t3, t4, t5, t6, t7, t8, t9, t10, t11;
|
||||
|
||||
#test different values of ROW_FORMAT with KEY_BLOCK_SIZE
|
||||
create table t1 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = compressed;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t2 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = redundant;
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t3 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = compact;
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t4 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = dynamic;
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t5 (id int primary key) engine = innodb
|
||||
key_block_size = 8 row_format = default;
|
||||
show errors;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
drop table t1;
|
||||
|
||||
#test multiple errors
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t1 (id int primary key) engine = innodb
|
||||
key_block_size = 9 row_format = redundant;
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t2 (id int primary key) engine = innodb
|
||||
key_block_size = 9 row_format = compact;
|
||||
show errors;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t2 (id int primary key) engine = innodb
|
||||
key_block_size = 9 row_format = dynamic;
|
||||
show errors;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
|
||||
#test valid values with innodb_file_per_table unset
|
||||
set global innodb_file_per_table = off;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 1;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t2 (id int primary key) engine = innodb key_block_size = 2;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t3 (id int primary key) engine = innodb key_block_size = 4;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t4 (id int primary key) engine = innodb key_block_size = 8;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t5 (id int primary key) engine = innodb key_block_size = 16;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t6 (id int primary key) engine = innodb row_format = compressed;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t7 (id int primary key) engine = innodb row_format = dynamic;
|
||||
show errors;
|
||||
create table t8 (id int primary key) engine = innodb row_format = compact;
|
||||
create table t9 (id int primary key) engine = innodb row_format = redundant;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
drop table t8, t9;
|
||||
|
||||
#test valid values with innodb_file_format unset
|
||||
set global innodb_file_per_table = on;
|
||||
set global innodb_file_format = `0`;
|
||||
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t1 (id int primary key) engine = innodb key_block_size = 1;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t2 (id int primary key) engine = innodb key_block_size = 2;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t3 (id int primary key) engine = innodb key_block_size = 4;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t4 (id int primary key) engine = innodb key_block_size = 8;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t5 (id int primary key) engine = innodb key_block_size = 16;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t6 (id int primary key) engine = innodb row_format = compressed;
|
||||
show errors;
|
||||
--error ER_CANT_CREATE_TABLE
|
||||
create table t7 (id int primary key) engine = innodb row_format = dynamic;
|
||||
show errors;
|
||||
create table t8 (id int primary key) engine = innodb row_format = compact;
|
||||
create table t9 (id int primary key) engine = innodb row_format = redundant;
|
||||
|
||||
SELECT table_schema, table_name, row_format
|
||||
FROM information_schema.tables WHERE engine='innodb';
|
||||
drop table t8, t9;
|
||||
|
||||
eval set global innodb_file_per_table=$per_table;
|
||||
eval set global innodb_file_format=$format;
|
||||
#
|
||||
# Testing of tablespace tagging
|
||||
#
|
||||
-- disable_info
|
||||
set global innodb_file_per_table=on;
|
||||
set global innodb_file_format=`Barracuda`;
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
create table normal_table (
|
||||
c1 int
|
||||
) engine = innodb;
|
||||
select @@innodb_file_format_check;
|
||||
create table zip_table (
|
||||
c1 int
|
||||
) engine = innodb key_block_size = 8;
|
||||
select @@innodb_file_format_check;
|
||||
set global innodb_file_format_check=`Antelope`;
|
||||
select @@innodb_file_format_check;
|
||||
-- disable_result_log
|
||||
show table status;
|
||||
-- enable_result_log
|
||||
select @@innodb_file_format_check;
|
||||
drop table normal_table, zip_table;
|
||||
-- disable_result_log
|
||||
|
||||
#
|
||||
# restore environment to the state it was before this test execution
|
||||
#
|
||||
|
||||
-- disable_query_log
|
||||
eval set global innodb_file_format=$format;
|
||||
eval set global innodb_file_per_table=$per_table;
|
||||
eval set global innodb_file_format_check=$innodb_file_format_check_orig;
|
@ -1126,7 +1126,7 @@ show create table t2;
|
||||
create index id2 on t2 (id);
|
||||
show create table t2;
|
||||
drop index id2 on t2;
|
||||
--error 1025,1025
|
||||
--error ER_DROP_INDEX_FK
|
||||
drop index id on t2;
|
||||
show create table t2;
|
||||
drop table t2;
|
||||
@ -1294,6 +1294,7 @@ drop table t1;
|
||||
|
||||
# Test for testable InnoDB status variables. This test
|
||||
# uses previous ones(pages_created, rows_deleted, ...).
|
||||
--replace_result 512 511
|
||||
show status like "Innodb_buffer_pool_pages_total";
|
||||
show status like "Innodb_page_size";
|
||||
show status like "Innodb_rows_deleted";
|
||||
@ -2357,6 +2358,7 @@ DROP TABLE t1,t2;
|
||||
#
|
||||
# Bug #21101 (Prints wrong error message if max row size is too large)
|
||||
#
|
||||
set innodb_strict_mode=on;
|
||||
--error 1118
|
||||
CREATE TABLE t1 (
|
||||
c01 CHAR(255), c02 CHAR(255), c03 CHAR(255), c04 CHAR(255),
|
||||
|
@ -9,6 +9,7 @@
|
||||
-- disable_result_log
|
||||
|
||||
# set packet size and reconnect
|
||||
SET @save_max_allowed_packet=@@global.max_allowed_packet;
|
||||
SET @@global.max_allowed_packet=16777216;
|
||||
--connect (newconn, localhost, root,,)
|
||||
|
||||
@ -21,7 +22,6 @@ CREATE TABLE bug34300 (
|
||||
|
||||
INSERT INTO bug34300 VALUES ('xxx', repeat('a', 8459264), 'zzz');
|
||||
|
||||
-- enable_query_log
|
||||
-- enable_result_log
|
||||
|
||||
SELECT f4, f8 FROM bug34300;
|
||||
@ -31,11 +31,6 @@ ALTER TABLE bug34300 ADD COLUMN (f10 INT);
|
||||
SELECT f4, f8 FROM bug34300;
|
||||
|
||||
DROP TABLE bug34300;
|
||||
|
||||
disconnect newconn;
|
||||
connection default;
|
||||
--disable_result_log
|
||||
--disable_query_log
|
||||
SET @@global.max_allowed_packet=default;
|
||||
--enable_result_log
|
||||
--enable_query_log
|
||||
SET @@global.max_allowed_packet=@save_max_allowed_packet;
|
||||
|
1162
mysql-test/t/innodb_bug36169.test
Normal file
1162
mysql-test/t/innodb_bug36169.test
Normal file
File diff suppressed because it is too large
Load Diff
33
mysql-test/t/innodb_bug36172.test
Normal file
33
mysql-test/t/innodb_bug36172.test
Normal file
@ -0,0 +1,33 @@
|
||||
#
|
||||
# Test case for bug 36172
|
||||
#
|
||||
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET storage_engine=InnoDB;
|
||||
|
||||
# we do not really care about what gets printed, we are only
|
||||
# interested in getting success or failure according to our
|
||||
# expectations
|
||||
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
SET @save_innodb_file_format=@@global.innodb_file_format;
|
||||
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
|
||||
SET @save_innodb_file_per_table=@@global.innodb_file_per_table;
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=on;
|
||||
|
||||
DROP TABLE IF EXISTS `table0`;
|
||||
CREATE TABLE `table0` ( `col0` tinyint(1) DEFAULT NULL, `col1` tinyint(1) DEFAULT NULL, `col2` tinyint(4) DEFAULT NULL, `col3` date DEFAULT NULL, `col4` time DEFAULT NULL, `col5` set('test1','test2','test3') DEFAULT NULL, `col6` time DEFAULT NULL, `col7` text, `col8` decimal(10,0) DEFAULT NULL, `col9` set('test1','test2','test3') DEFAULT NULL, `col10` float DEFAULT NULL, `col11` double DEFAULT NULL, `col12` enum('test1','test2','test3') DEFAULT NULL, `col13` tinyblob, `col14` year(4) DEFAULT NULL, `col15` set('test1','test2','test3') DEFAULT NULL, `col16` decimal(10,0) DEFAULT NULL, `col17` decimal(10,0) DEFAULT NULL, `col18` blob, `col19` datetime DEFAULT NULL, `col20` double DEFAULT NULL, `col21` decimal(10,0) DEFAULT NULL, `col22` datetime DEFAULT NULL, `col23` decimal(10,0) DEFAULT NULL, `col24` decimal(10,0) DEFAULT NULL, `col25` longtext, `col26` tinyblob, `col27` time DEFAULT NULL, `col28` tinyblob, `col29` enum('test1','test2','test3') DEFAULT NULL, `col30` smallint(6) DEFAULT NULL, `col31` double DEFAULT NULL, `col32` float DEFAULT NULL, `col33` char(175) DEFAULT NULL, `col34` tinytext, `col35` tinytext, `col36` tinyblob, `col37` tinyblob, `col38` tinytext, `col39` mediumblob, `col40` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `col41` double DEFAULT NULL, `col42` smallint(6) DEFAULT NULL, `col43` longblob, `col44` varchar(80) DEFAULT NULL, `col45` mediumtext, `col46` decimal(10,0) DEFAULT NULL, `col47` bigint(20) DEFAULT NULL, `col48` date DEFAULT NULL, `col49` tinyblob, `col50` date DEFAULT NULL, `col51` tinyint(1) DEFAULT NULL, `col52` mediumint(9) DEFAULT NULL, `col53` float DEFAULT NULL, `col54` tinyblob, `col55` longtext, `col56` smallint(6) DEFAULT NULL, `col57` enum('test1','test2','test3') DEFAULT NULL, `col58` datetime DEFAULT NULL, `col59` mediumtext, `col60` varchar(232) DEFAULT NULL, `col61` decimal(10,0) DEFAULT NULL, `col62` year(4) DEFAULT NULL, `col63` smallint(6) DEFAULT NULL, `col64` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `col65` blob, `col66` longblob, `col67` int(11) DEFAULT NULL, `col68` longtext, `col69` enum('test1','test2','test3') DEFAULT NULL, `col70` int(11) DEFAULT NULL, `col71` time DEFAULT NULL, `col72` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `col73` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `col74` varchar(170) DEFAULT NULL, `col75` set('test1','test2','test3') DEFAULT NULL, `col76` tinyblob, `col77` bigint(20) DEFAULT NULL, `col78` decimal(10,0) DEFAULT NULL, `col79` datetime DEFAULT NULL, `col80` year(4) DEFAULT NULL, `col81` decimal(10,0) DEFAULT NULL, `col82` longblob, `col83` text, `col84` char(83) DEFAULT NULL, `col85` decimal(10,0) DEFAULT NULL, `col86` float DEFAULT NULL, `col87` int(11) DEFAULT NULL, `col88` varchar(145) DEFAULT NULL, `col89` date DEFAULT NULL, `col90` decimal(10,0) DEFAULT NULL, `col91` decimal(10,0) DEFAULT NULL, `col92` mediumblob, `col93` time DEFAULT NULL, KEY `idx0` (`col69`,`col90`,`col8`), KEY `idx1` (`col60`), KEY `idx2` (`col60`,`col70`,`col74`), KEY `idx3` (`col22`,`col32`,`col72`,`col30`), KEY `idx4` (`col29`), KEY `idx5` (`col19`,`col45`(143)), KEY `idx6` (`col46`,`col48`,`col5`,`col39`(118)), KEY `idx7` (`col48`,`col61`), KEY `idx8` (`col93`), KEY `idx9` (`col31`), KEY `idx10` (`col30`,`col21`), KEY `idx11` (`col67`), KEY `idx12` (`col44`,`col6`,`col8`,`col38`(226)), KEY `idx13` (`col71`,`col41`,`col15`,`col49`(88)), KEY `idx14` (`col78`), KEY `idx15` (`col63`,`col67`,`col64`), KEY `idx16` (`col17`,`col86`), KEY `idx17` (`col77`,`col56`,`col10`,`col55`(24)), KEY `idx18` (`col62`), KEY `idx19` (`col31`,`col57`,`col56`,`col53`), KEY `idx20` (`col46`), KEY `idx21` (`col83`(54)), KEY `idx22` (`col51`,`col7`(120)), KEY `idx23` (`col7`(163),`col31`,`col71`,`col14`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=2;
|
||||
insert ignore into `table0` set `col23` = 7887371.5084383683, `col24` = 4293854615.6906948000, `col25` = 'vitalist', `col26` = 'widespread', `col27` = '3570490', `col28` = 'habitual', `col30` = -5471, `col31` = 4286985783.6771750000, `col32` = 6354540.9826654866, `col33` = 'defoliation', `col34` = 'logarithms', `col35` = 'tegument\'s', `col36` = 'scouting\'s', `col37` = 'intermittency', `col38` = 'elongates', `col39` = 'prophecies', `col40` = '20560103035939', `col41` = 4292809130.0544143000, `col42` = 22057, `col43` = 'Hess\'s', `col44` = 'bandstand', `col45` = 'phenylketonuria', `col46` = 6338767.4018677324, `col47` = 5310247, `col48` = '12592418', `col49` = 'churchman\'s', `col50` = '32226125', `col51` = -58, `col52` = -6207968, `col53` = 1244839.3255104220, `col54` = 'robotized', `col55` = 'monotonous', `col56` = -26909, `col58` = '20720107023550', `col59` = 'suggestiveness\'s', `col60` = 'gemology', `col61` = 4287800670.2229986000, `col62` = '1944', `col63` = -16827, `col64` = '20700107212324', `col65` = 'Nicolais', `col66` = 'apteryx', `col67` = 6935317, `col68` = 'stroganoff', `col70` = 3316430, `col71` = '3277608', `col72` = '19300511045918', `col73` = '20421201003327', `col74` = 'attenuant', `col75` = '15173', `col76` = 'upstroke\'s', `col77` = 8118987, `col78` = 6791516.2735374002, `col79` = '20780701144624', `col80` = '2134', `col81` = 4290682351.3127537000, `col82` = 'unexplainably', `col83` = 'Storm', `col84` = 'Greyso\'s', `col85` = 4289119212.4306774000, `col86` = 7617575.8796655172, `col87` = -6325335, `col88` = 'fondue\'s', `col89` = '40608940', `col90` = 1659421.8093508712, `col91` = 8346904.6584368423, `col92` = 'reloads', `col93` = '5188366';
|
||||
CHECK TABLE table0 EXTENDED;
|
||||
INSERT IGNORE INTO `table0` SET `col19` = '19940127002709', `col20` = 2383927.9055146948, `col21` = 4293243420.5621204000, `col22` = '20511211123705', `col23` = 4289899778.6573381000, `col24` = 4293449279.0540481000, `col25` = 'emphysemic', `col26` = 'dentally', `col27` = '2347406', `col28` = 'eruct', `col30` = 1222, `col31` = 4294372994.9941406000, `col32` = 4291385574.1173744000, `col33` = 'borrowing\'s', `col34` = 'septics', `col35` = 'ratter\'s', `col36` = 'Kaye', `col37` = 'Florentia', `col38` = 'allium', `col39` = 'barkeep', `col40` = '19510407003441', `col41` = 4293559200.4215522000, `col42` = 22482, `col43` = 'decussate', `col44` = 'Brom\'s', `col45` = 'violated', `col46` = 4925506.4635456400, `col47` = 930549, `col48` = '51296066', `col49` = 'voluminously', `col50` = '29306676', `col51` = -88, `col52` = -2153690, `col53` = 4290250202.1464887000, `col54` = 'expropriation', `col55` = 'Aberdeen\'s', `col56` = 20343, `col58` = '19640415171532', `col59` = 'extern', `col60` = 'Ubana', `col61` = 4290487961.8539081000, `col62` = '2147', `col63` = -24271, `col64` = '20750801194548', `col65` = 'Cunaxa\'s', `col66` = 'pasticcio', `col67` = 2795817, `col68` = 'Indore\'s', `col70` = 6864127, `col71` = '1817832', `col72` = '20540506114211', `col73` = '20040101012300', `col74` = 'rationalized', `col75` = '45522', `col76` = 'indene', `col77` = -6964559, `col78` = 4247535.5266884370, `col79` = '20720416124357', `col80` = '2143', `col81` = 4292060102.4466386000, `col82` = 'striving', `col83` = 'boneblack\'s', `col84` = 'redolent', `col85` = 6489697.9009369183, `col86` = 4287473465.9731131000, `col87` = 7726015, `col88` = 'perplexed', `col89` = '17153791', `col90` = 5478587.1108127078, `col91` = 4287091404.7004304000, `col92` = 'Boulez\'s', `col93` = '2931278';
|
||||
CHECK TABLE table0 EXTENDED;
|
||||
|
||||
SET GLOBAL innodb_file_format=@save_innodb_file_format;
|
||||
SET GLOBAL innodb_file_format_check=@save_innodb_file_format_check;
|
||||
SET GLOBAL innodb_file_per_table=@save_innodb_file_per_table;
|
||||
DROP TABLE table0;
|
16
mysql-test/t/innodb_bug40360.test
Normal file
16
mysql-test/t/innodb_bug40360.test
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# Make sure http://bugs.mysql.com/40360 remains fixed.
|
||||
#
|
||||
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET TX_ISOLATION='READ-COMMITTED';
|
||||
|
||||
# This is the default since MySQL 5.1.29 SET BINLOG_FORMAT='STATEMENT';
|
||||
|
||||
CREATE TABLE bug40360 (a INT) engine=innodb;
|
||||
|
||||
INSERT INTO bug40360 VALUES (1);
|
||||
|
||||
DROP TABLE bug40360;
|
14
mysql-test/t/innodb_bug41904.test
Normal file
14
mysql-test/t/innodb_bug41904.test
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# Make sure http://bugs.mysql.com/41904 remains fixed.
|
||||
#
|
||||
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
CREATE TABLE bug41904 (id INT PRIMARY KEY, uniquecol CHAR(15)) ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO bug41904 VALUES (1,NULL), (2,NULL);
|
||||
|
||||
CREATE UNIQUE INDEX ui ON bug41904 (uniquecol);
|
||||
|
||||
DROP TABLE bug41904;
|
145
mysql-test/t/innodb_information_schema.test
Normal file
145
mysql-test/t/innodb_information_schema.test
Normal file
@ -0,0 +1,145 @@
|
||||
#
|
||||
# Test that user data is correctly "visualized" in
|
||||
# INFORMATION_SCHEMA.innodb_locks.lock_data
|
||||
#
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
SET storage_engine=InnoDB;
|
||||
|
||||
-- disable_warnings
|
||||
DROP TABLE IF EXISTS t_min, t_max;
|
||||
-- enable_warnings
|
||||
|
||||
let $table_def =
|
||||
(
|
||||
c01 TINYINT,
|
||||
c02 TINYINT UNSIGNED,
|
||||
c03 SMALLINT,
|
||||
c04 SMALLINT UNSIGNED,
|
||||
c05 MEDIUMINT,
|
||||
c06 MEDIUMINT UNSIGNED,
|
||||
c07 INT,
|
||||
c08 INT UNSIGNED,
|
||||
c09 BIGINT,
|
||||
c10 BIGINT UNSIGNED,
|
||||
PRIMARY KEY(c01, c02, c03, c04, c05, c06, c07, c08, c09, c10)
|
||||
);
|
||||
|
||||
-- eval CREATE TABLE t_min $table_def;
|
||||
INSERT INTO t_min VALUES
|
||||
(-128, 0,
|
||||
-32768, 0,
|
||||
-8388608, 0,
|
||||
-2147483648, 0,
|
||||
-9223372036854775808, 0);
|
||||
|
||||
-- eval CREATE TABLE t_max $table_def;
|
||||
INSERT INTO t_max VALUES
|
||||
(127, 255,
|
||||
32767, 65535,
|
||||
8388607, 16777215,
|
||||
2147483647, 4294967295,
|
||||
9223372036854775807, 18446744073709551615);
|
||||
|
||||
CREATE TABLE ```t'\"_str` (
|
||||
c1 VARCHAR(32),
|
||||
c2 VARCHAR(32),
|
||||
c3 VARCHAR(32),
|
||||
c4 VARCHAR(32),
|
||||
c5 VARCHAR(32),
|
||||
c6 VARCHAR(32),
|
||||
c7 VARCHAR(32),
|
||||
PRIMARY KEY(c1, c2, c3, c4, c5, c6, c7)
|
||||
);
|
||||
INSERT INTO ```t'\"_str` VALUES
|
||||
('1', 'abc', '''abc', 'abc''', 'a''bc', 'a''bc''', '''abc''''');
|
||||
INSERT INTO ```t'\"_str` VALUES
|
||||
('2', 'abc', '"abc', 'abc"', 'a"bc', 'a"bc"', '"abc""');
|
||||
INSERT INTO ```t'\"_str` VALUES
|
||||
('3', 'abc', '\\abc', 'abc\\', 'a\\bc', 'a\\bc\\', '\\abc\\\\');
|
||||
INSERT INTO ```t'\"_str` VALUES
|
||||
('4', 'abc', 0x00616263, 0x61626300, 0x61006263, 0x6100626300, 0x610062630000);
|
||||
|
||||
-- connect (con_lock,localhost,root,,)
|
||||
-- connect (con_min_trylock,localhost,root,,)
|
||||
-- connect (con_max_trylock,localhost,root,,)
|
||||
-- connect (con_str_insert_supremum,localhost,root,,)
|
||||
-- connect (con_str_lock_row1,localhost,root,,)
|
||||
-- connect (con_str_lock_row2,localhost,root,,)
|
||||
-- connect (con_str_lock_row3,localhost,root,,)
|
||||
-- connect (con_str_lock_row4,localhost,root,,)
|
||||
-- connect (con_verify_innodb_locks,localhost,root,,)
|
||||
|
||||
-- connection con_lock
|
||||
SET autocommit=0;
|
||||
SELECT * FROM t_min FOR UPDATE;
|
||||
SELECT * FROM t_max FOR UPDATE;
|
||||
SELECT * FROM ```t'\"_str` FOR UPDATE;
|
||||
|
||||
-- connection con_min_trylock
|
||||
-- send
|
||||
SELECT * FROM t_min FOR UPDATE;
|
||||
|
||||
-- connection con_max_trylock
|
||||
-- send
|
||||
SELECT * FROM t_max FOR UPDATE;
|
||||
|
||||
-- connection con_str_insert_supremum
|
||||
-- send
|
||||
INSERT INTO ```t'\"_str` VALUES
|
||||
('z', 'z', 'z', 'z', 'z', 'z', 'z');
|
||||
|
||||
-- connection con_str_lock_row1
|
||||
-- send
|
||||
SELECT * FROM ```t'\"_str` WHERE c1 = '1' FOR UPDATE;
|
||||
|
||||
-- connection con_str_lock_row2
|
||||
-- send
|
||||
SELECT * FROM ```t'\"_str` WHERE c1 = '2' FOR UPDATE;
|
||||
|
||||
-- connection con_str_lock_row3
|
||||
-- send
|
||||
SELECT * FROM ```t'\"_str` WHERE c1 = '3' FOR UPDATE;
|
||||
|
||||
-- connection con_str_lock_row4
|
||||
-- send
|
||||
SELECT * FROM ```t'\"_str` WHERE c1 = '4' FOR UPDATE;
|
||||
|
||||
# Give time to the above 2 queries to execute before continuing.
|
||||
# Without this sleep it sometimes happens that the SELECT from innodb_locks
|
||||
# executes before some of them, resulting in less than expected number
|
||||
# of rows being selected from innodb_locks.
|
||||
-- sleep 0.1
|
||||
|
||||
-- enable_result_log
|
||||
-- connection con_verify_innodb_locks
|
||||
SELECT lock_mode, lock_type, lock_table, lock_index, lock_rec, lock_data
|
||||
FROM INFORMATION_SCHEMA.INNODB_LOCKS ORDER BY lock_data;
|
||||
|
||||
SELECT lock_table,COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS
|
||||
GROUP BY lock_table;
|
||||
|
||||
set @save_sql_mode = @@sql_mode;
|
||||
SET SQL_MODE='ANSI_QUOTES';
|
||||
SELECT lock_table,COUNT(*) FROM INFORMATION_SCHEMA.INNODB_LOCKS
|
||||
GROUP BY lock_table;
|
||||
SET @@sql_mode=@save_sql_mode;
|
||||
-- disable_result_log
|
||||
|
||||
-- connection default
|
||||
|
||||
-- disconnect con_lock
|
||||
-- disconnect con_min_trylock
|
||||
-- disconnect con_max_trylock
|
||||
-- disconnect con_str_insert_supremum
|
||||
-- disconnect con_str_lock_row1
|
||||
-- disconnect con_str_lock_row2
|
||||
-- disconnect con_str_lock_row3
|
||||
-- disconnect con_str_lock_row4
|
||||
-- disconnect con_verify_innodb_locks
|
||||
|
||||
DROP TABLE t_min, t_max, ```t'\"_str`;
|
45
mysql-test/t/innodb_xtradb_bug317074.test
Normal file
45
mysql-test/t/innodb_xtradb_bug317074.test
Normal file
@ -0,0 +1,45 @@
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
SET @save_innodb_file_format=@@global.innodb_file_format;
|
||||
SET @save_innodb_file_format_check=@@global.innodb_file_format_check;
|
||||
SET @save_innodb_file_per_table=@@global.innodb_file_per_table;
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
||||
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
DROP TABLE IF EXISTS `test1`;
|
||||
CREATE TABLE IF NOT EXISTS `test1` (
|
||||
`a` int primary key auto_increment,
|
||||
`b` int default 0,
|
||||
`c` char(100) default 'testtest'
|
||||
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
|
||||
|
||||
delimiter |;
|
||||
CREATE PROCEDURE insert_many(p1 int)
|
||||
BEGIN
|
||||
SET @x = 0;
|
||||
SET @y = 0;
|
||||
REPEAT
|
||||
insert into test1 set b=1;
|
||||
SET @x = @x + 1;
|
||||
SET @y = @y + 1;
|
||||
IF @y >= 100 THEN
|
||||
commit;
|
||||
SET @y = 0;
|
||||
END IF;
|
||||
UNTIL @x >= p1 END REPEAT;
|
||||
END|
|
||||
delimiter ;|
|
||||
call insert_many(100000);
|
||||
DROP PROCEDURE insert_many;
|
||||
|
||||
# The bug is hangup at the following statement
|
||||
ALTER TABLE test1 ENGINE=MyISAM;
|
||||
|
||||
SET GLOBAL innodb_file_format=@save_innodb_file_format;
|
||||
SET GLOBAL innodb_file_format_check=@save_innodb_file_format_check;
|
||||
SET GLOBAL innodb_file_per_table=@save_innodb_file_per_table;
|
||||
|
||||
DROP TABLE test1;
|
@ -23,6 +23,16 @@
|
||||
# This is a big test.
|
||||
--source include/big_test.inc
|
||||
|
||||
--echo #
|
||||
--echo # We need big packets.
|
||||
--echo #
|
||||
connect (con1, localhost, root,,);
|
||||
connection con1;
|
||||
SET @old_global_max_allowed_packet=@@global.max_allowed_packet;
|
||||
SET @@global.max_allowed_packet= 1024*1024*1024;
|
||||
connect (con2, localhost, root,,);
|
||||
connection con2;
|
||||
|
||||
--echo #
|
||||
--echo # Preparatory cleanup.
|
||||
--echo #
|
||||
@ -35,11 +45,6 @@ DROP TABLE IF EXISTS t1;
|
||||
--echo #
|
||||
SET timestamp=1000000000;
|
||||
|
||||
--echo #
|
||||
--echo # We need big packets.
|
||||
--echo #
|
||||
SET @@global.max_allowed_packet= 1024*1024*1024;
|
||||
|
||||
--echo #
|
||||
--echo # Delete all existing binary logs.
|
||||
--echo #
|
||||
@ -122,9 +127,14 @@ let $MYSQLD_DATADIR= `select @@datadir`;
|
||||
--echo #
|
||||
DROP TABLE t1;
|
||||
|
||||
connection con1;
|
||||
SET @@global.max_allowed_packet=@old_global_max_allowed_packet;
|
||||
|
||||
--echo remove_file \$MYSQLTEST_VARDIR/$mysqlbinlog_output
|
||||
#
|
||||
# NOTE: If you want to see the *huge* mysqlbinlog output, disable next line:
|
||||
#
|
||||
--remove_file $MYSQLTEST_VARDIR/$mysqlbinlog_output
|
||||
|
||||
disconnect con1
|
||||
disconnect con2
|
||||
|
@ -27,14 +27,14 @@ UPDATE t1 SET DATA = data*2 WHERE id = 3;
|
||||
|
||||
# grouping/referencing in replace_regex is very slow on long strings,
|
||||
# removing all before/after the interesting row before grouping/referencing
|
||||
--replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
|
||||
--replace_regex /.*LIST OF TRANSACTIONS FOR EACH SESSION:// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
|
||||
SHOW ENGINE InnoDB STATUS;
|
||||
|
||||
UPDATE t1 SET data = data*2 WHERE data = 2;
|
||||
|
||||
# grouping/referencing in replace_regex is very slow on long strings,
|
||||
# removing all before/after the interesting row before grouping/referencing
|
||||
--replace_regex /.*---TRANSACTION [0-9]+ [0-9]+, .*, OS thread id [0-9]+// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
|
||||
--replace_regex /.*LIST OF TRANSACTIONS FOR EACH SESSION:// /MySQL thread id [0-9]+, query id [0-9]+ .*// /.*([0-9]+ lock struct\(s\)), heap size [0-9]+, ([0-9]+ row lock\(s\)).*/\1 \2/
|
||||
SHOW ENGINE InnoDB STATUS;
|
||||
|
||||
SET @@session.tx_isolation = @old_tx_isolation;
|
||||
|
@ -41,7 +41,7 @@ create table t1 (a bit) engine=innodb;
|
||||
insert into t1 values (b'0'), (b'1'), (b'000'), (b'100'), (b'001');
|
||||
select hex(a) from t1;
|
||||
# It is not deterministic which duplicate will be seen first
|
||||
--replace_regex /(.*Duplicate entry )'.*'( for key.*)/\1''\2/
|
||||
--replace_regex /entry '(.*)' for/entry '' for/
|
||||
--error ER_DUP_ENTRY
|
||||
alter table t1 add unique (a);
|
||||
drop table t1;
|
||||
|
@ -8,19 +8,20 @@
|
||||
# Bug #27322 failure to allocate transaction_prealloc_size causes crash
|
||||
#
|
||||
|
||||
set @pid_temp = (select ID from information_schema.processlist);
|
||||
set session transaction_prealloc_size=1024*1024*1024*1;
|
||||
--replace_column 1 #
|
||||
show processlist;
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
set session transaction_prealloc_size=1024*1024*1024*2;
|
||||
--replace_column 1 #
|
||||
show processlist;
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
--replace_column 1 #
|
||||
set session transaction_prealloc_size=1024*1024*1024*3;
|
||||
--replace_column 1 #
|
||||
show processlist;
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
set session transaction_prealloc_size=1024*1024*1024*4;
|
||||
--replace_column 1 #
|
||||
show processlist;
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
set session transaction_prealloc_size=1024*1024*1024*5;
|
||||
--replace_column 1 #
|
||||
show processlist;
|
||||
select @pid_temp = (select ID from information_schema.processlist) as 'TRUE';
|
||||
|
@ -464,3 +464,52 @@ process_flags:
|
||||
err:
|
||||
return (size_t) -1;
|
||||
}
|
||||
|
||||
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||
const char *default_val)
|
||||
{
|
||||
uint length;
|
||||
DBUG_ENTER("init_strvar_from_file");
|
||||
|
||||
if ((length=my_b_gets(f,var, max_size)))
|
||||
{
|
||||
char* last_p = var + length -1;
|
||||
if (*last_p == '\n')
|
||||
*last_p = 0; /* if we stopped on newline, kill it */
|
||||
else
|
||||
{
|
||||
/*
|
||||
If we truncated a line or stopped on last char, remove all chars
|
||||
up to and including newline.
|
||||
*/
|
||||
int c;
|
||||
while (((c=my_b_get(f)) != '\n' && c != my_b_EOF))
|
||||
;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else if (default_val)
|
||||
{
|
||||
strmake(var, default_val, max_size-1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
|
||||
{
|
||||
char buf[32];
|
||||
DBUG_ENTER("init_intvar_from_file");
|
||||
|
||||
if (my_b_gets(f, buf, sizeof(buf)))
|
||||
{
|
||||
*var = atoi(buf);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else if (default_val)
|
||||
{
|
||||
*var = default_val;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
@ -149,6 +149,35 @@ static inline void remove_from_active_list(safe_mutex_t *mp)
|
||||
mp->prev= mp->next= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
We initialise the hashes for deadlock detection lazily.
|
||||
This greatly helps with performance when lots of mutexes are initiased but
|
||||
only a few of them are actually used (eg. XtraDB).
|
||||
*/
|
||||
static int safe_mutex_lazy_init_deadlock_detection(safe_mutex_t *mp)
|
||||
{
|
||||
if (!my_multi_malloc(MY_FAE | MY_WME,
|
||||
&mp->locked_mutex, sizeof(*mp->locked_mutex),
|
||||
&mp->used_mutex, sizeof(*mp->used_mutex), NullS))
|
||||
{
|
||||
return 1; /* Error */
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&THR_LOCK_mutex);
|
||||
mp->id= ++safe_mutex_id;
|
||||
pthread_mutex_unlock(&THR_LOCK_mutex);
|
||||
hash_init(mp->locked_mutex, &my_charset_bin,
|
||||
1000,
|
||||
offsetof(safe_mutex_deadlock_t, id),
|
||||
sizeof(mp->id),
|
||||
0, 0, HASH_UNIQUE);
|
||||
hash_init(mp->used_mutex, &my_charset_bin,
|
||||
1000,
|
||||
offsetof(safe_mutex_t, id),
|
||||
sizeof(mp->id),
|
||||
0, 0, HASH_UNIQUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int safe_mutex_init(safe_mutex_t *mp,
|
||||
const pthread_mutexattr_t *attr __attribute__((unused)),
|
||||
@ -167,35 +196,8 @@ int safe_mutex_init(safe_mutex_t *mp,
|
||||
mp->line= line;
|
||||
/* Skip the very common '&' prefix from the autogenerated name */
|
||||
mp->name= name[0] == '&' ? name + 1 : name;
|
||||
/* Deadlock detection is initialised only lazily, on first use. */
|
||||
|
||||
if (safe_mutex_deadlock_detector && !( my_flags & MYF_NO_DEADLOCK_DETECTION))
|
||||
{
|
||||
if (!my_multi_malloc(MY_FAE | MY_WME,
|
||||
&mp->locked_mutex, sizeof(*mp->locked_mutex),
|
||||
&mp->used_mutex, sizeof(*mp->used_mutex), NullS))
|
||||
{
|
||||
/* Disable deadlock handling for this mutex */
|
||||
my_flags|= MYF_NO_DEADLOCK_DETECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock(&THR_LOCK_mutex);
|
||||
mp->id= ++safe_mutex_id;
|
||||
pthread_mutex_unlock(&THR_LOCK_mutex);
|
||||
hash_init(mp->locked_mutex, &my_charset_bin,
|
||||
1000,
|
||||
offsetof(safe_mutex_deadlock_t, id),
|
||||
sizeof(mp->id),
|
||||
0, 0, HASH_UNIQUE);
|
||||
hash_init(mp->used_mutex, &my_charset_bin,
|
||||
1000,
|
||||
offsetof(safe_mutex_t, id),
|
||||
sizeof(mp->id),
|
||||
0, 0, HASH_UNIQUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
my_flags|= MYF_NO_DEADLOCK_DETECTION;
|
||||
mp->create_flags= my_flags;
|
||||
|
||||
#ifdef SAFE_MUTEX_DETECT_DESTROY
|
||||
@ -310,7 +312,8 @@ int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
|
||||
/* Deadlock detection */
|
||||
|
||||
mp->prev= mp->next= 0;
|
||||
if (!(mp->active_flags & (MYF_TRY_LOCK | MYF_NO_DEADLOCK_DETECTION)))
|
||||
if (!(mp->active_flags & (MYF_TRY_LOCK | MYF_NO_DEADLOCK_DETECTION)) &&
|
||||
(mp->used_mutex != NULL || !safe_mutex_lazy_init_deadlock_detection(mp)))
|
||||
{
|
||||
safe_mutex_t **mutex_in_use= my_thread_var_mutex_in_use();
|
||||
|
||||
@ -643,7 +646,7 @@ int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line)
|
||||
void safe_mutex_free_deadlock_data(safe_mutex_t *mp)
|
||||
{
|
||||
/* Free all entries that points to this one */
|
||||
if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION))
|
||||
if (!(mp->create_flags & MYF_NO_DEADLOCK_DETECTION) && mp->used_mutex != NULL)
|
||||
{
|
||||
pthread_mutex_lock(&THR_LOCK_mutex);
|
||||
my_hash_iterate(mp->used_mutex,
|
||||
|
@ -9313,3 +9313,29 @@ st_print_event_info::st_print_event_info()
|
||||
open_cached_file(&body_cache, NULL, NULL, 0, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MYSQL_SERVER)
|
||||
/*
|
||||
Access to the current replication position.
|
||||
|
||||
There is a dummy replacement for this in the embedded library that returns
|
||||
FALSE; this is used by XtraDB to allow it to access replication stuff while
|
||||
still being able to use the same plugin in both stand-alone and embedded.
|
||||
*/
|
||||
bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos,
|
||||
const char **group_relay_log_name,
|
||||
ulonglong *relay_log_pos)
|
||||
{
|
||||
#if defined(EMBEDDED_LIBRARY) || !defined(HAVE_REPLICATION)
|
||||
return FALSE;
|
||||
#else
|
||||
const Relay_log_info *rli= &(active_mi->rli);
|
||||
*log_file_name= rli->group_master_log_name;
|
||||
*log_pos= rli->group_master_log_pos +
|
||||
(rli->future_event_relay_log_pos - rli->group_relay_log_pos);
|
||||
*group_relay_log_name= rli->group_relay_log_name;
|
||||
*relay_log_pos= rli->future_event_relay_log_pos;
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
@ -3917,6 +3917,10 @@ static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache,
|
||||
reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE);
|
||||
}
|
||||
|
||||
bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos,
|
||||
const char **group_relay_log_name,
|
||||
ulonglong *relay_log_pos);
|
||||
|
||||
/**
|
||||
@} (end of group Replication)
|
||||
*/
|
||||
|
@ -22,11 +22,6 @@
|
||||
#ifdef HAVE_REPLICATION
|
||||
|
||||
|
||||
// Defined in slave.cc
|
||||
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
|
||||
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||
const char *default_val);
|
||||
|
||||
Master_info::Master_info()
|
||||
:Slave_reporting_capability("I/O"),
|
||||
ssl(0), ssl_verify_server_cert(0), fd(-1), io_thd(0), inited(0),
|
||||
|
@ -23,11 +23,6 @@
|
||||
|
||||
static int count_relay_log_space(Relay_log_info* rli);
|
||||
|
||||
// Defined in slave.cc
|
||||
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
|
||||
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||
const char *default_val);
|
||||
|
||||
|
||||
Relay_log_info::Relay_log_info()
|
||||
:Slave_reporting_capability("SQL"),
|
||||
|
51
sql/slave.cc
51
sql/slave.cc
@ -755,57 +755,6 @@ const char *print_slave_db_safe(const char* db)
|
||||
DBUG_RETURN((db ? db : ""));
|
||||
}
|
||||
|
||||
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
|
||||
const char *default_val)
|
||||
{
|
||||
uint length;
|
||||
DBUG_ENTER("init_strvar_from_file");
|
||||
|
||||
if ((length=my_b_gets(f,var, max_size)))
|
||||
{
|
||||
char* last_p = var + length -1;
|
||||
if (*last_p == '\n')
|
||||
*last_p = 0; // if we stopped on newline, kill it
|
||||
else
|
||||
{
|
||||
/*
|
||||
If we truncated a line or stopped on last char, remove all chars
|
||||
up to and including newline.
|
||||
*/
|
||||
int c;
|
||||
while (((c=my_b_get(f)) != '\n' && c != my_b_EOF))
|
||||
;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else if (default_val)
|
||||
{
|
||||
strmake(var, default_val, max_size-1);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
||||
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
|
||||
{
|
||||
char buf[32];
|
||||
DBUG_ENTER("init_intvar_from_file");
|
||||
|
||||
|
||||
if (my_b_gets(f, buf, sizeof(buf)))
|
||||
{
|
||||
*var = atoi(buf);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
else if (default_val)
|
||||
{
|
||||
*var = default_val;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/*
|
||||
Note that we rely on the master's version (3.23, 4.0.14 etc) instead of
|
||||
relying on the binlog's version. This is not perfect: imagine an upgrade
|
||||
|
97
storage/xtradb/CMakeLists.txt
Normal file
97
storage/xtradb/CMakeLists.txt
Normal file
@ -0,0 +1,97 @@
|
||||
# Copyright (C) 2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
ADD_DEFINITIONS(-D_WIN32 -D_LIB)
|
||||
|
||||
# Bug 19424 - InnoDB: Possibly a memory overrun of the buffer being freed (64-bit Visual C)
|
||||
# Removing Win64 compiler optimizations for all innodb/mem/* files.
|
||||
IF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/storage/xtradb/mem/mem0mem.c
|
||||
${CMAKE_SOURCE_DIR}/storage/xtradb/mem/mem0pool.c
|
||||
PROPERTIES COMPILE_FLAGS -Od)
|
||||
ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
|
||||
${CMAKE_SOURCE_DIR}/storage/xtradb/include
|
||||
${CMAKE_SOURCE_DIR}/storage/xtradb/handler
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
||||
buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
|
||||
data/data0data.c data/data0type.c
|
||||
dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c
|
||||
dyn/dyn0dyn.c
|
||||
eval/eval0eval.c eval/eval0proc.c
|
||||
fil/fil0fil.c
|
||||
fsp/fsp0fsp.c
|
||||
fut/fut0fut.c fut/fut0lst.c
|
||||
ha/ha0ha.c ha/hash0hash.c ha/ha0storage.c
|
||||
ibuf/ibuf0ibuf.c
|
||||
pars/lexyy.c pars/pars0grm.c pars/pars0opt.c pars/pars0pars.c pars/pars0sym.c
|
||||
lock/lock0lock.c lock/lock0iter.c
|
||||
log/log0log.c log/log0recv.c
|
||||
mach/mach0data.c
|
||||
mem/mem0mem.c mem/mem0pool.c
|
||||
mtr/mtr0log.c mtr/mtr0mtr.c
|
||||
os/os0file.c os/os0proc.c os/os0sync.c os/os0thread.c
|
||||
page/page0cur.c page/page0page.c page/page0zip.c
|
||||
que/que0que.c
|
||||
handler/ha_innodb.cc handler/handler0alter.cc handler/i_s.cc handler/mysql_addons.cc
|
||||
read/read0read.c
|
||||
rem/rem0cmp.c rem/rem0rec.c
|
||||
row/row0ext.c row/row0ins.c row/row0merge.c row/row0mysql.c
|
||||
row/row0purge.c row/row0row.c row/row0sel.c row/row0uins.c
|
||||
row/row0umod.c row/row0undo.c row/row0upd.c row/row0vers.c
|
||||
srv/srv0que.c srv/srv0srv.c srv/srv0start.c
|
||||
sync/sync0arr.c sync/sync0rw.c sync/sync0sync.c
|
||||
thr/thr0loc.c
|
||||
trx/trx0i_s.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/ut0list.c ut/ut0wqueue.c)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(innobase ${INNOBASE_SOURCES})
|
||||
ADD_DEPENDENCIES(innobase GenError)
|
||||
SET_TARGET_PROPERTIES(innobase PROPERTIES COMPILE_FLAGS "-DMYSQL_SERVER")
|
||||
|
||||
IF(INNODB_DYNAMIC_PLUGIN)
|
||||
# The dynamic plugin requires CMake 2.6.0 or later. Otherwise, the /DELAYLOAD property
|
||||
# will not be set
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR)
|
||||
ADD_LIBRARY(ha_innodb SHARED ${INNOBASE_SOURCES} ha_innodb.def handler/win_delay_loader.cc)
|
||||
ADD_DEPENDENCIES(ha_innodb GenError mysqld)
|
||||
# If build type is not specified as Release, default to Debug
|
||||
# This is a workaround to a problem in CMake 2.6, which does not
|
||||
# set the path of mysqld.lib correctly
|
||||
IF(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
SET(CMAKE_BUILD_TYPE "Release")
|
||||
ELSE(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
SET(CMAKE_BUILD_TYPE "Debug")
|
||||
ENDIF(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
TARGET_LINK_LIBRARIES(ha_innodb strings zlib)
|
||||
TARGET_LINK_LIBRARIES(ha_innodb ${CMAKE_SOURCE_DIR}/sql/${CMAKE_BUILD_TYPE}/mysqld.lib)
|
||||
SET_TARGET_PROPERTIES(ha_innodb PROPERTIES OUTPUT_NAME ha_innodb)
|
||||
SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/MAP /MAPINFO:EXPORTS")
|
||||
SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/ENTRY:\"_DllMainCRTStartup@12\"")
|
||||
SET_TARGET_PROPERTIES(ha_innodb PROPERTIES COMPILE_FLAGS "-DMYSQL_DYNAMIC_PLUGIN")
|
||||
SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/DELAYLOAD:mysqld.exe")
|
||||
ENDIF(INNODB_DYNAMIC_PLUGIN)
|
||||
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
30
storage/xtradb/COPYING.Google
Normal file
30
storage/xtradb/COPYING.Google
Normal file
@ -0,0 +1,30 @@
|
||||
Portions of this software contain modifications contributed by Google, Inc.
|
||||
These contributions are used with the following license:
|
||||
|
||||
Copyright (c) 2008, Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
* Neither the name of the Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
775
storage/xtradb/ChangeLog
Normal file
775
storage/xtradb/ChangeLog
Normal file
@ -0,0 +1,775 @@
|
||||
2009-03-05 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
|
||||
mysql-test/innodb-autoinc.test:
|
||||
Fix Bug#43203 Overflow from auto incrementing causes server segv
|
||||
|
||||
2009-02-25 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
|
||||
mysql-test/innodb-autoinc.test:
|
||||
Fix Bug#42714 AUTO_INCREMENT errors in 5.1.31
|
||||
|
||||
2009-02-23 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c:
|
||||
Fix Bug#43043 Crash on BLOB delete operation
|
||||
|
||||
2009-02-20 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Make innodb_use_sys_malloc=ON the default.
|
||||
|
||||
2009-02-20 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
|
||||
mysql-test/innodb-autoinc.test:
|
||||
Fix Bug#42400 InnoDB autoinc code can't handle floating-point columns
|
||||
|
||||
2009-02-18 The InnoDB Team
|
||||
|
||||
* include/ut0mem.h, os/os0proc.c, ut/ut0mem.c:
|
||||
Protect ut_total_allocated_memory with ut_list_mutex in
|
||||
os_mem_alloc_large() and os_mem_free_large(). The lack of this mutex
|
||||
protection could cause an assertion failure during fast index
|
||||
creation. Also, add UNIV_MEM_ALLOC and UNIV_MEM_FREE instrumentation
|
||||
to os_mem_alloc_large() and os_mem_free_large(), so that Valgrind can
|
||||
detect more errors.
|
||||
|
||||
2009-02-11 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Make innodb_thread_concurrency=0 the default. The old default value
|
||||
was 8. A non-zero setting may be useful when InnoDB is showing severe
|
||||
scalability problems under multiple concurrent connections.
|
||||
|
||||
2009-02-10 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, handler/ha_innodb.h:
|
||||
Fix Bug#41676 Table names are case insensitive in locking
|
||||
|
||||
2009-02-10 The InnoDB Team
|
||||
|
||||
* mem/mem0dbg.c, mem/mem0mem.c, mem/mem0pool.c:
|
||||
When innodb_use_sys_malloc is set, ignore
|
||||
innodb_additional_mem_pool_size, because nothing will be allocated
|
||||
from mem_comm_pool.
|
||||
|
||||
2009-02-10 The InnoDB Team
|
||||
|
||||
* ut/ut0mem.c:
|
||||
Map ut_malloc_low(), ut_realloc(), and ut_free() directly to malloc(),
|
||||
realloc(), and free() when innodb_use_sys_malloc is set. As a side
|
||||
effect, ut_total_allocated_memory ("Total memory allocated" in the
|
||||
"BUFFER POOL AND MEMORY" section of SHOW ENGINE INNODB STATUS) will
|
||||
exclude any memory allocated by these functions when
|
||||
innodb_use_sys_malloc is set.
|
||||
|
||||
2009-02-10 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, btr/btr0sea.c, buf/buf0buf.c, handler/ha_innodb.cc,
|
||||
include/buf0buf.ic, include/os0sync.h, include/srv0srv.h,
|
||||
include/sync0rw.h, include/sync0rw.ic, include/sync0sync.h,
|
||||
include/sync0sync.ic, include/univ.i, row/row0sel.c, srv/srv0srv.c,
|
||||
srv/srv0start.c, sync/sync0arr.c, sync/sync0rw.c, sync/sync0sync.c:
|
||||
On those platforms that support it, implement the synchronization
|
||||
primitives of InnoDB mutexes and read/write locks with GCC atomic
|
||||
builtins instead of Pthreads mutexes and InnoDB mutexes. These changes
|
||||
are based on a patch supplied by Mark Callaghan of Google under a BSD
|
||||
license.
|
||||
|
||||
2009-01-30 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, btr/btr0sea.c, buf/buf0buf.c, handler/ha_innodb.cc,
|
||||
include/btr0sea.h, include/buf0buf.h, include/sync0sync.h,
|
||||
sync/sync0sync.c:
|
||||
Make the configuration parameter innodb_adaptive_hash_index dynamic,
|
||||
so that it can be changed at runtime.
|
||||
|
||||
2009-01-29 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, ibuf/ibuf0ibuf.c, include/ibuf0ibuf.h,
|
||||
include/ibuf0ibuf.ic:
|
||||
Implement the settable global variable innodb_change_buffering,
|
||||
with the allowed values 'none' and 'inserts'. The default value
|
||||
'inserts' enables the buffering of inserts to non-unique secondary
|
||||
index trees when the B-tree leaf page is not in the buffer pool.
|
||||
|
||||
2009-01-27 The InnoDB Team
|
||||
|
||||
* buf/buf0lru.c:
|
||||
Fix a race condition in buf_LRU_invalidate_tablespace(): The
|
||||
compressed page size (zip_size) was read while the block descriptor
|
||||
was no longer protected by a mutex. This could lead to corruption
|
||||
when a table is dropped on a busy system that contains compressed
|
||||
tables.
|
||||
|
||||
2009-01-26 The InnoDB Team
|
||||
|
||||
* btr/btr0sea.c, buf/buf0buf.c, include/buf0buf.h, include/buf0buf.ic,
|
||||
include/mtr0log.ic, include/row0upd.ic, mtr/mtr0mtr.c:
|
||||
Implement buf_block_align() with pointer arithmetics, as it is in the
|
||||
built-in InnoDB distributed with MySQL. Do not acquire the buffer pool
|
||||
mutex before buf_block_align(). This removes a scalability bottleneck
|
||||
in the adaptive hash index lookup. In CHECK TABLE, check that
|
||||
buf_pool->page_hash is consistent with buf_block_align().
|
||||
|
||||
2009-01-23 The InnoDB Team
|
||||
|
||||
* btr/btr0sea.c:
|
||||
Fix Bug#42279 Race condition in btr_search_drop_page_hash_when_freed()
|
||||
|
||||
2009-01-23 The InnoDB Team
|
||||
|
||||
* buf/buf0buf.c, include/buf0buf.h:
|
||||
Remove the unused mode BUF_GET_NOWAIT of buf_page_get_gen()
|
||||
|
||||
2009-01-20 The InnoDB Team
|
||||
|
||||
* include/rem0rec.h, include/rem0rec.ic:
|
||||
Fix Bug#41571 MySQL segfaults after innodb recovery
|
||||
|
||||
2009-01-20 The InnoDB Team
|
||||
|
||||
* lock/lock0lock.c:
|
||||
Fix Bug#42152 Race condition in lock_is_table_exclusive()
|
||||
|
||||
2009-01-14 The InnoDB Team
|
||||
|
||||
* include/trx0roll.h, trx/trx0roll.c, trx/trx0trx.c:
|
||||
Fix Bug#38187 Error 153 when creating savepoints
|
||||
|
||||
2009-01-14 The InnoDB Team
|
||||
|
||||
* dict/dict0load.c:
|
||||
Fix Bug#42075 dict_load_indexes failure in dict_load_table will
|
||||
corrupt the dictionary cache
|
||||
|
||||
2009-01-13 The InnoDB Team
|
||||
|
||||
* buf/buf0buddy.c, dict/dict0dict.c, dict/dict0mem.c, fil/fil0fil.c,
|
||||
ha/ha0storage.c, handler/ha_innodb.cc, handler/win_delay_loader.cc,
|
||||
include/buf0buf.ic, include/dict0dict.ic, include/hash0hash.h,
|
||||
thr/thr0loc.c, trx/trx0i_s.c:
|
||||
Add the parameter ASSERTION to HASH_SEARCH() macro, and use it for
|
||||
light validation of the traversed items in hash table lookups when
|
||||
UNIV_DEBUG is enabled.
|
||||
|
||||
2009-01-09 The InnoDB Team
|
||||
|
||||
* buf/buf0flu.c, include/buf0flu.h, include/buf0flu.ic:
|
||||
Remove unused code from the functions
|
||||
buf_flush_insert_into_flush_list() and
|
||||
buf_flush_insert_sorted_into_flush_list().
|
||||
|
||||
2009-01-09 The InnoDB Team
|
||||
|
||||
* buf/buf0flu.c:
|
||||
Simplify the functions buf_flush_try_page() and buf_flush_batch(). Add
|
||||
debug assertions and an explanation to buf_flush_write_block_low().
|
||||
|
||||
2009-01-07 The InnoDB Team
|
||||
|
||||
* row/row0merge.c:
|
||||
Fix a bug in recovery when dropping temporary indexes.
|
||||
|
||||
2009-01-07 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:
|
||||
Fix Bug#41680 calls to trx_allocate_for_mysql are not consistent
|
||||
|
||||
2009-01-07 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb_bug41904.result, mysql-test/innodb_bug41904.test,
|
||||
row/row0merge.c:
|
||||
Fix Bug#41904 create unique index problem
|
||||
|
||||
2009-01-02 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, include/srv0srv.h, mem/mem0pool.c,
|
||||
mysql-test/innodb-use-sys-malloc-master.opt,
|
||||
mysql-test/innodb-use-sys-malloc.result,
|
||||
mysql-test/innodb-use-sys-malloc.test, srv/srv0srv.c, srv/srv0start.c:
|
||||
Implement the configuration parameter innodb_use_sys_malloc (false by
|
||||
default), for disabling InnoDB's internal memory allocator and using
|
||||
system malloc/free instead. The "BUFFER POOL AND MEMORY" section of
|
||||
SHOW ENGINE INNODB STATUS will report "in additional pool allocated
|
||||
allocated 0" when innodb_use_sys_malloc is set.
|
||||
|
||||
2008-12-30 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c:
|
||||
When setting the PAGE_LEVEL of a compressed B-tree page from or to 0,
|
||||
compress the page at the same time. This is necessary, because the
|
||||
column information stored on the compressed page will differ between
|
||||
leaf and non-leaf pages. Leaf pages are identified by PAGE_LEVEL=0.
|
||||
This bug can make InnoDB crash when all rows of a compressed table are
|
||||
deleted.
|
||||
|
||||
2008-12-17 The InnoDB Team
|
||||
|
||||
* include/row0sel.h, include/row0upd.h, pars/pars0pars.c,
|
||||
row/row0mysql.c, row/row0sel.c, row/row0upd.c:
|
||||
Remove update-in-place select from the internal SQL interpreter. It
|
||||
was only used for updating the InnoDB internal data dictionary when
|
||||
renaming or dropping tables. It could have caused deadlocks when
|
||||
acquiring latches on insert buffer bitmap pages.
|
||||
|
||||
2008-12-17 The InnoDB Team
|
||||
|
||||
* btr/btr0sea.c, buf/buf0buf.c, buf/buf0lru.c, ha/ha0ha.c,
|
||||
ha/hash0hash.c, include/buf0buf.h, include/ha0ha.h, include/ha0ha.ic,
|
||||
include/hash0hash.h, include/univ.i:
|
||||
Introduce the preprocessor symbol UNIV_AHI_DEBUG for enabling adaptive
|
||||
hash index debugging independently of UNIV_DEBUG.
|
||||
|
||||
2008-12-16 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c:
|
||||
Do not update the free bits in the insert buffer bitmap when inserting
|
||||
or deleting from the insert buffer B-tree. Assert that records in the
|
||||
insert buffer B-tree are never updated.
|
||||
|
||||
2008-12-12 The InnoDB Team
|
||||
|
||||
* buf/buf0buf.c, fil/fil0fil.c, fsp/fsp0fsp.c, ibuf/ibuf0ibuf.c,
|
||||
include/fil0fil.h, include/ibuf0ibuf.h, include/ibuf0ibuf.ic,
|
||||
include/ibuf0types.h:
|
||||
Clean up the insert buffer subsystem so that only one insert
|
||||
buffer B-tree exists.
|
||||
Originally, there were provisions in InnoDB for multiple insert
|
||||
buffer B-trees, apparently one for each tablespace.
|
||||
When Heikki Tuuri implemented multiple InnoDB tablespaces in
|
||||
MySQL/InnoDB 4.1, he made the insert buffer live only in the
|
||||
system tablespace (space 0) but left the provisions in the code.
|
||||
|
||||
2008-12-11 The InnoDB Team
|
||||
|
||||
* include/srv0srv.h, os/os0proc.c, srv/srv0srv.c:
|
||||
Fix the issue that the InnoDB plugin fails if innodb_buffer_pool_size
|
||||
is defined bigger than 4096M on 64-bit Windows. This bug should not
|
||||
have affected other 64-bit systems.
|
||||
|
||||
2008-12-09 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Fix Bug#40386 Not flushing query cache after truncate.
|
||||
|
||||
2008-12-09 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, srv/srv0srv.c, trx/trx0trx.c:
|
||||
Fix Bug#40760 "set global innodb_thread_concurrency = 0;" is not safe
|
||||
|
||||
2008-12-04 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, handler/mysql_addons.cc,
|
||||
include/mysql_addons.h, trx/trx0i_s.c, win-plugin/win-plugin.diff:
|
||||
Remove dependencies to MySQL internals (defining MYSQL_SERVER).
|
||||
|
||||
2008-12-02 The InnoDB Team
|
||||
|
||||
* page/page0cur.c:
|
||||
When allocating space for a record from the free list of previously
|
||||
purged records, zero out the DB_TRX_ID and DB_ROLL_PTR of the purged
|
||||
record if the new record would not overwrite these fields. This fixes
|
||||
a harmless content mismatch reported by page_zip_validate().
|
||||
|
||||
2008-12-02 The InnoDB Team
|
||||
|
||||
* row/row0merge.c:
|
||||
Replace the WHILE 1 with WHILE 1=1 in the SQL procedure, so that the
|
||||
loop will actually be entered and temporary indexes be dropped during
|
||||
crash recovery.
|
||||
|
||||
2008-12-01 The InnoDB Team
|
||||
|
||||
InnoDB Plugin 1.0.2 released
|
||||
|
||||
2008-10-31 The InnoDB Team
|
||||
|
||||
* dict/dict0mem.c, include/dict0mem.h, include/lock0lock.h,
|
||||
include/row0mysql.h, include/trx0trx.h, include/univ.i,
|
||||
include/ut0vec.h, include/ut0vec.ic, lock/lock0lock.c,
|
||||
row/row0mysql.c, trx/trx0trx.c:
|
||||
Fix Bug#26316 Triggers create duplicate entries on auto-increment
|
||||
columns
|
||||
|
||||
2008-10-30 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, handler/handler0vars.h,
|
||||
handler/win_delay_loader.cc, mysql-test/innodb_bug40360.result,
|
||||
mysql-test/innodb_bug40360.test:
|
||||
Fix Bug#40360 Binlog related errors with binlog off
|
||||
|
||||
2008-10-29 The InnoDB Team
|
||||
|
||||
* include/data0type.ic:
|
||||
Fix Bug#40369 dtype_get_sql_null_size() returns 0 or 1, not the size
|
||||
|
||||
2008-10-29 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, include/srv0srv.h, srv/srv0srv.c:
|
||||
Fix Bug#38189 innodb_stats_on_metadata missing
|
||||
|
||||
2008-10-28 The InnoDB Team
|
||||
|
||||
* CMakeLists.txt, ha_innodb.def, handler/ha_innodb.cc,
|
||||
handler/handler0alter.cc, handler/handler0vars.h, handler/i_s.cc,
|
||||
handler/win_delay_loader.cc, win-plugin/*:
|
||||
Implemented the delayloading of externals for the plugin on Windows.
|
||||
This makes it possible to build a dynamic plugin (ha_innodb.dll) on
|
||||
Windows.
|
||||
|
||||
2008-10-27 The InnoDB Team
|
||||
|
||||
* CMakeLists.txt:
|
||||
Fix Bug#19424 InnoDB: Possibly a memory overrun of the buffer being
|
||||
freed (64-bit Visual C)
|
||||
|
||||
2008-10-23 The InnoDB Team
|
||||
|
||||
* ibuf/ibuf0ibuf.c:
|
||||
ibuf_delete_rec(): When the cursor to the insert buffer record
|
||||
cannot be restored, do not complain if the tablespace does not
|
||||
exist, because the insert buffer record may have been discarded by
|
||||
some other thread. This bug has existed in MySQL/InnoDB since
|
||||
version 4.1, when innodb_file_per_table was implemented.
|
||||
This may fix Bug#27276 InnoDB Error: ibuf cursor restoration fails.
|
||||
|
||||
2008-10-22 The InnoDB Team
|
||||
|
||||
* dict/dict0dict.c, dict/dict0mem.c, handler/ha_innodb.cc,
|
||||
handler/ha_innodb.h, include/dict0dict.h, include/dict0mem.h,
|
||||
row/row0mysql.c:
|
||||
Fix Bug#39830 Table autoinc value not updated on first insert
|
||||
Fix Bug#35498 Cannot get table test/table1 auto-inccounter value in
|
||||
::info
|
||||
Fix Bug#36411 "Failed to read auto-increment value from storage
|
||||
engine" in 5.1.24 auto-inc
|
||||
|
||||
2008-10-22 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c:
|
||||
Fix Bug#40224 New AUTOINC changes mask reporting of deadlock/timeout
|
||||
errors
|
||||
|
||||
2008-10-16 The InnoDB Team
|
||||
|
||||
* dict/dict0dict.c, mysql-test/innodb-index.result,
|
||||
mysql-test/innodb-index.test:
|
||||
Skip the undo log size check when creating REDUNDANT and COMPACT
|
||||
tables. In ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED, column
|
||||
prefix indexes require that prefixes of externally stored columns
|
||||
be written to the undo log. This may make the undo log record
|
||||
bigger than the record on the B-tree page. The maximum size of an
|
||||
undo log record is the page size. That must be checked for, in
|
||||
dict_index_add_to_cache(). However, this restriction must not
|
||||
be enforced on REDUNDANT or COMPACT tables.
|
||||
|
||||
2008-10-15 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, include/btr0cur.h, row/row0ext.c, row/row0sel.c,
|
||||
row/row0upd.c:
|
||||
When the server crashes while freeing an externally stored column
|
||||
of a compressed table, the BTR_EXTERN_LEN field in the BLOB
|
||||
pointer will be written as 0. Tolerate this in the functions that
|
||||
deal with externally stored columns. This fixes problems after
|
||||
crash recovery, in the rollback of incomplete transactions, and in
|
||||
the purge of delete-marked records.
|
||||
|
||||
2008-10-15 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c, include/page0zip.h, page/page0zip.c, include/univ.i:
|
||||
When a B-tree node of a compressed table is split or merged, the
|
||||
compression may fail. In this case, the entire compressed page
|
||||
will be copied and the excess records will be deleted. However,
|
||||
page_zip_copy(), now renamed to page_zip_copy_recs(), copied too
|
||||
many fields in the page header, overwriting PAGE_BTR_SEG_LEAF and
|
||||
PAGE_BTR_SEG_TOP when splitting the B-tree root. This caused
|
||||
corruption of compressed tables. Furthermore, the lock table and
|
||||
the adaptive hash index would be corrupted, because we forgot to
|
||||
update them when invoking page_zip_copy_recs().
|
||||
|
||||
Introduce the symbol UNIV_ZIP_DEBUG for triggering the copying of
|
||||
compressed pages more often, for debugging purposes.
|
||||
|
||||
2008-10-10 The InnoDB Team
|
||||
|
||||
* handler/handler0alter.cc, include/row0merge.h, row/row0merge.c,
|
||||
row/row0mysql.c:
|
||||
Fix some locking issues, mainly in fast index creation. The
|
||||
InnoDB data dictionary cache should be latched whenever a
|
||||
transaction is holding locks on any data dictionary tables.
|
||||
Otherwise, lock waits or deadlocks could occur. Furthermore, the
|
||||
data dictionary transaction must be committed (and the locks
|
||||
released) before the data dictionary latch is released.
|
||||
|
||||
ha_innobase::add_index(): Lock the data dictionary before renaming
|
||||
or dropping the created indexes, because neither operation will
|
||||
commit the data dictionary transaction.
|
||||
|
||||
ha_innobase::final_drop_index(): Commit the transactions before
|
||||
unlocking the data dictionary.
|
||||
|
||||
2008-10-09 The InnoDB Team
|
||||
|
||||
* buf/buf0lru.c:
|
||||
Fix Bug#39939 DROP TABLE/DISCARD TABLESPACE takes long time in
|
||||
buf_LRU_invalidate_tablespace()
|
||||
|
||||
2008-10-08 The InnoDB Team
|
||||
|
||||
* dict/dict0crea.c, trx/trx0roll.c, include/row0mysql.h,
|
||||
row/row0merge.c, row/row0mysql.c:
|
||||
When dropping a table, hold the data dictionary latch until the
|
||||
transaction has been committed. The data dictionary latch is
|
||||
supposed to prevent lock waits and deadlocks in the data
|
||||
dictionary tables. Due to this bug, DROP TABLE could cause a
|
||||
deadlock or hang. Note that because of Bug#33650 and Bug#39833,
|
||||
MySQL may also drop a (temporary) table when executing CREATE INDEX
|
||||
or ALTER TABLE ... ADD INDEX.
|
||||
|
||||
2008-10-04 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb_bug39438-master.opt,
|
||||
mysql-test/innodb_bug39438.result, mysql-test/innodb_bug39438.test:
|
||||
Fix Bug#39438 Testcase for Bug#39436 crashes on 5.1 in
|
||||
fil_space_get_latch
|
||||
|
||||
2008-10-04 The InnoDB Team
|
||||
|
||||
* include/lock0lock.h, lock/lock0lock.c,
|
||||
mysql-test/innodb_bug38231.result, mysql-test/innodb_bug38231.test,
|
||||
row/row0mysql.c:
|
||||
Fix Bug#38231 Innodb crash in lock_reset_all_on_table() on TRUNCATE +
|
||||
LOCK / UNLOCK
|
||||
|
||||
2008-10-04 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Fix Bug#35498 Cannot get table test/table1 auto-inccounter value in
|
||||
::info
|
||||
|
||||
2008-10-04 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, handler/ha_innodb.h:
|
||||
Fix Bug#37788 InnoDB Plugin: AUTO_INCREMENT wrong for compressed
|
||||
tables
|
||||
|
||||
2008-10-04 The InnoDB Team
|
||||
|
||||
* dict/dict0dict.c, handler/ha_innodb.cc, handler/ha_innodb.h,
|
||||
include/dict0dict.h, include/dict0mem.h, row/row0mysql.c:
|
||||
Fix Bug#39830 Table autoinc value not updated on first insert
|
||||
|
||||
2008-10-03 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-index.test, mysql-test/innodb-index.result,
|
||||
mysql-test/innodb-timeout.test, mysql-test/innodb-timeout.result,
|
||||
srv/srv0srv.c, include/srv0srv.h, handler/ha_innodb.cc,
|
||||
include/ha_prototypes.h:
|
||||
Fix Bug#36285 innodb_lock_wait_timeout is not dynamic, not per session
|
||||
|
||||
2008-09-19 The InnoDB Team
|
||||
|
||||
* os/os0proc.c:
|
||||
Fix a memory leak on Windows. The memory leak was due to wrong
|
||||
parameters passed into VirtualFree() call. As the result, the
|
||||
call fails with Windows error 87.
|
||||
|
||||
2008-09-17 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb.result, mysql-test/innodb-zip.result,
|
||||
mysql-test/innodb-zip.test, mysql-test/innodb.test, ibuf/ibuf0ibuf.c,
|
||||
dict/dict0crea.c, dict/dict0load.c, dict/dict0boot.c,
|
||||
include/dict0dict.h, include/trx0trx.h, dict/dict0dict.c,
|
||||
trx/trx0trx.c, include/ha_prototypes.h, handler/ha_innodb.cc:
|
||||
When creating an index in innodb_strict_mode, check that the
|
||||
maximum record size will never exceed the B-tree page size limit.
|
||||
For uncompressed tables, there should always be enough space for
|
||||
two records in an empty B-tree page. For compressed tables, there
|
||||
should be enough space for storing two node pointer records or one
|
||||
data record in an empty page in uncompressed format.
|
||||
The purpose of this check is to guarantee that INSERT or UPDATE
|
||||
will never fail due to too big record size.
|
||||
|
||||
2008-09-17 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, data/data0data.c, include/page0zip.h,
|
||||
include/page0zip.ic, page/page0zip.c, mysql-test/innodb_bug36172.test:
|
||||
Prevent infinite B-tree page splits in compressed tables by
|
||||
ensuring that there will always be enough space for two node
|
||||
pointer records in an empty B-tree page. Also, require that at
|
||||
least one data record will fit in an empty compressed page. This
|
||||
will reduce the maximum size of records in compressed tables.
|
||||
|
||||
2008-09-09 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb.result:
|
||||
Fix the failing innodb test by merging changes that MySQL made to
|
||||
that file (r2646.12.1 in MySQL BZR repository)
|
||||
|
||||
2008-09-09 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
|
||||
mysql-test/innodb-autoinc.test:
|
||||
Fix Bug#38839 auto increment does not work properly with InnoDB after
|
||||
update
|
||||
|
||||
2008-09-09 The InnoDB Team
|
||||
|
||||
* dict/dict0dict.c, handler/handler0alter.cc, include/dict0dict.h,
|
||||
mysql-test/innodb-index.result, mysql-test/innodb-index.test:
|
||||
Fix Bug#38786 InnoDB plugin crashes on drop table/create table with FK
|
||||
|
||||
2008-08-21 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, include/ha_prototypes.h, row/row0sel.c:
|
||||
Fix Bug#37885 row_search_for_mysql may gap lock unnecessarily with SQL
|
||||
comments in query
|
||||
|
||||
2008-08-21 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Fix Bug#38185 ha_innobase::info can hold locks even when called with
|
||||
HA_STATUS_NO_LOCK
|
||||
|
||||
2008-08-18 The InnoDB Team
|
||||
|
||||
* buf/buf0buf.c, buf/buf0lru.c, include/buf0buf.ic, include/univ.i:
|
||||
Introduce UNIV_LRU_DEBUG for debugging the LRU buffer pool cache
|
||||
|
||||
2008-08-08 The InnoDB Team
|
||||
|
||||
* buf/buf0lru.c, include/buf0buf.h:
|
||||
Fix two recovery bugs that could lead to a crash in debug builds with
|
||||
small buffer size
|
||||
|
||||
2008-08-07 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, handler/ha_innodb.cc, include/srv0srv.h,
|
||||
srv/srv0srv.c:
|
||||
Add a parameter innodb_stats_sample_pages to allow users to control
|
||||
the number of index dives when InnoDB estimates the cardinality of
|
||||
an index (ANALYZE TABLE, SHOW TABLE STATUS etc)
|
||||
|
||||
2008-08-07 The InnoDB Team
|
||||
|
||||
* trx/trx0i_s.c:
|
||||
Fix a bug that would lead to a crash if a SELECT was issued from the
|
||||
INFORMATION_SCHEMA tables and there are rolling back transactions at
|
||||
the same time
|
||||
|
||||
2008-08-06 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c, btr/btr0cur.c, ibuf/ibuf0ibuf.c, include/btr0cur.h,
|
||||
include/trx0roll.h, include/trx0types.h, row/row0purge.c,
|
||||
row/row0uins.c, row/row0umod.c, trx/trx0roll.c:
|
||||
In the rollback of incomplete transactions after crash recovery,
|
||||
tolerate clustered index records whose externally stored columns
|
||||
have not been written.
|
||||
|
||||
2008-07-30 The InnoDB Team
|
||||
|
||||
* trx/trx0trx.c:
|
||||
Fixes a race in recovery where the recovery thread recovering a
|
||||
PREPARED trx and the background rollback thread can both try
|
||||
to free the trx after its status is set to COMMITTED_IN_MEMORY.
|
||||
|
||||
2008-07-29 The InnoDB Team
|
||||
|
||||
* include/trx0rec.h, row/row0purge.c, row/row0vers.c, trx/trx0rec.c:
|
||||
Fix a BLOB corruption bug
|
||||
|
||||
2008-07-15 The InnoDB Team
|
||||
|
||||
* btr/btr0sea.c, dict/dict0dict.c, include/btr0sea.h:
|
||||
Fixed a timing hole where a thread dropping an index can free the
|
||||
in-memory index struct while another thread is still using that
|
||||
structure to remove entries from adaptive hash index belonging
|
||||
to one of the pages that belongs to the index being dropped.
|
||||
|
||||
2008-07-04 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-index.result:
|
||||
Fix the failing innodb-index test by adjusting the result to a new
|
||||
MySQL behavior (the change occured in BZR-r2667)
|
||||
|
||||
2008-07-03 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-zip.result, mysql-test/innodb-zip.test:
|
||||
Remove the negative test cases that produce warnings
|
||||
|
||||
2008-07-02 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-replace.result, mysql-test/innodb-index.test:
|
||||
Disable part of innodb-index test because MySQL changed its behavior
|
||||
and is not calling ::add_index() anymore when adding primary index on
|
||||
non-NULL column
|
||||
|
||||
2008-07-01 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-replace.result, mysql-test/innodb-replace.test:
|
||||
Fix the failing innodb-replace test by merging changes that MySQL
|
||||
made to that file (r2659 in MySQL BZR repository)
|
||||
|
||||
2008-07-01 The InnoDB Team
|
||||
|
||||
* lock/lock0lock.c:
|
||||
Fix Bug#36942 Performance problem in lock_get_n_rec_locks (SHOW INNODB
|
||||
STATUS)
|
||||
|
||||
2008-07-01 The InnoDB Team
|
||||
|
||||
* ha/ha0ha.c:
|
||||
Fix Bug#36941 Performance problem in ha_print_info (SHOW INNODB
|
||||
STATUS)
|
||||
|
||||
2008-07-01 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.result,
|
||||
mysql-test/innodb-autoinc.test:
|
||||
Fix Bug#37531 After truncate, auto_increment behaves incorrectly for
|
||||
InnoDB
|
||||
|
||||
2008-06-19 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Rewrite the function innodb_plugin_init() to support parameters in
|
||||
different order (in static and dynamic InnoDB) and to support more
|
||||
parameters in the static InnoDB
|
||||
|
||||
2008-06-19 The InnoDB Team
|
||||
|
||||
* handler/handler0alter.cc:
|
||||
Fix a bug in ::add_index() which set the transaction state to "active"
|
||||
but never restored it to the original value. This bug caused warnings
|
||||
to be printed by the rpl.rpl_ddl mysql-test.
|
||||
|
||||
2008-06-19 The InnoDB Team
|
||||
|
||||
* mysql-test/patches:
|
||||
Add a directory which contains patches, which need to be applied to
|
||||
MySQL source in order to get some mysql-tests to succeed. The patches
|
||||
cannot be committed in MySQL repository because they are specific to
|
||||
the InnoDB plugin.
|
||||
|
||||
2008-06-19 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb-zip.result, mysql-test/innodb-zip.test,
|
||||
row/row0row.c:
|
||||
Fix an anomaly when updating a record with BLOB prefix
|
||||
|
||||
2008-06-18 The InnoDB Team
|
||||
|
||||
* include/trx0sys.h, srv/srv0start.c, trx/trx0sys.c:
|
||||
Fix a bug in recovery which was a side effect of the file_format_check
|
||||
changes
|
||||
|
||||
2008-06-09 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb.result:
|
||||
Fix the failing innodb test by merging changes that MySQL made to that
|
||||
file
|
||||
|
||||
2008-06-06 The InnoDB Team
|
||||
|
||||
* buf/buf0buf.c, handler/ha_innodb.cc, include/buf0buf.h,
|
||||
include/srv0srv.h, srv/srv0srv.c:
|
||||
Fix Bug#36600 SHOW STATUS takes a lot of CPU in
|
||||
buf_get_latched_pages_number
|
||||
|
||||
* handler/ha_innodb.cc, os/os0file.c:
|
||||
Fix Bug#11894 innodb_file_per_table crashes w/ Windows .sym symbolic
|
||||
link hack
|
||||
|
||||
* include/ut0ut.h, srv/srv0srv.c, ut/ut0ut.c:
|
||||
Fix Bug#36819 ut_usectime does not handle errors from gettimeofday
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Fix Bug#35602 Failed to read auto-increment value from storage engine
|
||||
|
||||
* srv/srv0start.c:
|
||||
Fix Bug#36149 Read buffer overflow in srv0start.c found during "make
|
||||
test"
|
||||
|
||||
2008-05-08 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c, mysql-test/innodb_bug36172.result,
|
||||
mysql-test/innodb_bug36172.test:
|
||||
Fix Bug#36172 insert into compressed innodb table crashes
|
||||
|
||||
2008-05-08 The InnoDB Team
|
||||
|
||||
InnoDB Plugin 1.0.1 released
|
||||
|
||||
2008-05-06 The InnoDB Team
|
||||
|
||||
* handler/ha_innodb.cc, include/srv0srv.h, include/sync0sync.h,
|
||||
include/trx0sys.h, mysql-test/innodb-zip.result,
|
||||
mysql-test/innodb-zip.test, srv/srv0srv.c, srv/srv0start.c,
|
||||
sync/sync0sync.c, trx/trx0sys.c:
|
||||
Implement the system tablespace tagging
|
||||
|
||||
* handler/ha_innodb.cc, handler/i_s.cc, include/univ.i,
|
||||
srv/srv0start.c:
|
||||
Add InnoDB version in INFORMATION_SCHEMA.PLUGINS.PLUGIN_VERSION,
|
||||
in the startup message and in a server variable innodb_version.
|
||||
|
||||
* sync/sync0sync.c:
|
||||
Fix a bug in the sync debug code where a lock with level
|
||||
SYNC_LEVEL_VARYING would cause an assertion failure when a thread
|
||||
tried to release it.
|
||||
|
||||
2008-04-30 The InnoDB Team
|
||||
|
||||
* Makefile.am:
|
||||
Fix Bug#36434 ha_innodb.so is installed in the wrong directory
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Merge change from MySQL (Fix Bug#35406 5.1-opt crashes on select from
|
||||
I_S.REFERENTIAL_CONSTRAINTS):
|
||||
ChangeSet@1.2563, 2008-03-18 19:42:04+04:00, gluh@mysql.com +1 -0
|
||||
|
||||
* scripts/install_innodb_plugins.sql:
|
||||
Added
|
||||
|
||||
* mysql-test/innodb.result:
|
||||
Merge change from MySQL (this fixes the failing innodb test):
|
||||
ChangeSet@1.1810.3601.4, 2008-02-07 02:33:21+04:00
|
||||
|
||||
* row/row0sel.c:
|
||||
Fix Bug#35226 RBR event crashes slave
|
||||
|
||||
* handler/ha_innodb.cc:
|
||||
Change the fix for Bug#32440 to show bytes instead of kilobytes in
|
||||
INFORMATION_SCHEMA.TABLES.DATA_FREE
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb.result,
|
||||
mysql-test/innodb.test:
|
||||
Fix Bug#29507 TRUNCATE shows to many rows effected
|
||||
|
||||
* handler/ha_innodb.cc, mysql-test/innodb.result,
|
||||
mysql-test/innodb.test:
|
||||
Fix Bug#35537 Innodb doesn't increment handler_update and
|
||||
handler_delete
|
||||
|
||||
2008-04-29 The InnoDB Team
|
||||
|
||||
* handler/i_s.cc, include/srv0start.h, srv/srv0start.c:
|
||||
Fix Bug#36310 InnoDB plugin crash
|
||||
|
||||
2008-04-23 The InnoDB Team
|
||||
|
||||
* mysql-test/innodb_bug36169.result, mysql-test/innodb_bug36169.test,
|
||||
row/row0mysql.c:
|
||||
Fix Bug#36169 create innodb compressed table with too large row size
|
||||
crashed
|
||||
|
||||
* (outside the source tree):
|
||||
Fix Bug#36222 New InnoDB plugin 1.0 has wrong MKDIR_P defined in
|
||||
Makefile.in
|
||||
|
||||
2008-04-15 The InnoDB Team
|
||||
|
||||
InnoDB Plugin 1.0.0 released
|
195
storage/xtradb/Makefile.am
Normal file
195
storage/xtradb/Makefile.am
Normal file
@ -0,0 +1,195 @@
|
||||
# Copyright (C) 2001, 2004, 2006 MySQL AB & Innobase Oy
|
||||
#
|
||||
# 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
|
||||
|
||||
# Process this file with automake to create Makefile.in
|
||||
|
||||
MYSQLDATAdir= $(localstatedir)
|
||||
MYSQLSHAREdir= $(pkgdatadir)
|
||||
MYSQLBASEdir= $(prefix)
|
||||
MYSQLLIBdir= $(pkglibdir)
|
||||
pkgplugindir= $(pkglibdir)/plugin
|
||||
INCLUDES= -I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||
-I$(top_srcdir)/regex \
|
||||
-I$(top_srcdir)/storage/xtradb/include \
|
||||
-I$(top_srcdir)/sql \
|
||||
-I$(srcdir)
|
||||
|
||||
DEFS= @DEFS@
|
||||
|
||||
|
||||
noinst_HEADERS= include/btr0btr.h include/btr0btr.ic \
|
||||
include/btr0cur.h include/btr0cur.ic \
|
||||
include/btr0pcur.h include/btr0pcur.ic \
|
||||
include/btr0sea.h include/btr0sea.ic \
|
||||
include/btr0types.h include/buf0buddy.h \
|
||||
include/buf0buddy.ic include/buf0buf.h \
|
||||
include/buf0buf.ic include/buf0flu.h \
|
||||
include/buf0flu.ic include/buf0lru.h \
|
||||
include/buf0lru.ic include/buf0rea.h \
|
||||
include/buf0types.h include/data0data.h \
|
||||
include/data0data.ic include/data0type.h \
|
||||
include/data0type.ic include/data0types.h \
|
||||
include/db0err.h include/dict0boot.h \
|
||||
include/dict0boot.ic include/dict0crea.h \
|
||||
include/dict0crea.ic include/dict0dict.h \
|
||||
include/dict0dict.ic include/dict0load.h \
|
||||
include/dict0load.ic include/dict0mem.h \
|
||||
include/dict0mem.ic include/dict0types.h \
|
||||
include/dyn0dyn.h include/dyn0dyn.ic \
|
||||
include/eval0eval.h include/eval0eval.ic \
|
||||
include/eval0proc.h include/eval0proc.ic \
|
||||
include/fil0fil.h include/fsp0fsp.h \
|
||||
include/fsp0fsp.ic include/fut0fut.h \
|
||||
include/fut0fut.ic include/fut0lst.h \
|
||||
include/fut0lst.ic include/ha0ha.h \
|
||||
include/ha0ha.ic \
|
||||
include/ha0storage.h \
|
||||
include/ha0storage.ic \
|
||||
include/hash0hash.h \
|
||||
include/hash0hash.ic include/ibuf0ibuf.h \
|
||||
include/ibuf0ibuf.ic include/ibuf0types.h \
|
||||
include/lock0iter.h \
|
||||
include/lock0lock.h include/lock0lock.ic \
|
||||
include/lock0priv.h include/lock0priv.ic \
|
||||
include/lock0types.h include/log0log.h \
|
||||
include/log0log.ic include/log0recv.h \
|
||||
include/log0recv.ic include/mach0data.h \
|
||||
include/mach0data.ic include/mem0dbg.h \
|
||||
include/mem0dbg.ic mem/mem0dbg.c \
|
||||
include/mem0mem.h include/mem0mem.ic \
|
||||
include/mem0pool.h include/mem0pool.ic \
|
||||
include/mtr0log.h include/mtr0log.ic \
|
||||
include/mtr0mtr.h include/mtr0mtr.ic \
|
||||
include/mtr0types.h \
|
||||
include/mysql_addons.h \
|
||||
include/os0file.h \
|
||||
include/os0proc.h include/os0proc.ic \
|
||||
include/os0sync.h include/os0sync.ic \
|
||||
include/os0thread.h include/os0thread.ic \
|
||||
include/page0cur.h include/page0cur.ic \
|
||||
include/page0page.h include/page0page.ic \
|
||||
include/page0zip.h include/page0zip.ic \
|
||||
include/page0types.h include/pars0grm.h \
|
||||
include/pars0opt.h include/pars0opt.ic \
|
||||
include/pars0pars.h include/pars0pars.ic \
|
||||
include/pars0sym.h include/pars0sym.ic \
|
||||
include/pars0types.h include/que0que.h \
|
||||
include/que0que.ic include/que0types.h \
|
||||
include/read0read.h include/read0read.ic \
|
||||
include/read0types.h include/rem0cmp.h \
|
||||
include/rem0cmp.ic include/rem0rec.h \
|
||||
include/rem0rec.ic include/rem0types.h \
|
||||
include/row0ext.h include/row0ext.ic \
|
||||
include/row0ins.h include/row0ins.ic \
|
||||
include/row0merge.h \
|
||||
include/row0mysql.h include/row0mysql.ic \
|
||||
include/row0purge.h include/row0purge.ic \
|
||||
include/row0row.h include/row0row.ic \
|
||||
include/row0sel.h include/row0sel.ic \
|
||||
include/row0types.h include/row0uins.h \
|
||||
include/row0uins.ic include/row0umod.h \
|
||||
include/row0umod.ic include/row0undo.h \
|
||||
include/row0undo.ic include/row0upd.h \
|
||||
include/row0upd.ic include/row0vers.h \
|
||||
include/row0vers.ic include/srv0que.h \
|
||||
include/srv0srv.h include/srv0srv.ic \
|
||||
include/srv0start.h include/sync0arr.h \
|
||||
include/sync0arr.ic include/sync0rw.h \
|
||||
include/sync0rw.ic include/sync0sync.h \
|
||||
include/sync0sync.ic include/sync0types.h \
|
||||
include/thr0loc.h include/thr0loc.ic \
|
||||
include/trx0i_s.h \
|
||||
include/trx0purge.h include/trx0purge.ic \
|
||||
include/trx0rec.h include/trx0rec.ic \
|
||||
include/trx0roll.h include/trx0roll.ic \
|
||||
include/trx0rseg.h include/trx0rseg.ic \
|
||||
include/trx0sys.h include/trx0sys.ic \
|
||||
include/trx0trx.h include/trx0trx.ic \
|
||||
include/trx0types.h include/trx0undo.h \
|
||||
include/trx0undo.ic include/trx0xa.h \
|
||||
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/ut0list.h \
|
||||
include/ut0list.ic include/ut0wqueue.h \
|
||||
include/ha_prototypes.h handler/ha_innodb.h \
|
||||
include/handler0alter.h \
|
||||
handler/i_s.h handler/innodb_patch_info.h
|
||||
|
||||
EXTRA_LIBRARIES= libinnobase.a
|
||||
noinst_LIBRARIES= @plugin_innobase_static_target@
|
||||
libinnobase_a_SOURCES= btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
|
||||
btr/btr0sea.c buf/buf0buddy.c \
|
||||
buf/buf0buf.c buf/buf0flu.c \
|
||||
buf/buf0lru.c buf/buf0rea.c data/data0data.c \
|
||||
data/data0type.c dict/dict0boot.c \
|
||||
dict/dict0crea.c dict/dict0dict.c \
|
||||
dict/dict0load.c dict/dict0mem.c dyn/dyn0dyn.c \
|
||||
eval/eval0eval.c eval/eval0proc.c \
|
||||
fil/fil0fil.c fsp/fsp0fsp.c fut/fut0fut.c \
|
||||
fut/fut0lst.c ha/ha0ha.c \
|
||||
ha/ha0storage.c \
|
||||
ha/hash0hash.c \
|
||||
ibuf/ibuf0ibuf.c lock/lock0iter.c \
|
||||
lock/lock0lock.c \
|
||||
log/log0log.c log/log0recv.c mach/mach0data.c \
|
||||
mem/mem0mem.c mem/mem0pool.c mtr/mtr0log.c \
|
||||
mtr/mtr0mtr.c os/os0file.c os/os0proc.c \
|
||||
os/os0sync.c os/os0thread.c page/page0cur.c \
|
||||
page/page0page.c page/page0zip.c \
|
||||
pars/lexyy.c pars/pars0grm.c \
|
||||
pars/pars0opt.c pars/pars0pars.c \
|
||||
pars/pars0sym.c que/que0que.c read/read0read.c \
|
||||
rem/rem0cmp.c rem/rem0rec.c row/row0ext.c \
|
||||
row/row0ins.c row/row0merge.c \
|
||||
row/row0mysql.c row/row0purge.c row/row0row.c \
|
||||
row/row0sel.c row/row0uins.c row/row0umod.c \
|
||||
row/row0undo.c row/row0upd.c row/row0vers.c \
|
||||
srv/srv0que.c srv/srv0srv.c srv/srv0start.c \
|
||||
sync/sync0arr.c sync/sync0rw.c \
|
||||
sync/sync0sync.c thr/thr0loc.c \
|
||||
trx/trx0i_s.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/ut0list.c ut/ut0mem.c ut/ut0rnd.c \
|
||||
ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c \
|
||||
handler/ha_innodb.cc handler/handler0alter.cc \
|
||||
handler/i_s.cc \
|
||||
handler/mysql_addons.cc
|
||||
|
||||
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
|
||||
libinnobase_a_CFLAGS= $(AM_CFLAGS)
|
||||
|
||||
EXTRA_LTLIBRARIES= ha_innodb.la
|
||||
pkgplugin_LTLIBRARIES= @plugin_innobase_shared_target@
|
||||
|
||||
ha_innodb_la_LDFLAGS= -module -rpath $(pkgplugindir)
|
||||
ha_innodb_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
|
||||
ha_innodb_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
|
||||
ha_innodb_la_SOURCES= $(libinnobase_a_SOURCES)
|
||||
|
||||
EXTRA_DIST= CMakeLists.txt plug.in \
|
||||
pars/make_bison.sh pars/make_flex.sh \
|
||||
pars/pars0grm.y pars/pars0lex.l
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
3656
storage/xtradb/btr/btr0btr.c
Normal file
3656
storage/xtradb/btr/btr0btr.c
Normal file
File diff suppressed because it is too large
Load Diff
4809
storage/xtradb/btr/btr0cur.c
Normal file
4809
storage/xtradb/btr/btr0cur.c
Normal file
File diff suppressed because it is too large
Load Diff
584
storage/xtradb/btr/btr0pcur.c
Normal file
584
storage/xtradb/btr/btr0pcur.c
Normal file
@ -0,0 +1,584 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
The index tree persistent cursor
|
||||
|
||||
Created 2/23/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "btr0pcur.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "btr0pcur.ic"
|
||||
#endif
|
||||
|
||||
#include "ut0byte.h"
|
||||
#include "rem0cmp.h"
|
||||
#include "trx0trx.h"
|
||||
|
||||
/******************************************************************
|
||||
Allocates memory for a persistent cursor object and initializes the cursor. */
|
||||
UNIV_INTERN
|
||||
btr_pcur_t*
|
||||
btr_pcur_create_for_mysql(void)
|
||||
/*============================*/
|
||||
/* out, own: persistent cursor */
|
||||
{
|
||||
btr_pcur_t* pcur;
|
||||
|
||||
pcur = mem_alloc(sizeof(btr_pcur_t));
|
||||
|
||||
pcur->btr_cur.index = NULL;
|
||||
btr_pcur_init(pcur);
|
||||
|
||||
return(pcur);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Frees the memory for a persistent cursor object. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_free_for_mysql(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor) /* in, own: persistent cursor */
|
||||
{
|
||||
if (cursor->old_rec_buf != NULL) {
|
||||
|
||||
mem_free(cursor->old_rec_buf);
|
||||
|
||||
cursor->old_rec_buf = NULL;
|
||||
}
|
||||
|
||||
cursor->btr_cur.page_cur.rec = NULL;
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_n_fields = 0;
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
cursor->latch_mode = BTR_NO_LATCHES;
|
||||
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
|
||||
|
||||
mem_free(cursor);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
The position of the cursor is stored by taking an initial segment of the
|
||||
record the cursor is positioned on, before, or after, and copying it to the
|
||||
cursor data structure, or just setting a flag if the cursor id before the
|
||||
first in an EMPTY tree, or after the last in an EMPTY tree. NOTE that the
|
||||
page where the cursor is positioned must not be empty if the index tree is
|
||||
not totally empty! */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_store_position(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor, /* in: persistent cursor */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
page_cur_t* page_cursor;
|
||||
buf_block_t* block;
|
||||
rec_t* rec;
|
||||
dict_index_t* index;
|
||||
page_t* page;
|
||||
ulint offs;
|
||||
|
||||
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
block = btr_pcur_get_block(cursor);
|
||||
index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
|
||||
|
||||
page_cursor = btr_pcur_get_page_cur(cursor);
|
||||
|
||||
rec = page_cur_get_rec(page_cursor);
|
||||
page = page_align(rec);
|
||||
offs = page_offset(rec);
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_S_FIX)
|
||||
|| mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_a(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
if (UNIV_UNLIKELY(page_get_n_recs(page) == 0)) {
|
||||
/* It must be an empty index tree; NOTE that in this case
|
||||
we do not store the modify_clock, but always do a search
|
||||
if we restore the cursor position */
|
||||
|
||||
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
|
||||
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
if (page_rec_is_supremum_low(offs)) {
|
||||
|
||||
cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
|
||||
} else {
|
||||
cursor->rel_pos = BTR_PCUR_BEFORE_FIRST_IN_TREE;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (page_rec_is_supremum_low(offs)) {
|
||||
|
||||
rec = page_rec_get_prev(rec);
|
||||
|
||||
cursor->rel_pos = BTR_PCUR_AFTER;
|
||||
|
||||
} else if (page_rec_is_infimum_low(offs)) {
|
||||
|
||||
rec = page_rec_get_next(rec);
|
||||
|
||||
cursor->rel_pos = BTR_PCUR_BEFORE;
|
||||
} else {
|
||||
cursor->rel_pos = BTR_PCUR_ON;
|
||||
}
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
cursor->old_rec = dict_index_copy_rec_order_prefix(
|
||||
index, rec, &cursor->old_n_fields,
|
||||
&cursor->old_rec_buf, &cursor->buf_size);
|
||||
|
||||
cursor->block_when_stored = block;
|
||||
cursor->modify_clock = buf_block_get_modify_clock(block);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Copies the stored position of a pcur to another pcur. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_copy_stored_position(
|
||||
/*==========================*/
|
||||
btr_pcur_t* pcur_receive, /* in: pcur which will receive the
|
||||
position info */
|
||||
btr_pcur_t* pcur_donate) /* in: pcur from which the info is
|
||||
copied */
|
||||
{
|
||||
if (pcur_receive->old_rec_buf) {
|
||||
mem_free(pcur_receive->old_rec_buf);
|
||||
}
|
||||
|
||||
ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t));
|
||||
|
||||
if (pcur_donate->old_rec_buf) {
|
||||
|
||||
pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size);
|
||||
|
||||
ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf,
|
||||
pcur_donate->buf_size);
|
||||
pcur_receive->old_rec = pcur_receive->old_rec_buf
|
||||
+ (pcur_donate->old_rec - pcur_donate->old_rec_buf);
|
||||
}
|
||||
|
||||
pcur_receive->old_n_fields = pcur_donate->old_n_fields;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Restores the stored position of a persistent cursor bufferfixing the page and
|
||||
obtaining the specified latches. If the cursor position was saved when the
|
||||
(1) cursor was positioned on a user record: this function restores the position
|
||||
to the last record LESS OR EQUAL to the stored record;
|
||||
(2) cursor was positioned on a page infimum record: restores the position to
|
||||
the last record LESS than the user record which was the successor of the page
|
||||
infimum;
|
||||
(3) cursor was positioned on the page supremum: restores to the first record
|
||||
GREATER than the user record which was the predecessor of the supremum.
|
||||
(4) cursor was positioned before the first or after the last in an empty tree:
|
||||
restores to before first or after the last in the tree. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_pcur_restore_position(
|
||||
/*======================*/
|
||||
/* out: TRUE if the cursor position
|
||||
was stored when it was on a user record
|
||||
and it can be restored on a user record
|
||||
whose ordering fields are identical to
|
||||
the ones of the original user record */
|
||||
ulint latch_mode, /* in: BTR_SEARCH_LEAF, ... */
|
||||
btr_pcur_t* cursor, /* in: detached persistent cursor */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
dict_index_t* index;
|
||||
dtuple_t* tuple;
|
||||
ulint mode;
|
||||
ulint old_mode;
|
||||
mem_heap_t* heap;
|
||||
|
||||
index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
|
||||
|
||||
if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
|
||||
|| UNIV_UNLIKELY(cursor->pos_state != BTR_PCUR_WAS_POSITIONED
|
||||
&& cursor->pos_state != BTR_PCUR_IS_POSITIONED)) {
|
||||
ut_print_buf(stderr, cursor, sizeof(btr_pcur_t));
|
||||
putc('\n', stderr);
|
||||
if (cursor->trx_if_known) {
|
||||
trx_print(stderr, cursor->trx_if_known, 0);
|
||||
}
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
(cursor->rel_pos == BTR_PCUR_AFTER_LAST_IN_TREE
|
||||
|| cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE)) {
|
||||
|
||||
/* In these cases we do not try an optimistic restoration,
|
||||
but always do a search */
|
||||
|
||||
btr_cur_open_at_index_side(
|
||||
cursor->rel_pos == BTR_PCUR_BEFORE_FIRST_IN_TREE,
|
||||
index, latch_mode, btr_pcur_get_btr_cur(cursor), mtr);
|
||||
|
||||
cursor->block_when_stored = btr_pcur_get_block(cursor);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ut_a(cursor->old_rec);
|
||||
ut_a(cursor->old_n_fields);
|
||||
|
||||
if (UNIV_LIKELY(latch_mode == BTR_SEARCH_LEAF)
|
||||
|| UNIV_LIKELY(latch_mode == BTR_MODIFY_LEAF)) {
|
||||
/* Try optimistic restoration */
|
||||
|
||||
if (UNIV_LIKELY(buf_page_optimistic_get(
|
||||
latch_mode,
|
||||
cursor->block_when_stored,
|
||||
cursor->modify_clock, mtr))) {
|
||||
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
|
||||
|
||||
buf_block_dbg_add_level(btr_pcur_get_block(cursor),
|
||||
SYNC_TREE_NODE);
|
||||
|
||||
if (cursor->rel_pos == BTR_PCUR_ON) {
|
||||
#ifdef UNIV_DEBUG
|
||||
const rec_t* rec;
|
||||
const ulint* offsets1;
|
||||
const ulint* offsets2;
|
||||
#endif /* UNIV_DEBUG */
|
||||
cursor->latch_mode = latch_mode;
|
||||
#ifdef UNIV_DEBUG
|
||||
rec = btr_pcur_get_rec(cursor);
|
||||
|
||||
heap = mem_heap_create(256);
|
||||
offsets1 = rec_get_offsets(
|
||||
cursor->old_rec, index, NULL,
|
||||
cursor->old_n_fields, &heap);
|
||||
offsets2 = rec_get_offsets(
|
||||
rec, index, NULL,
|
||||
cursor->old_n_fields, &heap);
|
||||
|
||||
ut_ad(!cmp_rec_rec(cursor->old_rec,
|
||||
rec, offsets1, offsets2,
|
||||
index));
|
||||
mem_heap_free(heap);
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* If optimistic restoration did not succeed, open the cursor anew */
|
||||
|
||||
heap = mem_heap_create(256);
|
||||
|
||||
tuple = dict_index_build_data_tuple(index, cursor->old_rec,
|
||||
cursor->old_n_fields, heap);
|
||||
|
||||
/* Save the old search mode of the cursor */
|
||||
old_mode = cursor->search_mode;
|
||||
|
||||
if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
|
||||
mode = PAGE_CUR_LE;
|
||||
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
|
||||
mode = PAGE_CUR_G;
|
||||
} else {
|
||||
ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
|
||||
mode = PAGE_CUR_L;
|
||||
}
|
||||
|
||||
btr_pcur_open_with_no_init(index, tuple, mode, latch_mode,
|
||||
cursor, 0, mtr);
|
||||
|
||||
/* Restore the old search mode */
|
||||
cursor->search_mode = old_mode;
|
||||
|
||||
if (cursor->rel_pos == BTR_PCUR_ON
|
||||
&& btr_pcur_is_on_user_rec(cursor)
|
||||
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(
|
||||
btr_pcur_get_rec(cursor), index,
|
||||
NULL, ULINT_UNDEFINED, &heap))) {
|
||||
|
||||
/* We have to store the NEW value for the modify clock, since
|
||||
the cursor can now be on a different page! But we can retain
|
||||
the value of old_rec */
|
||||
|
||||
cursor->block_when_stored = btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock = buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
/* We have to store new position information, modify_clock etc.,
|
||||
to the cursor because it can now be on a different page, the record
|
||||
under it may have been removed, etc. */
|
||||
|
||||
btr_pcur_store_position(cursor, mtr);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
|
||||
releases the page latch and bufferfix reserved by the cursor.
|
||||
NOTE! In the case of BTR_LEAF_MODIFY, there should not exist changes
|
||||
made by the current mini-transaction to the data protected by the
|
||||
cursor latch, as then the latch must not be released until mtr_commit. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_release_leaf(
|
||||
/*==================*/
|
||||
btr_pcur_t* cursor, /* in: persistent cursor */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
block = btr_pcur_get_block(cursor);
|
||||
|
||||
btr_leaf_page_release(block, cursor->latch_mode, mtr);
|
||||
|
||||
cursor->latch_mode = BTR_NO_LATCHES;
|
||||
|
||||
cursor->pos_state = BTR_PCUR_WAS_POSITIONED;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Moves the persistent cursor to the first record on the next page. Releases the
|
||||
latch on the current page, and bufferunfixes it. Note that there must not be
|
||||
modifications on the current page, as then the x-latch can be released only in
|
||||
mtr_commit. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_move_to_next_page(
|
||||
/*=======================*/
|
||||
btr_pcur_t* cursor, /* in: persistent cursor; must be on the
|
||||
last record of the current page */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
ulint next_page_no;
|
||||
ulint space;
|
||||
ulint zip_size;
|
||||
page_t* page;
|
||||
buf_block_t* next_block;
|
||||
page_t* next_page;
|
||||
|
||||
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
ut_ad(btr_pcur_is_after_last_on_page(cursor));
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
page = btr_pcur_get_page(cursor);
|
||||
next_page_no = btr_page_get_next(page, mtr);
|
||||
space = buf_block_get_space(btr_pcur_get_block(cursor));
|
||||
zip_size = buf_block_get_zip_size(btr_pcur_get_block(cursor));
|
||||
|
||||
ut_ad(next_page_no != FIL_NULL);
|
||||
|
||||
next_block = btr_block_get(space, zip_size, next_page_no,
|
||||
cursor->latch_mode, mtr);
|
||||
next_page = buf_block_get_frame(next_block);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
ut_a(page_is_comp(next_page) == page_is_comp(page));
|
||||
ut_a(btr_page_get_prev(next_page, mtr)
|
||||
== buf_block_get_page_no(btr_pcur_get_block(cursor)));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
next_block->check_index_page_at_flush = TRUE;
|
||||
|
||||
btr_leaf_page_release(btr_pcur_get_block(cursor),
|
||||
cursor->latch_mode, mtr);
|
||||
|
||||
page_cur_set_before_first(next_block, btr_pcur_get_page_cur(cursor));
|
||||
|
||||
page_check_dir(next_page);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Moves the persistent cursor backward if it is on the first record of the page.
|
||||
Commits mtr. Note that to prevent a possible deadlock, the operation
|
||||
first stores the position of the cursor, commits mtr, acquires the necessary
|
||||
latches and restores the cursor position again before returning. The
|
||||
alphabetical position of the cursor is guaranteed to be sensible on
|
||||
return, but it may happen that the cursor is not positioned on the last
|
||||
record of any page, because the structure of the tree may have changed
|
||||
during the time when the cursor had no latches. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_move_backward_from_page(
|
||||
/*=============================*/
|
||||
btr_pcur_t* cursor, /* in: persistent cursor, must be on the first
|
||||
record of the current page */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
ulint prev_page_no;
|
||||
ulint space;
|
||||
page_t* page;
|
||||
buf_block_t* prev_block;
|
||||
ulint latch_mode;
|
||||
ulint latch_mode2;
|
||||
|
||||
ut_a(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
ut_ad(btr_pcur_is_before_first_on_page(cursor));
|
||||
ut_ad(!btr_pcur_is_before_first_in_tree(cursor, mtr));
|
||||
|
||||
latch_mode = cursor->latch_mode;
|
||||
|
||||
if (latch_mode == BTR_SEARCH_LEAF) {
|
||||
|
||||
latch_mode2 = BTR_SEARCH_PREV;
|
||||
|
||||
} else if (latch_mode == BTR_MODIFY_LEAF) {
|
||||
|
||||
latch_mode2 = BTR_MODIFY_PREV;
|
||||
} else {
|
||||
latch_mode2 = 0; /* To eliminate compiler warning */
|
||||
ut_error;
|
||||
}
|
||||
|
||||
btr_pcur_store_position(cursor, mtr);
|
||||
|
||||
mtr_commit(mtr);
|
||||
|
||||
mtr_start(mtr);
|
||||
|
||||
btr_pcur_restore_position(latch_mode2, cursor, mtr);
|
||||
|
||||
page = btr_pcur_get_page(cursor);
|
||||
|
||||
prev_page_no = btr_page_get_prev(page, mtr);
|
||||
space = buf_block_get_space(btr_pcur_get_block(cursor));
|
||||
|
||||
if (prev_page_no == FIL_NULL) {
|
||||
} else if (btr_pcur_is_before_first_on_page(cursor)) {
|
||||
|
||||
prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
|
||||
|
||||
btr_leaf_page_release(btr_pcur_get_block(cursor),
|
||||
latch_mode, mtr);
|
||||
|
||||
page_cur_set_after_last(prev_block,
|
||||
btr_pcur_get_page_cur(cursor));
|
||||
} else {
|
||||
|
||||
/* The repositioned cursor did not end on an infimum record on
|
||||
a page. Cursor repositioning acquired a latch also on the
|
||||
previous page, but we do not need the latch: release it. */
|
||||
|
||||
prev_block = btr_pcur_get_btr_cur(cursor)->left_block;
|
||||
|
||||
btr_leaf_page_release(prev_block, latch_mode, mtr);
|
||||
}
|
||||
|
||||
cursor->latch_mode = latch_mode;
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Moves the persistent cursor to the previous record in the tree. If no records
|
||||
are left, the cursor stays 'before first in tree'. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_pcur_move_to_prev(
|
||||
/*==================*/
|
||||
/* out: TRUE if the cursor was not before first
|
||||
in tree */
|
||||
btr_pcur_t* cursor, /* in: persistent cursor; NOTE that the
|
||||
function may release the page latch */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
ut_ad(cursor->pos_state == BTR_PCUR_IS_POSITIONED);
|
||||
ut_ad(cursor->latch_mode != BTR_NO_LATCHES);
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
|
||||
|
||||
if (btr_pcur_is_before_first_on_page(cursor)) {
|
||||
|
||||
if (btr_pcur_is_before_first_in_tree(cursor, mtr)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
btr_pcur_move_backward_from_page(cursor, mtr);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
btr_pcur_move_to_prev_on_page(cursor);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
If mode is PAGE_CUR_G or PAGE_CUR_GE, opens a persistent cursor on the first
|
||||
user record satisfying the search condition, in the case PAGE_CUR_L or
|
||||
PAGE_CUR_LE, on the last user record. If no such user record exists, then
|
||||
in the first case sets the cursor after last in tree, and in the latter case
|
||||
before first in tree. The latching mode must be BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_open_on_user_rec(
|
||||
/*======================*/
|
||||
dict_index_t* index, /* in: index */
|
||||
const dtuple_t* tuple, /* in: tuple on which search done */
|
||||
ulint mode, /* in: PAGE_CUR_L, ... */
|
||||
ulint latch_mode, /* in: BTR_SEARCH_LEAF or
|
||||
BTR_MODIFY_LEAF */
|
||||
btr_pcur_t* cursor, /* in: memory buffer for persistent
|
||||
cursor */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr);
|
||||
|
||||
if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {
|
||||
|
||||
if (btr_pcur_is_after_last_on_page(cursor)) {
|
||||
|
||||
btr_pcur_move_to_next_user_rec(cursor, mtr);
|
||||
}
|
||||
} else {
|
||||
ut_ad((mode == PAGE_CUR_LE) || (mode == PAGE_CUR_L));
|
||||
|
||||
/* Not implemented yet */
|
||||
|
||||
ut_error;
|
||||
}
|
||||
}
|
1872
storage/xtradb/btr/btr0sea.c
Normal file
1872
storage/xtradb/btr/btr0sea.c
Normal file
File diff suppressed because it is too large
Load Diff
682
storage/xtradb/buf/buf0buddy.c
Normal file
682
storage/xtradb/buf/buf0buddy.c
Normal file
@ -0,0 +1,682 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
Binary buddy allocator for compressed pages
|
||||
|
||||
Created December 2006 by Marko Makela
|
||||
*******************************************************/
|
||||
|
||||
#define THIS_MODULE
|
||||
#include "buf0buddy.h"
|
||||
#ifdef UNIV_NONINL
|
||||
# include "buf0buddy.ic"
|
||||
#endif
|
||||
#undef THIS_MODULE
|
||||
#include "buf0buf.h"
|
||||
#include "buf0lru.h"
|
||||
#include "buf0flu.h"
|
||||
#include "page0zip.h"
|
||||
|
||||
/* Statistic counters */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Number of frames allocated from the buffer pool to the buddy system.
|
||||
Protected by buf_pool_mutex. */
|
||||
static ulint buf_buddy_n_frames;
|
||||
#endif /* UNIV_DEBUG */
|
||||
/** Statistics of the buddy system, indexed by block size.
|
||||
Protected by buf_pool_mutex. */
|
||||
UNIV_INTERN buf_buddy_stat_t buf_buddy_stat[BUF_BUDDY_SIZES + 1];
|
||||
|
||||
/**************************************************************************
|
||||
Get the offset of the buddy of a compressed page frame. */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
buf_buddy_get(
|
||||
/*==========*/
|
||||
/* out: the buddy relative of page */
|
||||
byte* page, /* in: compressed page */
|
||||
ulint size) /* in: page size in bytes */
|
||||
{
|
||||
ut_ad(ut_is_2pow(size));
|
||||
ut_ad(size >= BUF_BUDDY_LOW);
|
||||
ut_ad(size < BUF_BUDDY_HIGH);
|
||||
ut_ad(!ut_align_offset(page, size));
|
||||
|
||||
if (((ulint) page) & size) {
|
||||
return(page - size);
|
||||
} else {
|
||||
return(page + size);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Add a block to the head of the appropriate buddy free list. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_buddy_add_to_free(
|
||||
/*==================*/
|
||||
buf_page_t* bpage, /* in,own: block to be freed */
|
||||
ulint i) /* in: index of buf_pool->zip_free[] */
|
||||
{
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
buf_page_t* b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
|
||||
|
||||
if (b) UNIV_MEM_VALID(b, BUF_BUDDY_LOW << i);
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
ut_ad(buf_pool->zip_free[i].start != bpage);
|
||||
UT_LIST_ADD_FIRST(list, buf_pool->zip_free[i], bpage);
|
||||
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
if (b) UNIV_MEM_FREE(b, BUF_BUDDY_LOW << i);
|
||||
UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Remove a block from the appropriate buddy free list. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_buddy_remove_from_free(
|
||||
/*=======================*/
|
||||
buf_page_t* bpage, /* in: block to be removed */
|
||||
ulint i) /* in: index of buf_pool->zip_free[] */
|
||||
{
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
buf_page_t* prev = UT_LIST_GET_PREV(list, bpage);
|
||||
buf_page_t* next = UT_LIST_GET_NEXT(list, bpage);
|
||||
|
||||
if (prev) UNIV_MEM_VALID(prev, BUF_BUDDY_LOW << i);
|
||||
if (next) UNIV_MEM_VALID(next, BUF_BUDDY_LOW << i);
|
||||
|
||||
ut_ad(!prev || buf_page_get_state(prev) == BUF_BLOCK_ZIP_FREE);
|
||||
ut_ad(!next || buf_page_get_state(next) == BUF_BLOCK_ZIP_FREE);
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
UT_LIST_REMOVE(list, buf_pool->zip_free[i], bpage);
|
||||
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
if (prev) UNIV_MEM_FREE(prev, BUF_BUDDY_LOW << i);
|
||||
if (next) UNIV_MEM_FREE(next, BUF_BUDDY_LOW << i);
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Try to allocate a block from buf_pool->zip_free[]. */
|
||||
static
|
||||
void*
|
||||
buf_buddy_alloc_zip(
|
||||
/*================*/
|
||||
/* out: allocated block, or NULL
|
||||
if buf_pool->zip_free[] was empty */
|
||||
ulint i) /* in: index of buf_pool->zip_free[] */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_a(i < BUF_BUDDY_SIZES);
|
||||
|
||||
#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i]);
|
||||
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
|
||||
bpage = UT_LIST_GET_LAST(buf_pool->zip_free[i]);
|
||||
|
||||
if (bpage) {
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
|
||||
buf_buddy_remove_from_free(bpage, i);
|
||||
} else if (i + 1 < BUF_BUDDY_SIZES) {
|
||||
/* Attempt to split. */
|
||||
bpage = buf_buddy_alloc_zip(i + 1);
|
||||
|
||||
if (bpage) {
|
||||
buf_page_t* buddy = (buf_page_t*)
|
||||
(((char*) bpage) + (BUF_BUDDY_LOW << i));
|
||||
|
||||
ut_ad(!buf_pool_contains_zip(buddy));
|
||||
ut_d(memset(buddy, i, BUF_BUDDY_LOW << i));
|
||||
buddy->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_add_to_free(buddy, i);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (bpage) {
|
||||
memset(bpage, ~i, BUF_BUDDY_LOW << i);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i);
|
||||
|
||||
return(bpage);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Deallocate a buffer frame of UNIV_PAGE_SIZE. */
|
||||
static
|
||||
void
|
||||
buf_buddy_block_free(
|
||||
/*=================*/
|
||||
void* buf) /* in: buffer frame to deallocate */
|
||||
{
|
||||
const ulint fold = BUF_POOL_ZIP_FOLD_PTR(buf);
|
||||
buf_page_t* bpage;
|
||||
buf_block_t* block;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
|
||||
|
||||
HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
|
||||
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY
|
||||
&& bpage->in_zip_hash && !bpage->in_page_hash),
|
||||
((buf_block_t*) bpage)->frame == buf);
|
||||
ut_a(bpage);
|
||||
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY);
|
||||
ut_ad(!bpage->in_page_hash);
|
||||
ut_ad(bpage->in_zip_hash);
|
||||
ut_d(bpage->in_zip_hash = FALSE);
|
||||
HASH_DELETE(buf_page_t, hash, buf_pool->zip_hash, fold, bpage);
|
||||
|
||||
ut_d(memset(buf, 0, UNIV_PAGE_SIZE));
|
||||
UNIV_MEM_INVALID(buf, UNIV_PAGE_SIZE);
|
||||
|
||||
block = (buf_block_t*) bpage;
|
||||
mutex_enter(&block->mutex);
|
||||
buf_LRU_block_free_non_file_page(block);
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
ut_ad(buf_buddy_n_frames > 0);
|
||||
ut_d(buf_buddy_n_frames--);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Allocate a buffer block to the buddy allocator. */
|
||||
static
|
||||
void
|
||||
buf_buddy_block_register(
|
||||
/*=====================*/
|
||||
buf_block_t* block) /* in: buffer frame to allocate */
|
||||
{
|
||||
const ulint fold = BUF_POOL_ZIP_FOLD(block);
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
|
||||
buf_block_set_state(block, BUF_BLOCK_MEMORY);
|
||||
|
||||
ut_a(block->frame);
|
||||
ut_a(!ut_align_offset(block->frame, UNIV_PAGE_SIZE));
|
||||
|
||||
ut_ad(!block->page.in_page_hash);
|
||||
ut_ad(!block->page.in_zip_hash);
|
||||
ut_d(block->page.in_zip_hash = TRUE);
|
||||
HASH_INSERT(buf_page_t, hash, buf_pool->zip_hash, fold, &block->page);
|
||||
|
||||
ut_d(buf_buddy_n_frames++);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Allocate a block from a bigger object. */
|
||||
static
|
||||
void*
|
||||
buf_buddy_alloc_from(
|
||||
/*=================*/
|
||||
/* out: allocated block */
|
||||
void* buf, /* in: a block that is free to use */
|
||||
ulint i, /* in: index of buf_pool->zip_free[] */
|
||||
ulint j) /* in: size of buf as an index
|
||||
of buf_pool->zip_free[] */
|
||||
{
|
||||
ulint offs = BUF_BUDDY_LOW << j;
|
||||
ut_ad(j <= BUF_BUDDY_SIZES);
|
||||
ut_ad(j >= i);
|
||||
ut_ad(!ut_align_offset(buf, offs));
|
||||
|
||||
/* Add the unused parts of the block to the free lists. */
|
||||
while (j > i) {
|
||||
buf_page_t* bpage;
|
||||
|
||||
offs >>= 1;
|
||||
j--;
|
||||
|
||||
bpage = (buf_page_t*) ((byte*) buf + offs);
|
||||
ut_d(memset(bpage, j, BUF_BUDDY_LOW << j));
|
||||
bpage->state = BUF_BLOCK_ZIP_FREE;
|
||||
#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[j]);
|
||||
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
|
||||
buf_buddy_add_to_free(bpage, j);
|
||||
}
|
||||
|
||||
return(buf);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Allocate a block. The thread calling this function must hold
|
||||
buf_pool_mutex and must not hold buf_pool_zip_mutex or any block->mutex.
|
||||
The buf_pool_mutex may only be released and reacquired if lru != NULL. */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
buf_buddy_alloc_low(
|
||||
/*================*/
|
||||
/* out: allocated block,
|
||||
possibly NULL if lru==NULL */
|
||||
ulint i, /* in: index of buf_pool->zip_free[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
ibool* lru) /* in: pointer to a variable that will be assigned
|
||||
TRUE if storage was allocated from the LRU list
|
||||
and buf_pool_mutex was temporarily released,
|
||||
or NULL if the LRU list should not be used */
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
|
||||
if (i < BUF_BUDDY_SIZES) {
|
||||
/* Try to allocate from the buddy system. */
|
||||
block = buf_buddy_alloc_zip(i);
|
||||
|
||||
if (block) {
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try allocating from the buf_pool->free list. */
|
||||
block = buf_LRU_get_free_only();
|
||||
|
||||
if (block) {
|
||||
|
||||
goto alloc_big;
|
||||
}
|
||||
|
||||
if (!lru) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Try replacing an uncompressed page in the buffer pool. */
|
||||
buf_pool_mutex_exit();
|
||||
block = buf_LRU_get_free_block(0);
|
||||
*lru = TRUE;
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
alloc_big:
|
||||
buf_buddy_block_register(block);
|
||||
|
||||
block = buf_buddy_alloc_from(block->frame, i, BUF_BUDDY_SIZES);
|
||||
|
||||
func_exit:
|
||||
buf_buddy_stat[i].used++;
|
||||
return(block);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Try to relocate the control block of a compressed page. */
|
||||
static
|
||||
ibool
|
||||
buf_buddy_relocate_block(
|
||||
/*=====================*/
|
||||
/* out: TRUE if relocated */
|
||||
buf_page_t* bpage, /* in: block to relocate */
|
||||
buf_page_t* dpage) /* in: free block to relocate to */
|
||||
{
|
||||
buf_page_t* b;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
|
||||
switch (buf_page_get_state(bpage)) {
|
||||
case BUF_BLOCK_ZIP_FREE:
|
||||
case BUF_BLOCK_NOT_USED:
|
||||
case BUF_BLOCK_READY_FOR_USE:
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
case BUF_BLOCK_MEMORY:
|
||||
case BUF_BLOCK_REMOVE_HASH:
|
||||
ut_error;
|
||||
case BUF_BLOCK_ZIP_DIRTY:
|
||||
/* Cannot relocate dirty pages. */
|
||||
return(FALSE);
|
||||
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_enter(&buf_pool_zip_mutex);
|
||||
|
||||
if (!buf_page_can_relocate(bpage)) {
|
||||
mutex_exit(&buf_pool_zip_mutex);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
buf_relocate(bpage, dpage);
|
||||
ut_d(bpage->state = BUF_BLOCK_ZIP_FREE);
|
||||
|
||||
/* relocate buf_pool->zip_clean */
|
||||
b = UT_LIST_GET_PREV(list, dpage);
|
||||
UT_LIST_REMOVE(list, buf_pool->zip_clean, dpage);
|
||||
|
||||
if (b) {
|
||||
UT_LIST_INSERT_AFTER(list, buf_pool->zip_clean, b, dpage);
|
||||
} else {
|
||||
UT_LIST_ADD_FIRST(list, buf_pool->zip_clean, dpage);
|
||||
}
|
||||
|
||||
mutex_exit(&buf_pool_zip_mutex);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Try to relocate a block. */
|
||||
static
|
||||
ibool
|
||||
buf_buddy_relocate(
|
||||
/*===============*/
|
||||
/* out: TRUE if relocated */
|
||||
void* src, /* in: block to relocate */
|
||||
void* dst, /* in: free block to relocate to */
|
||||
ulint i) /* in: index of buf_pool->zip_free[] */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
const ulint size = BUF_BUDDY_LOW << i;
|
||||
ullint usec = ut_time_us(NULL);
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(!ut_align_offset(src, size));
|
||||
ut_ad(!ut_align_offset(dst, size));
|
||||
UNIV_MEM_ASSERT_W(dst, size);
|
||||
|
||||
/* We assume that all memory from buf_buddy_alloc()
|
||||
is used for either compressed pages or buf_page_t
|
||||
objects covering compressed pages. */
|
||||
|
||||
/* We look inside the allocated objects returned by
|
||||
buf_buddy_alloc() and assume that anything of
|
||||
PAGE_ZIP_MIN_SIZE or larger is a compressed page that contains
|
||||
a valid space_id and page_no in the page header. Should the
|
||||
fields be invalid, we will be unable to relocate the block.
|
||||
We also assume that anything that fits sizeof(buf_page_t)
|
||||
actually is a properly initialized buf_page_t object. */
|
||||
|
||||
if (size >= PAGE_ZIP_MIN_SIZE) {
|
||||
/* This is a compressed page. */
|
||||
mutex_t* mutex;
|
||||
|
||||
/* The src block may be split into smaller blocks,
|
||||
some of which may be free. Thus, the
|
||||
mach_read_from_4() calls below may attempt to read
|
||||
from free memory. The memory is "owned" by the buddy
|
||||
allocator (and it has been allocated from the buffer
|
||||
pool), so there is nothing wrong about this. The
|
||||
mach_read_from_4() calls here will only trigger bogus
|
||||
Valgrind memcheck warnings in UNIV_DEBUG_VALGRIND builds. */
|
||||
bpage = buf_page_hash_get(
|
||||
mach_read_from_4((const byte*) src
|
||||
+ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
|
||||
mach_read_from_4((const byte*) src
|
||||
+ FIL_PAGE_OFFSET));
|
||||
|
||||
if (!bpage || bpage->zip.data != src) {
|
||||
/* The block has probably been freshly
|
||||
allocated by buf_LRU_get_free_block() but not
|
||||
added to buf_pool->page_hash yet. Obviously,
|
||||
it cannot be relocated. */
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (page_zip_get_size(&bpage->zip) != size) {
|
||||
/* The block is of different size. We would
|
||||
have to relocate all blocks covered by src.
|
||||
For the sake of simplicity, give up. */
|
||||
ut_ad(page_zip_get_size(&bpage->zip) < size);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/* The block must have been allocated, but it may
|
||||
contain uninitialized data. */
|
||||
UNIV_MEM_ASSERT_W(src, size);
|
||||
|
||||
mutex = buf_page_get_mutex(bpage);
|
||||
|
||||
mutex_enter(mutex);
|
||||
|
||||
if (buf_page_can_relocate(bpage)) {
|
||||
/* Relocate the compressed page. */
|
||||
ut_a(bpage->zip.data == src);
|
||||
memcpy(dst, src, size);
|
||||
bpage->zip.data = dst;
|
||||
mutex_exit(mutex);
|
||||
success:
|
||||
UNIV_MEM_INVALID(src, size);
|
||||
{
|
||||
buf_buddy_stat_t* buddy_stat
|
||||
= &buf_buddy_stat[i];
|
||||
buddy_stat->relocated++;
|
||||
buddy_stat->relocated_usec
|
||||
+= ut_time_us(NULL) - usec;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
mutex_exit(mutex);
|
||||
} else if (i == buf_buddy_get_slot(sizeof(buf_page_t))) {
|
||||
/* This must be a buf_page_t object. */
|
||||
UNIV_MEM_ASSERT_RW(src, size);
|
||||
if (buf_buddy_relocate_block(src, dst)) {
|
||||
|
||||
goto success;
|
||||
}
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Deallocate a block. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_buddy_free_low(
|
||||
/*===============*/
|
||||
void* buf, /* in: block to be freed, must not be
|
||||
pointed to by the buffer pool */
|
||||
ulint i) /* in: index of buf_pool->zip_free[] */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
buf_page_t* buddy;
|
||||
|
||||
ut_ad(buf_pool_mutex_own());
|
||||
ut_ad(!mutex_own(&buf_pool_zip_mutex));
|
||||
ut_ad(i <= BUF_BUDDY_SIZES);
|
||||
ut_ad(buf_buddy_stat[i].used > 0);
|
||||
|
||||
buf_buddy_stat[i].used--;
|
||||
recombine:
|
||||
UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i);
|
||||
ut_d(((buf_page_t*) buf)->state = BUF_BLOCK_ZIP_FREE);
|
||||
|
||||
if (i == BUF_BUDDY_SIZES) {
|
||||
buf_buddy_block_free(buf);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_ad(i < BUF_BUDDY_SIZES);
|
||||
ut_ad(buf == ut_align_down(buf, BUF_BUDDY_LOW << i));
|
||||
ut_ad(!buf_pool_contains_zip(buf));
|
||||
|
||||
/* Try to combine adjacent blocks. */
|
||||
|
||||
buddy = (buf_page_t*) buf_buddy_get(((byte*) buf), BUF_BUDDY_LOW << i);
|
||||
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
|
||||
if (buddy->state != BUF_BLOCK_ZIP_FREE) {
|
||||
|
||||
goto buddy_nonfree;
|
||||
}
|
||||
|
||||
/* The field buddy->state can only be trusted for free blocks.
|
||||
If buddy->state == BUF_BLOCK_ZIP_FREE, the block is free if
|
||||
it is in the free list. */
|
||||
#endif /* !UNIV_DEBUG_VALGRIND */
|
||||
|
||||
for (bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); bpage; ) {
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
|
||||
if (bpage == buddy) {
|
||||
buddy_free:
|
||||
/* The buddy is free: recombine */
|
||||
buf_buddy_remove_from_free(bpage, i);
|
||||
buddy_free2:
|
||||
ut_ad(buf_page_get_state(buddy) == BUF_BLOCK_ZIP_FREE);
|
||||
ut_ad(!buf_pool_contains_zip(buddy));
|
||||
i++;
|
||||
buf = ut_align_down(buf, BUF_BUDDY_LOW << i);
|
||||
|
||||
goto recombine;
|
||||
}
|
||||
|
||||
ut_a(bpage != buf);
|
||||
|
||||
{
|
||||
buf_page_t* next = UT_LIST_GET_NEXT(list, bpage);
|
||||
UNIV_MEM_ASSERT_AND_FREE(bpage, BUF_BUDDY_LOW << i);
|
||||
bpage = next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
buddy_nonfree:
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i]));
|
||||
#endif /* UNIV_DEBUG_VALGRIND */
|
||||
|
||||
/* The buddy is not free. Is there a free block of this size? */
|
||||
bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
|
||||
|
||||
if (bpage) {
|
||||
/* Remove the block from the free list, because a successful
|
||||
buf_buddy_relocate() will overwrite bpage->list. */
|
||||
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
buf_buddy_remove_from_free(bpage, i);
|
||||
|
||||
/* Try to relocate the buddy of buf to the free block. */
|
||||
if (buf_buddy_relocate(buddy, bpage, i)) {
|
||||
|
||||
ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
|
||||
goto buddy_free2;
|
||||
}
|
||||
|
||||
buf_buddy_add_to_free(bpage, i);
|
||||
|
||||
/* Try to relocate the buddy of the free block to buf. */
|
||||
buddy = (buf_page_t*) buf_buddy_get(((byte*) bpage),
|
||||
BUF_BUDDY_LOW << i);
|
||||
|
||||
#if defined UNIV_DEBUG && !defined UNIV_DEBUG_VALGRIND
|
||||
{
|
||||
const buf_page_t* b;
|
||||
|
||||
/* The buddy must not be (completely) free, because
|
||||
we always recombine adjacent free blocks.
|
||||
(Parts of the buddy can be free in
|
||||
buf_pool->zip_free[j] with j < i.)*/
|
||||
for (b = UT_LIST_GET_FIRST(buf_pool->zip_free[i]);
|
||||
b; b = UT_LIST_GET_NEXT(list, b)) {
|
||||
|
||||
ut_a(b != buddy);
|
||||
}
|
||||
}
|
||||
#endif /* UNIV_DEBUG && !UNIV_DEBUG_VALGRIND */
|
||||
|
||||
if (buf_buddy_relocate(buddy, buf, i)) {
|
||||
|
||||
buf = bpage;
|
||||
UNIV_MEM_VALID(bpage, BUF_BUDDY_LOW << i);
|
||||
ut_d(buddy->state = BUF_BLOCK_ZIP_FREE);
|
||||
goto buddy_free;
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the block to the buddy list. */
|
||||
bpage = buf;
|
||||
#ifdef UNIV_DEBUG
|
||||
if (i < buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)) {
|
||||
/* This area has most likely been allocated for at
|
||||
least one compressed-only block descriptor. Check
|
||||
that there are no live objects in the area. This is
|
||||
not a complete check: it may yield false positives as
|
||||
well as false negatives. Also, due to buddy blocks
|
||||
being recombined, it is possible (although unlikely)
|
||||
that this branch is never reached. */
|
||||
|
||||
char* c;
|
||||
|
||||
# ifndef UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing
|
||||
uninitialized memory. Besides, Valgrind performs a
|
||||
more exhaustive check, at every memory access. */
|
||||
const buf_page_t* b = buf;
|
||||
const buf_page_t* const b_end = (buf_page_t*)
|
||||
((char*) b + (BUF_BUDDY_LOW << i));
|
||||
|
||||
for (; b < b_end; b++) {
|
||||
/* Avoid false positives (and cause false
|
||||
negatives) by checking for b->space < 1000. */
|
||||
|
||||
if ((b->state == BUF_BLOCK_ZIP_PAGE
|
||||
|| b->state == BUF_BLOCK_ZIP_DIRTY)
|
||||
&& b->space > 0 && b->space < 1000) {
|
||||
fprintf(stderr,
|
||||
"buddy dirty %p %u (%u,%u) %p,%lu\n",
|
||||
(void*) b,
|
||||
b->state, b->space, b->offset,
|
||||
buf, i);
|
||||
}
|
||||
}
|
||||
# endif /* !UNIV_DEBUG_VALGRIND */
|
||||
|
||||
/* Scramble the block. This should make any pointers
|
||||
invalid and trigger a segmentation violation. Because
|
||||
the scrambling can be reversed, it may be possible to
|
||||
track down the object pointing to the freed data by
|
||||
dereferencing the unscrambled bpage->LRU or
|
||||
bpage->list pointers. */
|
||||
for (c = (char*) buf + (BUF_BUDDY_LOW << i);
|
||||
c-- > (char*) buf; ) {
|
||||
*c = ~*c ^ i;
|
||||
}
|
||||
} else {
|
||||
/* Fill large blocks with a constant pattern. */
|
||||
memset(bpage, i, BUF_BUDDY_LOW << i);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
bpage->state = BUF_BLOCK_ZIP_FREE;
|
||||
buf_buddy_add_to_free(bpage, i);
|
||||
}
|
3920
storage/xtradb/buf/buf0buf.c
Normal file
3920
storage/xtradb/buf/buf0buf.c
Normal file
File diff suppressed because it is too large
Load Diff
1277
storage/xtradb/buf/buf0flu.c
Normal file
1277
storage/xtradb/buf/buf0flu.c
Normal file
File diff suppressed because it is too large
Load Diff
2060
storage/xtradb/buf/buf0lru.c
Normal file
2060
storage/xtradb/buf/buf0lru.c
Normal file
File diff suppressed because it is too large
Load Diff
818
storage/xtradb/buf/buf0rea.c
Normal file
818
storage/xtradb/buf/buf0rea.c
Normal file
@ -0,0 +1,818 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
The database buffer read
|
||||
|
||||
Created 11/5/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "buf0rea.h"
|
||||
|
||||
#include "fil0fil.h"
|
||||
#include "mtr0mtr.h"
|
||||
|
||||
#include "buf0buf.h"
|
||||
#include "buf0flu.h"
|
||||
#include "buf0lru.h"
|
||||
#include "ibuf0ibuf.h"
|
||||
#include "log0recv.h"
|
||||
#include "trx0sys.h"
|
||||
#include "os0file.h"
|
||||
#include "srv0start.h"
|
||||
|
||||
extern ulint srv_read_ahead;
|
||||
extern ulint srv_read_ahead_rnd;
|
||||
extern ulint srv_read_ahead_seq;
|
||||
extern ulint srv_buf_pool_reads;
|
||||
|
||||
/* The size in blocks of the area where the random read-ahead algorithm counts
|
||||
the accessed pages when deciding whether to read-ahead */
|
||||
#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA
|
||||
|
||||
/* There must be at least this many pages in buf_pool in the area to start
|
||||
a random read-ahead */
|
||||
#define BUF_READ_AHEAD_RANDOM_THRESHOLD (5 + buf_read_ahead_random_area / 8)
|
||||
|
||||
/* The linear read-ahead area size */
|
||||
#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
|
||||
|
||||
/* The linear read-ahead threshold */
|
||||
#define LINEAR_AREA_THRESHOLD_COEF 5 / 8
|
||||
|
||||
/* If there are buf_pool->curr_size per the number below pending reads, then
|
||||
read-ahead is not done: this is to prevent flooding the buffer pool with
|
||||
i/o-fixed buffer blocks */
|
||||
#define BUF_READ_AHEAD_PEND_LIMIT 2
|
||||
|
||||
/************************************************************************
|
||||
Low-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there, in which case does nothing.
|
||||
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
|
||||
flag is cleared and the x-lock released by an i/o-handler thread. */
|
||||
static
|
||||
ulint
|
||||
buf_read_page_low(
|
||||
/*==============*/
|
||||
/* out: 1 if a read request was queued, 0 if the page
|
||||
already resided in buf_pool, or if the page is in
|
||||
the doublewrite buffer blocks in which case it is never
|
||||
read into the pool, or if the tablespace does not
|
||||
exist or is being dropped */
|
||||
ulint* err, /* out: DB_SUCCESS or DB_TABLESPACE_DELETED if we are
|
||||
trying to read from a non-existent tablespace, or a
|
||||
tablespace which is just now being dropped */
|
||||
ibool sync, /* in: TRUE if synchronous aio is desired */
|
||||
ulint mode, /* in: BUF_READ_IBUF_PAGES_ONLY, ...,
|
||||
ORed to OS_AIO_SIMULATED_WAKE_LATER (see below
|
||||
at read-ahead functions) */
|
||||
ulint space, /* in: space id */
|
||||
ulint zip_size,/* in: compressed page size, or 0 */
|
||||
ibool unzip, /* in: TRUE=request uncompressed page */
|
||||
ib_int64_t tablespace_version, /* in: if the space memory object has
|
||||
this timestamp different from what we are giving here,
|
||||
treat the tablespace as dropped; this is a timestamp we
|
||||
use to stop dangling page reads from a tablespace
|
||||
which we have DISCARDed + IMPORTed back */
|
||||
ulint offset) /* in: page number */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ulint wake_later;
|
||||
|
||||
*err = DB_SUCCESS;
|
||||
|
||||
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
|
||||
mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
|
||||
|
||||
if (trx_doublewrite && space == TRX_SYS_SPACE
|
||||
&& ( (offset >= trx_doublewrite->block1
|
||||
&& offset < trx_doublewrite->block1
|
||||
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
|
||||
|| (offset >= trx_doublewrite->block2
|
||||
&& offset < trx_doublewrite->block2
|
||||
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE))) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Warning: trying to read"
|
||||
" doublewrite buffer page %lu\n",
|
||||
(ulong) offset);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (ibuf_bitmap_page(zip_size, offset)
|
||||
|| trx_sys_hdr_page(space, offset)) {
|
||||
|
||||
/* Trx sys header is so low in the latching order that we play
|
||||
safe and do not leave the i/o-completion to an asynchronous
|
||||
i/o-thread. Ibuf bitmap pages must always be read with
|
||||
syncronous i/o, to make sure they do not get involved in
|
||||
thread deadlocks. */
|
||||
|
||||
sync = TRUE;
|
||||
}
|
||||
|
||||
/* The following call will also check if the tablespace does not exist
|
||||
or is being dropped; if we succeed in initing the page in the buffer
|
||||
pool for read, then DISCARD cannot proceed until the read has
|
||||
completed */
|
||||
bpage = buf_page_init_for_read(err, mode, space, zip_size, unzip,
|
||||
tablespace_version, offset);
|
||||
if (bpage == NULL) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Posting read request for page %lu, sync %lu\n",
|
||||
(ulong) offset,
|
||||
(ulong) sync);
|
||||
}
|
||||
#endif
|
||||
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
|
||||
if (zip_size) {
|
||||
*err = fil_io(OS_FILE_READ | wake_later,
|
||||
sync, space, zip_size, offset, 0, zip_size,
|
||||
bpage->zip.data, bpage);
|
||||
} else {
|
||||
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
*err = fil_io(OS_FILE_READ | wake_later,
|
||||
sync, space, 0, offset, 0, UNIV_PAGE_SIZE,
|
||||
((buf_block_t*) bpage)->frame, bpage);
|
||||
}
|
||||
ut_a(*err == DB_SUCCESS);
|
||||
|
||||
if (sync) {
|
||||
/* The i/o is already completed when we arrive from
|
||||
fil_read */
|
||||
buf_page_io_complete(bpage);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Applies a random read-ahead in buf_pool if there are at least a threshold
|
||||
value of accessed pages from the random read-ahead area. Does not read any
|
||||
page, not even the one at the position (space, offset), if the read-ahead
|
||||
mechanism is not activated. NOTE 1: the calling thread may own latches on
|
||||
pages: to avoid deadlocks this function must be written such that it cannot
|
||||
end up waiting for these latches! NOTE 2: the calling thread must want
|
||||
access to the page given: this rule is set to prevent unintended read-aheads
|
||||
performed by ibuf routines, a situation which could result in a deadlock if
|
||||
the OS does not support asynchronous i/o. */
|
||||
static
|
||||
ulint
|
||||
buf_read_ahead_random(
|
||||
/*==================*/
|
||||
/* out: number of page read requests issued; NOTE
|
||||
that if we read ibuf pages, it may happen that
|
||||
the page at the given page number does not get
|
||||
read even if we return a value > 0! */
|
||||
ulint space, /* in: space id */
|
||||
ulint zip_size,/* in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /* in: page number of a page which the current thread
|
||||
wants to access */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint recent_blocks = 0;
|
||||
ulint count;
|
||||
ulint LRU_recent_limit;
|
||||
ulint ibuf_mode;
|
||||
ulint low, high;
|
||||
ulint err;
|
||||
ulint i;
|
||||
ulint buf_read_ahead_random_area;
|
||||
|
||||
if (!(srv_read_ahead & 1)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (srv_startup_is_before_trx_rollback_phase) {
|
||||
/* No read-ahead to avoid thread deadlocks */
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (ibuf_bitmap_page(zip_size, offset)
|
||||
|| trx_sys_hdr_page(space, offset)) {
|
||||
|
||||
/* If it is an ibuf bitmap page or trx sys hdr, we do
|
||||
no read-ahead, as that could break the ibuf page access
|
||||
order */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Remember the tablespace version before we ask te tablespace size
|
||||
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
|
||||
do not try to read outside the bounds of the tablespace! */
|
||||
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
buf_read_ahead_random_area = BUF_READ_AHEAD_RANDOM_AREA;
|
||||
|
||||
low = (offset / buf_read_ahead_random_area)
|
||||
* buf_read_ahead_random_area;
|
||||
high = (offset / buf_read_ahead_random_area + 1)
|
||||
* buf_read_ahead_random_area;
|
||||
if (high > fil_space_get_size(space)) {
|
||||
|
||||
high = fil_space_get_size(space);
|
||||
}
|
||||
|
||||
/* Get the minimum LRU_position field value for an initial segment
|
||||
of the LRU list, to determine which blocks have recently been added
|
||||
to the start of the list. */
|
||||
|
||||
LRU_recent_limit = buf_LRU_get_recent_limit();
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
if (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Count how many blocks in the area have been recently accessed,
|
||||
that is, reside near the start of the LRU list. */
|
||||
|
||||
for (i = low; i < high; i++) {
|
||||
const buf_page_t* bpage = buf_page_hash_get(space, i);
|
||||
|
||||
if (bpage
|
||||
&& buf_page_is_accessed(bpage)
|
||||
&& (buf_page_get_LRU_position(bpage) > LRU_recent_limit)) {
|
||||
|
||||
recent_blocks++;
|
||||
|
||||
if (recent_blocks >= BUF_READ_AHEAD_RANDOM_THRESHOLD) {
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
goto read_ahead;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
/* Do nothing */
|
||||
return(0);
|
||||
|
||||
read_ahead:
|
||||
/* Read all the suitable blocks within the area */
|
||||
|
||||
if (ibuf_inside()) {
|
||||
ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
|
||||
} else {
|
||||
ibuf_mode = BUF_READ_ANY_PAGE;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
||||
for (i = low; i < high; i++) {
|
||||
/* It is only sensible to do read-ahead in the non-sync aio
|
||||
mode: hence FALSE as the first parameter */
|
||||
|
||||
if (!ibuf_bitmap_page(zip_size, i)) {
|
||||
count += buf_read_page_low(
|
||||
&err, FALSE,
|
||||
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, FALSE,
|
||||
tablespace_version, i);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Warning: in random"
|
||||
" readahead trying to access\n"
|
||||
"InnoDB: tablespace %lu page %lu,\n"
|
||||
"InnoDB: but the tablespace does not"
|
||||
" exist or is just being dropped.\n",
|
||||
(ulong) space, (ulong) i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In simulated aio we wake the aio handler threads only after
|
||||
queuing all aio requests, in native aio the following call does
|
||||
nothing: */
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && (count > 0)) {
|
||||
fprintf(stderr,
|
||||
"Random read-ahead space %lu offset %lu pages %lu\n",
|
||||
(ulong) space, (ulong) offset,
|
||||
(ulong) count);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
++srv_read_ahead_rnd;
|
||||
return(count);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
High-level function which reads a page asynchronously from a file to the
|
||||
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
|
||||
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
|
||||
released by the i/o-handler thread. Does a random read-ahead if it seems
|
||||
sensible. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
/* out: number of page read requests issued: this can
|
||||
be > 1 if read-ahead occurred */
|
||||
ulint space, /* in: space id */
|
||||
ulint zip_size,/* in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /* in: page number */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
ulint count2;
|
||||
ulint err;
|
||||
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
count = buf_read_ahead_random(space, zip_size, offset);
|
||||
|
||||
/* We do the i/o in the synchronous aio mode to save thread
|
||||
switches: hence TRUE */
|
||||
|
||||
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, FALSE,
|
||||
tablespace_version, offset);
|
||||
srv_buf_pool_reads+= count2;
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: trying to access"
|
||||
" tablespace %lu page no. %lu,\n"
|
||||
"InnoDB: but the tablespace does not exist"
|
||||
" or is just being dropped.\n",
|
||||
(ulong) space, (ulong) offset);
|
||||
}
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin(FALSE);
|
||||
|
||||
/* Increment number of I/O operations used for LRU policy. */
|
||||
buf_LRU_stat_inc_io();
|
||||
|
||||
return(count + count2);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Applies linear read-ahead if in the buf_pool the page is a border page of
|
||||
a linear read-ahead area and all the pages in the area have been accessed.
|
||||
Does not read any page if the read-ahead mechanism is not activated. Note
|
||||
that the the algorithm looks at the 'natural' adjacent successor and
|
||||
predecessor of the page, which on the leaf level of a B-tree are the next
|
||||
and previous page in the chain of leaves. To know these, the page specified
|
||||
in (space, offset) must already be present in the buf_pool. Thus, the
|
||||
natural way to use this function is to call it when a page in the buf_pool
|
||||
is accessed the first time, calling this function just after it has been
|
||||
bufferfixed.
|
||||
NOTE 1: as this function looks at the natural predecessor and successor
|
||||
fields on the page, what happens, if these are not initialized to any
|
||||
sensible value? No problem, before applying read-ahead we check that the
|
||||
area to read is within the span of the space, if not, read-ahead is not
|
||||
applied. An uninitialized value may result in a useless read operation, but
|
||||
only very improbably.
|
||||
NOTE 2: the calling thread may own latches on pages: to avoid deadlocks this
|
||||
function must be written such that it cannot end up waiting for these
|
||||
latches!
|
||||
NOTE 3: the calling thread must want access to the page given: this rule is
|
||||
set to prevent unintended read-aheads performed by ibuf routines, a situation
|
||||
which could result in a deadlock if the OS does not support asynchronous io. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_read_ahead_linear(
|
||||
/*==================*/
|
||||
/* out: number of page read requests issued */
|
||||
ulint space, /* in: space id */
|
||||
ulint zip_size,/* in: compressed page size in bytes, or 0 */
|
||||
ulint offset) /* in: page number of a page; NOTE: the current thread
|
||||
must want access to this page (see NOTE 3 above) */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
buf_page_t* bpage;
|
||||
buf_frame_t* frame;
|
||||
buf_page_t* pred_bpage = NULL;
|
||||
ulint pred_offset;
|
||||
ulint succ_offset;
|
||||
ulint count;
|
||||
int asc_or_desc;
|
||||
ulint new_offset;
|
||||
ulint fail_count;
|
||||
ulint ibuf_mode;
|
||||
ulint low, high;
|
||||
ulint err;
|
||||
ulint i;
|
||||
const ulint buf_read_ahead_linear_area
|
||||
= BUF_READ_AHEAD_LINEAR_AREA;
|
||||
|
||||
if (!(srv_read_ahead & 2)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY(srv_startup_is_before_trx_rollback_phase)) {
|
||||
/* No read-ahead to avoid thread deadlocks */
|
||||
return(0);
|
||||
}
|
||||
|
||||
low = (offset / buf_read_ahead_linear_area)
|
||||
* buf_read_ahead_linear_area;
|
||||
high = (offset / buf_read_ahead_linear_area + 1)
|
||||
* buf_read_ahead_linear_area;
|
||||
|
||||
if ((offset != low) && (offset != high - 1)) {
|
||||
/* This is not a border page of the area: return */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (ibuf_bitmap_page(zip_size, offset)
|
||||
|| trx_sys_hdr_page(space, offset)) {
|
||||
|
||||
/* If it is an ibuf bitmap page or trx sys hdr, we do
|
||||
no read-ahead, as that could break the ibuf page access
|
||||
order */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Remember the tablespace version before we ask te tablespace size
|
||||
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
|
||||
do not try to read outside the bounds of the tablespace! */
|
||||
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
buf_pool_mutex_enter();
|
||||
|
||||
if (high > fil_space_get_size(space)) {
|
||||
buf_pool_mutex_exit();
|
||||
/* The area is not whole, return */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check that almost all pages in the area have been accessed; if
|
||||
offset == low, the accesses must be in a descending order, otherwise,
|
||||
in an ascending order. */
|
||||
|
||||
asc_or_desc = 1;
|
||||
|
||||
if (offset == low) {
|
||||
asc_or_desc = -1;
|
||||
}
|
||||
|
||||
fail_count = 0;
|
||||
|
||||
for (i = low; i < high; i++) {
|
||||
bpage = buf_page_hash_get(space, i);
|
||||
|
||||
if ((bpage == NULL) || !buf_page_is_accessed(bpage)) {
|
||||
/* Not accessed */
|
||||
fail_count++;
|
||||
|
||||
} else if (pred_bpage
|
||||
&& (ut_ulint_cmp(
|
||||
buf_page_get_LRU_position(bpage),
|
||||
buf_page_get_LRU_position(pred_bpage))
|
||||
!= asc_or_desc)) {
|
||||
/* Accesses not in the right order */
|
||||
|
||||
fail_count++;
|
||||
pred_bpage = bpage;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail_count > buf_read_ahead_linear_area
|
||||
* LINEAR_AREA_THRESHOLD_COEF) {
|
||||
/* Too many failures: return */
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* If we got this far, we know that enough pages in the area have
|
||||
been accessed in the right order: linear read-ahead can be sensible */
|
||||
|
||||
bpage = buf_page_hash_get(space, offset);
|
||||
|
||||
if (bpage == NULL) {
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
switch (buf_page_get_state(bpage)) {
|
||||
case BUF_BLOCK_ZIP_PAGE:
|
||||
frame = bpage->zip.data;
|
||||
break;
|
||||
case BUF_BLOCK_FILE_PAGE:
|
||||
frame = ((buf_block_t*) bpage)->frame;
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read the natural predecessor and successor page addresses from
|
||||
the page; NOTE that because the calling thread may have an x-latch
|
||||
on the page, we do not acquire an s-latch on the page, this is to
|
||||
prevent deadlocks. Even if we read values which are nonsense, the
|
||||
algorithm will work. */
|
||||
|
||||
pred_offset = fil_page_get_prev(frame);
|
||||
succ_offset = fil_page_get_next(frame);
|
||||
|
||||
buf_pool_mutex_exit();
|
||||
|
||||
if ((offset == low) && (succ_offset == offset + 1)) {
|
||||
|
||||
/* This is ok, we can continue */
|
||||
new_offset = pred_offset;
|
||||
|
||||
} else if ((offset == high - 1) && (pred_offset == offset - 1)) {
|
||||
|
||||
/* This is ok, we can continue */
|
||||
new_offset = succ_offset;
|
||||
} else {
|
||||
/* Successor or predecessor not in the right order */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
low = (new_offset / buf_read_ahead_linear_area)
|
||||
* buf_read_ahead_linear_area;
|
||||
high = (new_offset / buf_read_ahead_linear_area + 1)
|
||||
* buf_read_ahead_linear_area;
|
||||
|
||||
if ((new_offset != low) && (new_offset != high - 1)) {
|
||||
/* This is not a border page of the area: return */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (high > fil_space_get_size(space)) {
|
||||
/* The area is not whole, return */
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* If we got this far, read-ahead can be sensible: do it */
|
||||
|
||||
if (ibuf_inside()) {
|
||||
ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
|
||||
} else {
|
||||
ibuf_mode = BUF_READ_ANY_PAGE;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
||||
/* Since Windows XP seems to schedule the i/o handler thread
|
||||
very eagerly, and consequently it does not wait for the
|
||||
full read batch to be posted, we use special heuristics here */
|
||||
|
||||
os_aio_simulated_put_read_threads_to_sleep();
|
||||
|
||||
for (i = low; i < high; i++) {
|
||||
/* It is only sensible to do read-ahead in the non-sync
|
||||
aio mode: hence FALSE as the first parameter */
|
||||
|
||||
if (!ibuf_bitmap_page(zip_size, i)) {
|
||||
count += buf_read_page_low(
|
||||
&err, FALSE,
|
||||
ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, FALSE, tablespace_version, i);
|
||||
if (err == DB_TABLESPACE_DELETED) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Warning: in"
|
||||
" linear readahead trying to access\n"
|
||||
"InnoDB: tablespace %lu page %lu,\n"
|
||||
"InnoDB: but the tablespace does not"
|
||||
" exist or is just being dropped.\n",
|
||||
(ulong) space, (ulong) i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* In simulated aio we wake the aio handler threads only after
|
||||
queuing all aio requests, in native aio the following call does
|
||||
nothing: */
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin(FALSE);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints && (count > 0)) {
|
||||
fprintf(stderr,
|
||||
"LINEAR read-ahead space %lu offset %lu pages %lu\n",
|
||||
(ulong) space, (ulong) offset, (ulong) count);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* Read ahead is considered one I/O operation for the purpose of
|
||||
LRU policy decision. */
|
||||
buf_LRU_stat_inc_io();
|
||||
|
||||
++srv_read_ahead_seq;
|
||||
return(count);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Issues read requests for pages which the ibuf module wants to read in, in
|
||||
order to contract the insert buffer tree. Technically, this function is like
|
||||
a read-ahead function. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_read_ibuf_merge_pages(
|
||||
/*======================*/
|
||||
ibool sync, /* in: TRUE if the caller
|
||||
wants this function to wait
|
||||
for the highest address page
|
||||
to get read in, before this
|
||||
function returns */
|
||||
const ulint* space_ids, /* in: array of space ids */
|
||||
const ib_int64_t* space_versions,/* in: the spaces must have
|
||||
this version number
|
||||
(timestamp), otherwise we
|
||||
discard the read; we use this
|
||||
to cancel reads if DISCARD +
|
||||
IMPORT may have changed the
|
||||
tablespace size */
|
||||
const ulint* page_nos, /* in: array of page numbers
|
||||
to read, with the highest page
|
||||
number the last in the
|
||||
array */
|
||||
ulint n_stored) /* in: number of elements
|
||||
in the arrays */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_ad(!ibuf_inside());
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ut_a(n_stored < UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
while (buf_pool->n_pend_reads
|
||||
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
|
||||
os_thread_sleep(500000);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_stored; i++) {
|
||||
ulint zip_size = fil_space_get_zip_size(space_ids[i]);
|
||||
ulint err;
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
|
||||
|
||||
goto tablespace_deleted;
|
||||
}
|
||||
|
||||
buf_read_page_low(&err, sync && (i + 1 == n_stored),
|
||||
BUF_READ_ANY_PAGE, space_ids[i],
|
||||
zip_size, TRUE, space_versions[i],
|
||||
page_nos[i]);
|
||||
|
||||
if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) {
|
||||
tablespace_deleted:
|
||||
/* We have deleted or are deleting the single-table
|
||||
tablespace: remove the entries for that page */
|
||||
|
||||
ibuf_merge_or_delete_for_page(NULL, space_ids[i],
|
||||
page_nos[i],
|
||||
zip_size, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin(FALSE);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Ibuf merge read-ahead space %lu pages %lu\n",
|
||||
(ulong) space_ids[0], (ulong) n_stored);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Issues read requests for pages which recovery wants to read in. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_read_recv_pages(
|
||||
/*================*/
|
||||
ibool sync, /* in: TRUE if the caller
|
||||
wants this function to wait
|
||||
for the highest address page
|
||||
to get read in, before this
|
||||
function returns */
|
||||
ulint space, /* in: space id */
|
||||
ulint zip_size, /* in: compressed page size in
|
||||
bytes, or 0 */
|
||||
const ulint* page_nos, /* in: array of page numbers
|
||||
to read, with the highest page
|
||||
number the last in the
|
||||
array */
|
||||
ulint n_stored) /* in: number of page numbers
|
||||
in the array */
|
||||
{
|
||||
ib_int64_t tablespace_version;
|
||||
ulint count;
|
||||
ulint err;
|
||||
ulint i;
|
||||
|
||||
zip_size = fil_space_get_zip_size(space);
|
||||
tablespace_version = fil_space_get_version(space);
|
||||
|
||||
for (i = 0; i < n_stored; i++) {
|
||||
|
||||
count = 0;
|
||||
|
||||
os_aio_print_debug = FALSE;
|
||||
|
||||
while (buf_pool->n_pend_reads >= recv_n_pool_free_frames / 2) {
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
os_thread_sleep(500000);
|
||||
|
||||
count++;
|
||||
|
||||
if (count > 100) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: InnoDB has waited for"
|
||||
" 50 seconds for pending\n"
|
||||
"InnoDB: reads to the buffer pool to"
|
||||
" be finished.\n"
|
||||
"InnoDB: Number of pending reads %lu,"
|
||||
" pending pread calls %lu\n",
|
||||
(ulong) buf_pool->n_pend_reads,
|
||||
(ulong)os_file_n_pending_preads);
|
||||
|
||||
os_aio_print_debug = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
os_aio_print_debug = FALSE;
|
||||
|
||||
if ((i + 1 == n_stored) && sync) {
|
||||
buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
|
||||
zip_size, TRUE, tablespace_version,
|
||||
page_nos[i]);
|
||||
} else {
|
||||
buf_read_page_low(&err, FALSE, BUF_READ_ANY_PAGE
|
||||
| OS_AIO_SIMULATED_WAKE_LATER,
|
||||
space, zip_size, TRUE,
|
||||
tablespace_version, page_nos[i]);
|
||||
}
|
||||
}
|
||||
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* Flush pages from the end of the LRU list if necessary */
|
||||
buf_flush_free_margin(FALSE);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Recovery applies read-ahead pages %lu\n",
|
||||
(ulong) n_stored);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
758
storage/xtradb/data/data0data.c
Normal file
758
storage/xtradb/data/data0data.c
Normal file
@ -0,0 +1,758 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
SQL data field and tuple
|
||||
|
||||
Created 5/30/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "data0data.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "data0data.ic"
|
||||
#endif
|
||||
|
||||
#include "rem0rec.h"
|
||||
#include "rem0cmp.h"
|
||||
#include "page0page.h"
|
||||
#include "page0zip.h"
|
||||
#include "dict0dict.h"
|
||||
#include "btr0cur.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/* data pointers of tuple fields are initialized to point here
|
||||
for error checking */
|
||||
UNIV_INTERN byte data_error;
|
||||
|
||||
# ifndef UNIV_DEBUG_VALGRIND
|
||||
/* this is used to fool the compiler in dtuple_validate */
|
||||
UNIV_INTERN ulint data_dummy;
|
||||
# endif /* !UNIV_DEBUG_VALGRIND */
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*************************************************************************
|
||||
Tests if dfield data length and content is equal to the given. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dfield_data_is_binary_equal(
|
||||
/*========================*/
|
||||
/* out: TRUE if equal */
|
||||
const dfield_t* field, /* in: field */
|
||||
ulint len, /* in: data length or UNIV_SQL_NULL */
|
||||
const byte* data) /* in: data */
|
||||
{
|
||||
if (len != dfield_get_len(field)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (0 != memcmp(dfield_get_data(field), data, len)) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Compare two data tuples, respecting the collation of character fields. */
|
||||
UNIV_INTERN
|
||||
int
|
||||
dtuple_coll_cmp(
|
||||
/*============*/
|
||||
/* out: 1, 0 , -1 if tuple1 is greater, equal,
|
||||
less, respectively, than tuple2 */
|
||||
const dtuple_t* tuple1, /* in: tuple 1 */
|
||||
const dtuple_t* tuple2) /* in: tuple 2 */
|
||||
{
|
||||
ulint n_fields;
|
||||
ulint i;
|
||||
|
||||
ut_ad(tuple1 && tuple2);
|
||||
ut_ad(tuple1->magic_n == DATA_TUPLE_MAGIC_N);
|
||||
ut_ad(tuple2->magic_n == DATA_TUPLE_MAGIC_N);
|
||||
ut_ad(dtuple_check_typed(tuple1));
|
||||
ut_ad(dtuple_check_typed(tuple2));
|
||||
|
||||
n_fields = dtuple_get_n_fields(tuple1);
|
||||
|
||||
if (n_fields != dtuple_get_n_fields(tuple2)) {
|
||||
|
||||
return(n_fields < dtuple_get_n_fields(tuple2) ? -1 : 1);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
int cmp;
|
||||
const dfield_t* field1 = dtuple_get_nth_field(tuple1, i);
|
||||
const dfield_t* field2 = dtuple_get_nth_field(tuple2, i);
|
||||
|
||||
cmp = cmp_dfield_dfield(field1, field2);
|
||||
|
||||
if (cmp) {
|
||||
return(cmp);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Sets number of fields used in a tuple. Normally this is set in
|
||||
dtuple_create, but if you want later to set it smaller, you can use this. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtuple_set_n_fields(
|
||||
/*================*/
|
||||
dtuple_t* tuple, /* in: tuple */
|
||||
ulint n_fields) /* in: number of fields */
|
||||
{
|
||||
ut_ad(tuple);
|
||||
|
||||
tuple->n_fields = n_fields;
|
||||
tuple->n_fields_cmp = n_fields;
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Checks that a data field is typed. */
|
||||
static
|
||||
ibool
|
||||
dfield_check_typed_no_assert(
|
||||
/*=========================*/
|
||||
/* out: TRUE if ok */
|
||||
const dfield_t* field) /* in: data field */
|
||||
{
|
||||
if (dfield_get_type(field)->mtype > DATA_MYSQL
|
||||
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: data field type %lu, len %lu\n",
|
||||
(ulong) dfield_get_type(field)->mtype,
|
||||
(ulong) dfield_get_len(field));
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Checks that a data tuple is typed. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_check_typed_no_assert(
|
||||
/*=========================*/
|
||||
/* out: TRUE if ok */
|
||||
const dtuple_t* tuple) /* in: tuple */
|
||||
{
|
||||
const dfield_t* field;
|
||||
ulint i;
|
||||
|
||||
if (dtuple_get_n_fields(tuple) > REC_MAX_N_FIELDS) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: index entry has %lu fields\n",
|
||||
(ulong) dtuple_get_n_fields(tuple));
|
||||
dump:
|
||||
fputs("InnoDB: Tuple contents: ", stderr);
|
||||
dtuple_print(stderr, tuple);
|
||||
putc('\n', stderr);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
|
||||
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
|
||||
if (!dfield_check_typed_no_assert(field)) {
|
||||
goto dump;
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Checks that a data field is typed. Asserts an error if not. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dfield_check_typed(
|
||||
/*===============*/
|
||||
/* out: TRUE if ok */
|
||||
const dfield_t* field) /* in: data field */
|
||||
{
|
||||
if (dfield_get_type(field)->mtype > DATA_MYSQL
|
||||
|| dfield_get_type(field)->mtype < DATA_VARCHAR) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: data field type %lu, len %lu\n",
|
||||
(ulong) dfield_get_type(field)->mtype,
|
||||
(ulong) dfield_get_len(field));
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
Checks that a data tuple is typed. Asserts an error if not. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_check_typed(
|
||||
/*===============*/
|
||||
/* out: TRUE if ok */
|
||||
const dtuple_t* tuple) /* in: tuple */
|
||||
{
|
||||
const dfield_t* field;
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < dtuple_get_n_fields(tuple); i++) {
|
||||
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
|
||||
ut_a(dfield_check_typed(field));
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**************************************************************
|
||||
Validates the consistency of a tuple which must be complete, i.e,
|
||||
all fields must have been set. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_validate(
|
||||
/*============*/
|
||||
/* out: TRUE if ok */
|
||||
const dtuple_t* tuple) /* in: tuple */
|
||||
{
|
||||
const dfield_t* field;
|
||||
ulint n_fields;
|
||||
ulint len;
|
||||
ulint i;
|
||||
|
||||
ut_ad(tuple->magic_n == DATA_TUPLE_MAGIC_N);
|
||||
|
||||
n_fields = dtuple_get_n_fields(tuple);
|
||||
|
||||
/* We dereference all the data of each field to test
|
||||
for memory traps */
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
|
||||
field = dtuple_get_nth_field(tuple, i);
|
||||
len = dfield_get_len(field);
|
||||
|
||||
if (!dfield_is_null(field)) {
|
||||
|
||||
const byte* data = dfield_get_data(field);
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
ulint j;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
|
||||
data_dummy += *data; /* fool the compiler not
|
||||
to optimize out this
|
||||
code */
|
||||
data++;
|
||||
}
|
||||
#endif /* !UNIV_DEBUG_VALGRIND */
|
||||
|
||||
UNIV_MEM_ASSERT_RW(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
ut_a(dtuple_check_typed(tuple));
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/*****************************************************************
|
||||
Pretty prints a dfield value according to its data type. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dfield_print(
|
||||
/*=========*/
|
||||
const dfield_t* dfield) /* in: dfield */
|
||||
{
|
||||
const byte* data;
|
||||
ulint len;
|
||||
ulint i;
|
||||
|
||||
len = dfield_get_len(dfield);
|
||||
data = dfield_get_data(dfield);
|
||||
|
||||
if (dfield_is_null(dfield)) {
|
||||
fputs("NULL", stderr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dtype_get_mtype(dfield_get_type(dfield))) {
|
||||
case DATA_CHAR:
|
||||
case DATA_VARCHAR:
|
||||
for (i = 0; i < len; i++) {
|
||||
int c = *data++;
|
||||
putc(isprint(c) ? c : ' ', stderr);
|
||||
}
|
||||
|
||||
if (dfield_is_ext(dfield)) {
|
||||
fputs("(external)", stderr);
|
||||
}
|
||||
break;
|
||||
case DATA_INT:
|
||||
ut_a(len == 4); /* only works for 32-bit integers */
|
||||
fprintf(stderr, "%d", (int)mach_read_from_4(data));
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Pretty prints a dfield value according to its data type. Also the hex string
|
||||
is printed if a string contains non-printable characters. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dfield_print_also_hex(
|
||||
/*==================*/
|
||||
const dfield_t* dfield) /* in: dfield */
|
||||
{
|
||||
const byte* data;
|
||||
ulint len;
|
||||
ulint prtype;
|
||||
ulint i;
|
||||
ibool print_also_hex;
|
||||
|
||||
len = dfield_get_len(dfield);
|
||||
data = dfield_get_data(dfield);
|
||||
|
||||
if (dfield_is_null(dfield)) {
|
||||
fputs("NULL", stderr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
prtype = dtype_get_prtype(dfield_get_type(dfield));
|
||||
|
||||
switch (dtype_get_mtype(dfield_get_type(dfield))) {
|
||||
dulint id;
|
||||
case DATA_INT:
|
||||
switch (len) {
|
||||
ulint val;
|
||||
case 1:
|
||||
val = mach_read_from_1(data);
|
||||
|
||||
if (!(prtype & DATA_UNSIGNED)) {
|
||||
val &= ~0x80;
|
||||
fprintf(stderr, "%ld", (long) val);
|
||||
} else {
|
||||
fprintf(stderr, "%lu", (ulong) val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
val = mach_read_from_2(data);
|
||||
|
||||
if (!(prtype & DATA_UNSIGNED)) {
|
||||
val &= ~0x8000;
|
||||
fprintf(stderr, "%ld", (long) val);
|
||||
} else {
|
||||
fprintf(stderr, "%lu", (ulong) val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
val = mach_read_from_3(data);
|
||||
|
||||
if (!(prtype & DATA_UNSIGNED)) {
|
||||
val &= ~0x800000;
|
||||
fprintf(stderr, "%ld", (long) val);
|
||||
} else {
|
||||
fprintf(stderr, "%lu", (ulong) val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4:
|
||||
val = mach_read_from_4(data);
|
||||
|
||||
if (!(prtype & DATA_UNSIGNED)) {
|
||||
val &= ~0x80000000;
|
||||
fprintf(stderr, "%ld", (long) val);
|
||||
} else {
|
||||
fprintf(stderr, "%lu", (ulong) val);
|
||||
}
|
||||
break;
|
||||
|
||||
case 6:
|
||||
id = mach_read_from_6(data);
|
||||
fprintf(stderr, "{%lu %lu}",
|
||||
ut_dulint_get_high(id),
|
||||
ut_dulint_get_low(id));
|
||||
break;
|
||||
|
||||
case 7:
|
||||
id = mach_read_from_7(data);
|
||||
fprintf(stderr, "{%lu %lu}",
|
||||
ut_dulint_get_high(id),
|
||||
ut_dulint_get_low(id));
|
||||
break;
|
||||
case 8:
|
||||
id = mach_read_from_8(data);
|
||||
fprintf(stderr, "{%lu %lu}",
|
||||
ut_dulint_get_high(id),
|
||||
ut_dulint_get_low(id));
|
||||
break;
|
||||
default:
|
||||
goto print_hex;
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_SYS:
|
||||
switch (prtype & DATA_SYS_PRTYPE_MASK) {
|
||||
case DATA_TRX_ID:
|
||||
id = mach_read_from_6(data);
|
||||
|
||||
fprintf(stderr, "trx_id " TRX_ID_FMT,
|
||||
TRX_ID_PREP_PRINTF(id));
|
||||
break;
|
||||
|
||||
case DATA_ROLL_PTR:
|
||||
id = mach_read_from_7(data);
|
||||
|
||||
fprintf(stderr, "roll_ptr {%lu %lu}",
|
||||
ut_dulint_get_high(id), ut_dulint_get_low(id));
|
||||
break;
|
||||
|
||||
case DATA_ROW_ID:
|
||||
id = mach_read_from_6(data);
|
||||
|
||||
fprintf(stderr, "row_id {%lu %lu}",
|
||||
ut_dulint_get_high(id), ut_dulint_get_low(id));
|
||||
break;
|
||||
|
||||
default:
|
||||
id = mach_dulint_read_compressed(data);
|
||||
|
||||
fprintf(stderr, "mix_id {%lu %lu}",
|
||||
ut_dulint_get_high(id), ut_dulint_get_low(id));
|
||||
}
|
||||
break;
|
||||
|
||||
case DATA_CHAR:
|
||||
case DATA_VARCHAR:
|
||||
print_also_hex = FALSE;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int c = *data++;
|
||||
|
||||
if (!isprint(c)) {
|
||||
print_also_hex = TRUE;
|
||||
|
||||
fprintf(stderr, "\\x%02x", (unsigned char) c);
|
||||
} else {
|
||||
putc(c, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
if (dfield_is_ext(dfield)) {
|
||||
fputs("(external)", stderr);
|
||||
}
|
||||
|
||||
if (!print_also_hex) {
|
||||
break;
|
||||
}
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
/* fall through */
|
||||
|
||||
case DATA_BINARY:
|
||||
default:
|
||||
print_hex:
|
||||
fputs(" Hex: ",stderr);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
fprintf(stderr, "%02lx", (ulint) *data++);
|
||||
}
|
||||
|
||||
if (dfield_is_ext(dfield)) {
|
||||
fputs("(external)", stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Print a dfield value using ut_print_buf. */
|
||||
static
|
||||
void
|
||||
dfield_print_raw(
|
||||
/*=============*/
|
||||
FILE* f, /* in: output stream */
|
||||
const dfield_t* dfield) /* in: dfield */
|
||||
{
|
||||
ulint len = dfield_get_len(dfield);
|
||||
if (!dfield_is_null(dfield)) {
|
||||
ulint print_len = ut_min(len, 1000);
|
||||
ut_print_buf(f, dfield_get_data(dfield), print_len);
|
||||
if (len != print_len) {
|
||||
fprintf(f, "(total %lu bytes%s)",
|
||||
(ulong) len,
|
||||
dfield_is_ext(dfield) ? ", external" : "");
|
||||
}
|
||||
} else {
|
||||
fputs(" SQL NULL", f);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
The following function prints the contents of a tuple. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtuple_print(
|
||||
/*=========*/
|
||||
FILE* f, /* in: output stream */
|
||||
const dtuple_t* tuple) /* in: tuple */
|
||||
{
|
||||
ulint n_fields;
|
||||
ulint i;
|
||||
|
||||
n_fields = dtuple_get_n_fields(tuple);
|
||||
|
||||
fprintf(f, "DATA TUPLE: %lu fields;\n", (ulong) n_fields);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
fprintf(f, " %lu:", (ulong) i);
|
||||
|
||||
dfield_print_raw(f, dtuple_get_nth_field(tuple, i));
|
||||
|
||||
putc(';', f);
|
||||
putc('\n', f);
|
||||
}
|
||||
|
||||
ut_ad(dtuple_validate(tuple));
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Moves parts of long fields in entry to the big record vector so that
|
||||
the size of tuple drops below the maximum record size allowed in the
|
||||
database. Moves data only from those fields which are not necessary
|
||||
to determine uniquely the insertion place of the tuple in the index. */
|
||||
UNIV_INTERN
|
||||
big_rec_t*
|
||||
dtuple_convert_big_rec(
|
||||
/*===================*/
|
||||
/* out, own: created big record vector,
|
||||
NULL if we are not able to shorten
|
||||
the entry enough, i.e., if there are
|
||||
too many fixed-length or short fields
|
||||
in entry or the index is clustered */
|
||||
dict_index_t* index, /* in: index */
|
||||
dtuple_t* entry, /* in/out: index entry */
|
||||
ulint* n_ext) /* in/out: number of
|
||||
externally stored columns */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
big_rec_t* vector;
|
||||
dfield_t* dfield;
|
||||
dict_field_t* ifield;
|
||||
ulint size;
|
||||
ulint n_fields;
|
||||
ulint local_len;
|
||||
ulint local_prefix_len;
|
||||
|
||||
if (UNIV_UNLIKELY(!dict_index_is_clust(index))) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) {
|
||||
/* up to MySQL 5.1: store a 768-byte prefix locally */
|
||||
local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN;
|
||||
} else {
|
||||
/* new-format table: do not store any BLOB prefix locally */
|
||||
local_len = BTR_EXTERN_FIELD_REF_SIZE;
|
||||
}
|
||||
|
||||
ut_a(dtuple_check_typed_no_assert(entry));
|
||||
|
||||
size = rec_get_converted_size(index, entry, *n_ext);
|
||||
|
||||
if (UNIV_UNLIKELY(size > 1000000000)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: tuple size very big: %lu\n",
|
||||
(ulong) size);
|
||||
fputs("InnoDB: Tuple contents: ", stderr);
|
||||
dtuple_print(stderr, entry);
|
||||
putc('\n', stderr);
|
||||
}
|
||||
|
||||
heap = mem_heap_create(size + dtuple_get_n_fields(entry)
|
||||
* sizeof(big_rec_field_t) + 1000);
|
||||
|
||||
vector = mem_heap_alloc(heap, sizeof(big_rec_t));
|
||||
|
||||
vector->heap = heap;
|
||||
vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry)
|
||||
* sizeof(big_rec_field_t));
|
||||
|
||||
/* Decide which fields to shorten: the algorithm is to look for
|
||||
a variable-length field that yields the biggest savings when
|
||||
stored externally */
|
||||
|
||||
n_fields = 0;
|
||||
|
||||
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
|
||||
*n_ext),
|
||||
dict_table_is_comp(index->table),
|
||||
dict_index_get_n_fields(index),
|
||||
dict_table_zip_size(index->table))) {
|
||||
ulint i;
|
||||
ulint longest = 0;
|
||||
ulint longest_i = ULINT_MAX;
|
||||
byte* data;
|
||||
big_rec_field_t* b;
|
||||
|
||||
for (i = dict_index_get_n_unique_in_tree(index);
|
||||
i < dtuple_get_n_fields(entry); i++) {
|
||||
ulint savings;
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, i);
|
||||
ifield = dict_index_get_nth_field(index, i);
|
||||
|
||||
/* Skip fixed-length, NULL, externally stored,
|
||||
or short columns */
|
||||
|
||||
if (ifield->fixed_len
|
||||
|| dfield_is_null(dfield)
|
||||
|| dfield_is_ext(dfield)
|
||||
|| dfield_get_len(dfield) <= local_len
|
||||
|| dfield_get_len(dfield)
|
||||
<= BTR_EXTERN_FIELD_REF_SIZE * 2) {
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
savings = dfield_get_len(dfield) - local_len;
|
||||
|
||||
/* Check that there would be savings */
|
||||
if (longest >= savings) {
|
||||
goto skip_field;
|
||||
}
|
||||
|
||||
longest_i = i;
|
||||
longest = savings;
|
||||
|
||||
skip_field:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!longest) {
|
||||
/* Cannot shorten more */
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Move data from field longest_i to big rec vector.
|
||||
|
||||
We store the first bytes locally to the record. Then
|
||||
we can calculate all ordering fields in all indexes
|
||||
from locally stored data. */
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, longest_i);
|
||||
ifield = dict_index_get_nth_field(index, longest_i);
|
||||
local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
||||
b = &vector->fields[n_fields];
|
||||
b->field_no = longest_i;
|
||||
b->len = dfield_get_len(dfield) - local_prefix_len;
|
||||
b->data = (char*) dfield_get_data(dfield) + local_prefix_len;
|
||||
|
||||
/* Allocate the locally stored part of the column. */
|
||||
data = mem_heap_alloc(heap, local_len);
|
||||
|
||||
/* Copy the local prefix. */
|
||||
memcpy(data, dfield_get_data(dfield), local_prefix_len);
|
||||
/* Clear the extern field reference (BLOB pointer). */
|
||||
memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE);
|
||||
#if 0
|
||||
/* The following would fail the Valgrind checks in
|
||||
page_cur_insert_rec_low() and page_cur_insert_rec_zip().
|
||||
The BLOB pointers in the record will be initialized after
|
||||
the record and the BLOBs have been written. */
|
||||
UNIV_MEM_ALLOC(data + local_prefix_len,
|
||||
BTR_EXTERN_FIELD_REF_SIZE);
|
||||
#endif
|
||||
|
||||
dfield_set_data(dfield, data, local_len);
|
||||
dfield_set_ext(dfield);
|
||||
|
||||
n_fields++;
|
||||
(*n_ext)++;
|
||||
ut_ad(n_fields < dtuple_get_n_fields(entry));
|
||||
}
|
||||
|
||||
vector->n_fields = n_fields;
|
||||
return(vector);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
Puts back to entry the data stored in vector. Note that to ensure the
|
||||
fields in entry can accommodate the data, vector must have been created
|
||||
from entry with dtuple_convert_big_rec. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtuple_convert_back_big_rec(
|
||||
/*========================*/
|
||||
dict_index_t* index __attribute__((unused)), /* in: index */
|
||||
dtuple_t* entry, /* in: entry whose data was put to vector */
|
||||
big_rec_t* vector) /* in, own: big rec vector; it is
|
||||
freed in this function */
|
||||
{
|
||||
big_rec_field_t* b = vector->fields;
|
||||
const big_rec_field_t* const end = b + vector->n_fields;
|
||||
|
||||
for (; b < end; b++) {
|
||||
dfield_t* dfield;
|
||||
ulint local_len;
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, b->field_no);
|
||||
local_len = dfield_get_len(dfield);
|
||||
|
||||
ut_ad(dfield_is_ext(dfield));
|
||||
ut_ad(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
|
||||
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
||||
ut_ad(local_len <= DICT_MAX_INDEX_COL_LEN);
|
||||
|
||||
dfield_set_data(dfield,
|
||||
(char*) b->data - local_len,
|
||||
b->len + local_len);
|
||||
}
|
||||
|
||||
mem_heap_free(vector->heap);
|
||||
}
|
300
storage/xtradb/data/data0type.c
Normal file
300
storage/xtradb/data/data0type.c
Normal file
@ -0,0 +1,300 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
Data types
|
||||
|
||||
Created 1/16/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "data0type.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "data0type.ic"
|
||||
#endif
|
||||
|
||||
/**********************************************************************
|
||||
This function is used to find the storage length in bytes of the first n
|
||||
characters for prefix indexes using a multibyte character set. The function
|
||||
finds charset information and returns length of prefix_len characters in the
|
||||
index field in bytes.
|
||||
|
||||
NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
|
||||
this function, you MUST change also the prototype here! */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
innobase_get_at_most_n_mbchars(
|
||||
/*===========================*/
|
||||
/* out: number of bytes occupied by the first
|
||||
n characters */
|
||||
ulint charset_id, /* in: character set id */
|
||||
ulint prefix_len, /* in: prefix length in bytes of the index
|
||||
(this has to be divided by mbmaxlen to get the
|
||||
number of CHARACTERS n in the prefix) */
|
||||
ulint data_len, /* in: length of the string in bytes */
|
||||
const char* str); /* in: character string */
|
||||
|
||||
/* At the database startup we store the default-charset collation number of
|
||||
this MySQL installation to this global variable. If we have < 4.1.2 format
|
||||
column definitions, or records in the insert buffer, we use this
|
||||
charset-collation code for them. */
|
||||
|
||||
UNIV_INTERN ulint data_mysql_default_charset_coll;
|
||||
|
||||
/*************************************************************************
|
||||
Determine how many bytes the first n characters of the given string occupy.
|
||||
If the string is shorter than n characters, returns the number of bytes
|
||||
the characters in the string occupy. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dtype_get_at_most_n_mbchars(
|
||||
/*========================*/
|
||||
/* out: length of the prefix,
|
||||
in bytes */
|
||||
ulint prtype, /* in: precise type */
|
||||
ulint mbminlen, /* in: minimum length of a
|
||||
multi-byte character */
|
||||
ulint mbmaxlen, /* in: maximum length of a
|
||||
multi-byte character */
|
||||
ulint prefix_len, /* in: length of the requested
|
||||
prefix, in characters, multiplied by
|
||||
dtype_get_mbmaxlen(dtype) */
|
||||
ulint data_len, /* in: length of str (in bytes) */
|
||||
const char* str) /* in: the string whose prefix
|
||||
length is being determined */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ut_a(data_len != UNIV_SQL_NULL);
|
||||
ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen));
|
||||
|
||||
if (mbminlen != mbmaxlen) {
|
||||
ut_a(!(prefix_len % mbmaxlen));
|
||||
return(innobase_get_at_most_n_mbchars(
|
||||
dtype_get_charset_coll(prtype),
|
||||
prefix_len, data_len, str));
|
||||
}
|
||||
|
||||
if (prefix_len < data_len) {
|
||||
|
||||
return(prefix_len);
|
||||
|
||||
}
|
||||
|
||||
return(data_len);
|
||||
#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;
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks if a data main type is a string type. Also a BLOB is considered a
|
||||
string type. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_string_type(
|
||||
/*=================*/
|
||||
/* out: TRUE if string type */
|
||||
ulint mtype) /* in: InnoDB main data type code: DATA_CHAR, ... */
|
||||
{
|
||||
if (mtype <= DATA_BLOB
|
||||
|| mtype == DATA_MYSQL
|
||||
|| mtype == DATA_VARMYSQL) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks if a type is a binary string type. Note that for tables created with
|
||||
< 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. For
|
||||
those DATA_BLOB columns this function currently returns FALSE. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_binary_string_type(
|
||||
/*========================*/
|
||||
/* out: TRUE if binary string type */
|
||||
ulint mtype, /* in: main data type */
|
||||
ulint prtype) /* in: precise type */
|
||||
{
|
||||
if ((mtype == DATA_FIXBINARY)
|
||||
|| (mtype == DATA_BINARY)
|
||||
|| (mtype == DATA_BLOB && (prtype & DATA_BINARY_TYPE))) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks if a type is a non-binary string type. That is, dtype_is_string_type is
|
||||
TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created
|
||||
with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column.
|
||||
For those DATA_BLOB columns this function currently returns TRUE. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_non_binary_string_type(
|
||||
/*============================*/
|
||||
/* out: TRUE if non-binary string type */
|
||||
ulint mtype, /* in: main data type */
|
||||
ulint prtype) /* in: precise type */
|
||||
{
|
||||
if (dtype_is_string_type(mtype) == TRUE
|
||||
&& dtype_is_binary_string_type(mtype, prtype) == FALSE) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Forms a precise type from the < 4.1.2 format precise type plus the
|
||||
charset-collation code. */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dtype_form_prtype(
|
||||
/*==============*/
|
||||
ulint old_prtype, /* in: the MySQL type code and the flags
|
||||
DATA_BINARY_TYPE etc. */
|
||||
ulint charset_coll) /* in: MySQL charset-collation code */
|
||||
{
|
||||
ut_a(old_prtype < 256 * 256);
|
||||
ut_a(charset_coll < 256);
|
||||
|
||||
return(old_prtype + (charset_coll << 16));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Validates a data type structure. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_validate(
|
||||
/*===========*/
|
||||
/* out: TRUE if ok */
|
||||
const dtype_t* type) /* in: type struct to validate */
|
||||
{
|
||||
ut_a(type);
|
||||
ut_a(type->mtype >= DATA_VARCHAR);
|
||||
ut_a(type->mtype <= DATA_MYSQL);
|
||||
|
||||
if (type->mtype == DATA_SYS) {
|
||||
ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
|
||||
}
|
||||
|
||||
ut_a(type->mbminlen <= type->mbmaxlen);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Prints a data type structure. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dtype_print(
|
||||
/*========*/
|
||||
const dtype_t* type) /* in: type */
|
||||
{
|
||||
ulint mtype;
|
||||
ulint prtype;
|
||||
ulint len;
|
||||
|
||||
ut_a(type);
|
||||
|
||||
mtype = type->mtype;
|
||||
prtype = type->prtype;
|
||||
|
||||
switch (mtype) {
|
||||
case DATA_VARCHAR:
|
||||
fputs("DATA_VARCHAR", stderr);
|
||||
break;
|
||||
|
||||
case DATA_CHAR:
|
||||
fputs("DATA_CHAR", stderr);
|
||||
break;
|
||||
|
||||
case DATA_BINARY:
|
||||
fputs("DATA_BINARY", stderr);
|
||||
break;
|
||||
|
||||
case DATA_FIXBINARY:
|
||||
fputs("DATA_FIXBINARY", stderr);
|
||||
break;
|
||||
|
||||
case DATA_BLOB:
|
||||
fputs("DATA_BLOB", stderr);
|
||||
break;
|
||||
|
||||
case DATA_INT:
|
||||
fputs("DATA_INT", stderr);
|
||||
break;
|
||||
|
||||
case DATA_MYSQL:
|
||||
fputs("DATA_MYSQL", stderr);
|
||||
break;
|
||||
|
||||
case DATA_SYS:
|
||||
fputs("DATA_SYS", stderr);
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "type %lu", (ulong) mtype);
|
||||
break;
|
||||
}
|
||||
|
||||
len = type->len;
|
||||
|
||||
if ((type->mtype == DATA_SYS)
|
||||
|| (type->mtype == DATA_VARCHAR)
|
||||
|| (type->mtype == DATA_CHAR)) {
|
||||
putc(' ', stderr);
|
||||
if (prtype == DATA_ROW_ID) {
|
||||
fputs("DATA_ROW_ID", stderr);
|
||||
len = DATA_ROW_ID_LEN;
|
||||
} else if (prtype == DATA_ROLL_PTR) {
|
||||
fputs("DATA_ROLL_PTR", stderr);
|
||||
len = DATA_ROLL_PTR_LEN;
|
||||
} else if (prtype == DATA_TRX_ID) {
|
||||
fputs("DATA_TRX_ID", stderr);
|
||||
len = DATA_TRX_ID_LEN;
|
||||
} else if (prtype == DATA_ENGLISH) {
|
||||
fputs("DATA_ENGLISH", stderr);
|
||||
} else {
|
||||
fprintf(stderr, "prtype %lu", (ulong) prtype);
|
||||
}
|
||||
} else {
|
||||
if (prtype & DATA_UNSIGNED) {
|
||||
fputs(" DATA_UNSIGNED", stderr);
|
||||
}
|
||||
|
||||
if (prtype & DATA_BINARY_TYPE) {
|
||||
fputs(" DATA_BINARY_TYPE", stderr);
|
||||
}
|
||||
|
||||
if (prtype & DATA_NOT_NULL) {
|
||||
fputs(" DATA_NOT_NULL", stderr);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, " len %lu", (ulong) len);
|
||||
}
|
462
storage/xtradb/dict/dict0boot.c
Normal file
462
storage/xtradb/dict/dict0boot.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
Data dictionary creation and booting
|
||||
|
||||
Created 4/18/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "dict0boot.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "dict0boot.ic"
|
||||
#endif
|
||||
|
||||
#include "dict0crea.h"
|
||||
#include "btr0btr.h"
|
||||
#include "dict0load.h"
|
||||
#include "dict0load.h"
|
||||
#include "trx0trx.h"
|
||||
#include "srv0srv.h"
|
||||
#include "ibuf0ibuf.h"
|
||||
#include "buf0flu.h"
|
||||
#include "log0recv.h"
|
||||
#include "os0file.h"
|
||||
|
||||
/**************************************************************************
|
||||
Gets a pointer to the dictionary header and x-latches its page. */
|
||||
UNIV_INTERN
|
||||
dict_hdr_t*
|
||||
dict_hdr_get(
|
||||
/*=========*/
|
||||
/* out: pointer to the dictionary header,
|
||||
page x-latched */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
buf_block_t* block;
|
||||
dict_hdr_t* header;
|
||||
|
||||
block = buf_page_get(DICT_HDR_SPACE, 0, DICT_HDR_PAGE_NO,
|
||||
RW_X_LATCH, mtr);
|
||||
header = DICT_HDR + buf_block_get_frame(block);
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
|
||||
|
||||
return(header);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Returns a new table, index, or tree id. */
|
||||
UNIV_INTERN
|
||||
dulint
|
||||
dict_hdr_get_new_id(
|
||||
/*================*/
|
||||
/* out: the new id */
|
||||
ulint type) /* in: DICT_HDR_ROW_ID, ... */
|
||||
{
|
||||
dict_hdr_t* dict_hdr;
|
||||
dulint id;
|
||||
mtr_t mtr;
|
||||
|
||||
ut_ad((type == DICT_HDR_TABLE_ID) || (type == DICT_HDR_INDEX_ID));
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
dict_hdr = dict_hdr_get(&mtr);
|
||||
|
||||
id = mtr_read_dulint(dict_hdr + type, &mtr);
|
||||
id = ut_dulint_add(id, 1);
|
||||
|
||||
mlog_write_dulint(dict_hdr + type, id, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(id);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Writes the current value of the row id counter to the dictionary header file
|
||||
page. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_hdr_flush_row_id(void)
|
||||
/*=======================*/
|
||||
{
|
||||
dict_hdr_t* dict_hdr;
|
||||
dulint id;
|
||||
mtr_t mtr;
|
||||
|
||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||
|
||||
id = dict_sys->row_id;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
dict_hdr = dict_hdr_get(&mtr);
|
||||
|
||||
mlog_write_dulint(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Creates the file page for the dictionary header. This function is
|
||||
called only at the database creation. */
|
||||
static
|
||||
ibool
|
||||
dict_hdr_create(
|
||||
/*============*/
|
||||
/* out: TRUE if succeed */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
buf_block_t* block;
|
||||
dict_hdr_t* dict_header;
|
||||
ulint root_page_no;
|
||||
|
||||
ut_ad(mtr);
|
||||
|
||||
/* Create the dictionary header file block in a new, allocated file
|
||||
segment in the system tablespace */
|
||||
block = fseg_create(DICT_HDR_SPACE, 0,
|
||||
DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
|
||||
|
||||
ut_a(DICT_HDR_PAGE_NO == buf_block_get_page_no(block));
|
||||
|
||||
dict_header = dict_hdr_get(mtr);
|
||||
|
||||
/* Start counting row, table, index, and tree ids from
|
||||
DICT_HDR_FIRST_ID */
|
||||
mlog_write_dulint(dict_header + DICT_HDR_ROW_ID,
|
||||
ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
|
||||
|
||||
mlog_write_dulint(dict_header + DICT_HDR_TABLE_ID,
|
||||
ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
|
||||
|
||||
mlog_write_dulint(dict_header + DICT_HDR_INDEX_ID,
|
||||
ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
|
||||
|
||||
/* Obsolete, but we must initialize it to 0 anyway. */
|
||||
mlog_write_dulint(dict_header + DICT_HDR_MIX_ID,
|
||||
ut_dulint_create(0, DICT_HDR_FIRST_ID), mtr);
|
||||
|
||||
/* Create the B-tree roots for the clustered indexes of the basic
|
||||
system tables */
|
||||
|
||||
/*--------------------------*/
|
||||
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
DICT_HDR_SPACE, 0, DICT_TABLES_ID,
|
||||
srv_sys->dummy_ind1, mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
|
||||
MLOG_4BYTES, mtr);
|
||||
/*--------------------------*/
|
||||
root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, 0,
|
||||
DICT_TABLE_IDS_ID,
|
||||
srv_sys->dummy_ind1, mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
|
||||
MLOG_4BYTES, mtr);
|
||||
/*--------------------------*/
|
||||
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
DICT_HDR_SPACE, 0, DICT_COLUMNS_ID,
|
||||
srv_sys->dummy_ind1, mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
|
||||
MLOG_4BYTES, mtr);
|
||||
/*--------------------------*/
|
||||
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
DICT_HDR_SPACE, 0, DICT_INDEXES_ID,
|
||||
srv_sys->dummy_ind1, mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
|
||||
MLOG_4BYTES, mtr);
|
||||
/*--------------------------*/
|
||||
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
DICT_HDR_SPACE, 0, DICT_FIELDS_ID,
|
||||
srv_sys->dummy_ind1, mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
|
||||
MLOG_4BYTES, mtr);
|
||||
/*--------------------------*/
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Initializes the data dictionary memory structures when the database is
|
||||
started. This function is also called when the data dictionary is created. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_boot(void)
|
||||
/*===========*/
|
||||
{
|
||||
dict_table_t* table;
|
||||
dict_index_t* index;
|
||||
dict_hdr_t* dict_hdr;
|
||||
mem_heap_t* heap;
|
||||
mtr_t mtr;
|
||||
ulint error;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Create the hash tables etc. */
|
||||
dict_init();
|
||||
|
||||
heap = mem_heap_create(450);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
/* Get the dictionary header */
|
||||
dict_hdr = dict_hdr_get(&mtr);
|
||||
|
||||
/* Because we only write new row ids to disk-based data structure
|
||||
(dictionary header) when it is divisible by
|
||||
DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
|
||||
the latest value of the row id counter. Therefore we advance
|
||||
the counter at the database startup to avoid overlapping values.
|
||||
Note that when a user after database startup first time asks for
|
||||
a new row id, then because the counter is now divisible by
|
||||
..._MARGIN, it will immediately be updated to the disk-based
|
||||
header. */
|
||||
|
||||
dict_sys->row_id = ut_dulint_add(
|
||||
ut_dulint_align_up(mtr_read_dulint(dict_hdr + DICT_HDR_ROW_ID,
|
||||
&mtr),
|
||||
DICT_HDR_ROW_ID_WRITE_MARGIN),
|
||||
DICT_HDR_ROW_ID_WRITE_MARGIN);
|
||||
|
||||
/* Insert into the dictionary cache the descriptions of the basic
|
||||
system tables */
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
|
||||
/* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
|
||||
dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
|
||||
/* TYPE is either DICT_TABLE_ORDINARY, or (TYPE & DICT_TF_COMPACT)
|
||||
and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
|
||||
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
|
||||
|
||||
table->id = DICT_TABLES_ID;
|
||||
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_sys->sys_tables = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
|
||||
DICT_HDR_SPACE,
|
||||
DICT_UNIQUE | DICT_CLUSTERED, 1);
|
||||
|
||||
dict_mem_index_add_field(index, "NAME", 0);
|
||||
|
||||
index->id = DICT_TABLES_ID;
|
||||
|
||||
error = dict_index_add_to_cache(table, index,
|
||||
mtr_read_ulint(dict_hdr
|
||||
+ DICT_HDR_TABLES,
|
||||
MLOG_4BYTES, &mtr),
|
||||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
index = dict_mem_index_create("SYS_TABLES", "ID_IND",
|
||||
DICT_HDR_SPACE, DICT_UNIQUE, 1);
|
||||
dict_mem_index_add_field(index, "ID", 0);
|
||||
|
||||
index->id = DICT_TABLE_IDS_ID;
|
||||
error = dict_index_add_to_cache(table, index,
|
||||
mtr_read_ulint(dict_hdr
|
||||
+ DICT_HDR_TABLE_IDS,
|
||||
MLOG_4BYTES, &mtr),
|
||||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "MTYPE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "PRTYPE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "LEN", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "PREC", DATA_INT, 0, 4);
|
||||
|
||||
table->id = DICT_COLUMNS_ID;
|
||||
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_sys->sys_columns = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
|
||||
DICT_HDR_SPACE,
|
||||
DICT_UNIQUE | DICT_CLUSTERED, 2);
|
||||
|
||||
dict_mem_index_add_field(index, "TABLE_ID", 0);
|
||||
dict_mem_index_add_field(index, "POS", 0);
|
||||
|
||||
index->id = DICT_COLUMNS_ID;
|
||||
error = dict_index_add_to_cache(table, index,
|
||||
mtr_read_ulint(dict_hdr
|
||||
+ DICT_HDR_COLUMNS,
|
||||
MLOG_4BYTES, &mtr),
|
||||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
|
||||
|
||||
/* The '+ 2' below comes from the 2 system fields */
|
||||
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
|
||||
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2
|
||||
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 5 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
|
||||
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
|
||||
#endif
|
||||
|
||||
table->id = DICT_INDEXES_ID;
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_sys->sys_indexes = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
|
||||
DICT_HDR_SPACE,
|
||||
DICT_UNIQUE | DICT_CLUSTERED, 2);
|
||||
|
||||
dict_mem_index_add_field(index, "TABLE_ID", 0);
|
||||
dict_mem_index_add_field(index, "ID", 0);
|
||||
|
||||
index->id = DICT_INDEXES_ID;
|
||||
error = dict_index_add_to_cache(table, index,
|
||||
mtr_read_ulint(dict_hdr
|
||||
+ DICT_HDR_INDEXES,
|
||||
MLOG_4BYTES, &mtr),
|
||||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0);
|
||||
|
||||
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
|
||||
|
||||
table->id = DICT_FIELDS_ID;
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_sys->sys_fields = table;
|
||||
mem_heap_free(heap);
|
||||
|
||||
index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
|
||||
DICT_HDR_SPACE,
|
||||
DICT_UNIQUE | DICT_CLUSTERED, 2);
|
||||
|
||||
dict_mem_index_add_field(index, "INDEX_ID", 0);
|
||||
dict_mem_index_add_field(index, "POS", 0);
|
||||
|
||||
index->id = DICT_FIELDS_ID;
|
||||
error = dict_index_add_to_cache(table, index,
|
||||
mtr_read_ulint(dict_hdr
|
||||
+ DICT_HDR_FIELDS,
|
||||
MLOG_4BYTES, &mtr),
|
||||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
/*-------------------------*/
|
||||
|
||||
/* Initialize the insert buffer table and index for each tablespace */
|
||||
|
||||
ibuf_init_at_db_start();
|
||||
|
||||
/* Load definitions of other indexes on system tables */
|
||||
|
||||
dict_load_sys_table(dict_sys->sys_tables);
|
||||
dict_load_sys_table(dict_sys->sys_columns);
|
||||
dict_load_sys_table(dict_sys->sys_indexes);
|
||||
dict_load_sys_table(dict_sys->sys_fields);
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Inserts the basic system table data into themselves in the database
|
||||
creation. */
|
||||
static
|
||||
void
|
||||
dict_insert_initial_data(void)
|
||||
/*==========================*/
|
||||
{
|
||||
/* Does nothing yet */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Creates and initializes the data dictionary at the database creation. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_create(void)
|
||||
/*=============*/
|
||||
{
|
||||
mtr_t mtr;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
dict_hdr_create(&mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
dict_boot();
|
||||
|
||||
dict_insert_initial_data();
|
||||
}
|
1503
storage/xtradb/dict/dict0crea.c
Normal file
1503
storage/xtradb/dict/dict0crea.c
Normal file
File diff suppressed because it is too large
Load Diff
4747
storage/xtradb/dict/dict0dict.c
Normal file
4747
storage/xtradb/dict/dict0dict.c
Normal file
File diff suppressed because it is too large
Load Diff
1460
storage/xtradb/dict/dict0load.c
Normal file
1460
storage/xtradb/dict/dict0load.c
Normal file
File diff suppressed because it is too large
Load Diff
308
storage/xtradb/dict/dict0mem.c
Normal file
308
storage/xtradb/dict/dict0mem.c
Normal file
@ -0,0 +1,308 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
Data dictionary memory object creation
|
||||
|
||||
Created 1/8/1996 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "dict0mem.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "dict0mem.ic"
|
||||
#endif
|
||||
|
||||
#include "rem0rec.h"
|
||||
#include "data0type.h"
|
||||
#include "mach0data.h"
|
||||
#include "dict0dict.h"
|
||||
#include "lock0lock.h"
|
||||
|
||||
#define DICT_HEAP_SIZE 100 /* initial memory heap size when
|
||||
creating a table or index object */
|
||||
|
||||
/**************************************************************************
|
||||
Creates a table memory object. */
|
||||
UNIV_INTERN
|
||||
dict_table_t*
|
||||
dict_mem_table_create(
|
||||
/*==================*/
|
||||
/* out, own: table object */
|
||||
const char* name, /* in: table name */
|
||||
ulint space, /* in: space where the clustered index of
|
||||
the table is placed; this parameter is
|
||||
ignored if the table is made a member of
|
||||
a cluster */
|
||||
ulint n_cols, /* in: number of columns */
|
||||
ulint flags) /* in: table flags */
|
||||
{
|
||||
dict_table_t* table;
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(name);
|
||||
ut_a(!(flags & (~0 << DICT_TF_BITS)));
|
||||
|
||||
heap = mem_heap_create(DICT_HEAP_SIZE);
|
||||
|
||||
table = mem_heap_zalloc(heap, sizeof(dict_table_t));
|
||||
|
||||
table->heap = heap;
|
||||
|
||||
table->flags = (unsigned int) flags;
|
||||
table->name = mem_heap_strdup(heap, name);
|
||||
table->space = (unsigned int) space;
|
||||
table->n_cols = (unsigned int) (n_cols + DATA_N_SYS_COLS);
|
||||
|
||||
table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
|
||||
* sizeof(dict_col_t));
|
||||
|
||||
table->autoinc_lock = mem_heap_alloc(heap, lock_get_size());
|
||||
|
||||
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
|
||||
|
||||
table->autoinc = 0;
|
||||
|
||||
/* The number of transactions that are either waiting on the
|
||||
AUTOINC lock or have been granted the lock. */
|
||||
table->n_waiting_or_granted_auto_inc_locks = 0;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
table->magic_n = DICT_TABLE_MAGIC_N;
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(table);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Free a table memory object. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_mem_table_free(
|
||||
/*================*/
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_d(table->cached = FALSE);
|
||||
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
mem_heap_free(table->heap);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Append 'name' to 'col_names' (@see dict_table_t::col_names). */
|
||||
static
|
||||
const char*
|
||||
dict_add_col_name(
|
||||
/*==============*/
|
||||
/* out: new column names array */
|
||||
const char* col_names, /* in: existing column names, or
|
||||
NULL */
|
||||
ulint cols, /* in: number of existing columns */
|
||||
const char* name, /* in: new column name */
|
||||
mem_heap_t* heap) /* in: heap */
|
||||
{
|
||||
ulint old_len;
|
||||
ulint new_len;
|
||||
ulint total_len;
|
||||
char* res;
|
||||
|
||||
ut_ad(!cols == !col_names);
|
||||
|
||||
/* Find out length of existing array. */
|
||||
if (col_names) {
|
||||
const char* s = col_names;
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < cols; i++) {
|
||||
s += strlen(s) + 1;
|
||||
}
|
||||
|
||||
old_len = s - col_names;
|
||||
} else {
|
||||
old_len = 0;
|
||||
}
|
||||
|
||||
new_len = strlen(name) + 1;
|
||||
total_len = old_len + new_len;
|
||||
|
||||
res = mem_heap_alloc(heap, total_len);
|
||||
|
||||
if (old_len > 0) {
|
||||
memcpy(res, col_names, old_len);
|
||||
}
|
||||
|
||||
memcpy(res + old_len, name, new_len);
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Adds a column definition to a table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_mem_table_add_col(
|
||||
/*===================*/
|
||||
dict_table_t* table, /* in: table */
|
||||
mem_heap_t* heap, /* in: temporary memory heap, or NULL */
|
||||
const char* name, /* in: column name, or NULL */
|
||||
ulint mtype, /* in: main datatype */
|
||||
ulint prtype, /* in: precise type */
|
||||
ulint len) /* in: precision */
|
||||
{
|
||||
dict_col_t* col;
|
||||
ulint mbminlen;
|
||||
ulint mbmaxlen;
|
||||
ulint i;
|
||||
|
||||
ut_ad(table);
|
||||
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
|
||||
ut_ad(!heap == !name);
|
||||
|
||||
i = table->n_def++;
|
||||
|
||||
if (name) {
|
||||
if (UNIV_UNLIKELY(table->n_def == table->n_cols)) {
|
||||
heap = table->heap;
|
||||
}
|
||||
if (UNIV_LIKELY(i) && UNIV_UNLIKELY(!table->col_names)) {
|
||||
/* All preceding column names are empty. */
|
||||
char* s = mem_heap_zalloc(heap, table->n_def);
|
||||
table->col_names = s;
|
||||
}
|
||||
|
||||
table->col_names = dict_add_col_name(table->col_names,
|
||||
i, name, heap);
|
||||
}
|
||||
|
||||
col = dict_table_get_nth_col(table, i);
|
||||
|
||||
col->ind = (unsigned int) i;
|
||||
col->ord_part = 0;
|
||||
|
||||
col->mtype = (unsigned int) mtype;
|
||||
col->prtype = (unsigned int) prtype;
|
||||
col->len = (unsigned int) len;
|
||||
|
||||
dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
|
||||
|
||||
col->mbminlen = (unsigned int) mbminlen;
|
||||
col->mbmaxlen = (unsigned int) mbmaxlen;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Creates an index memory object. */
|
||||
UNIV_INTERN
|
||||
dict_index_t*
|
||||
dict_mem_index_create(
|
||||
/*==================*/
|
||||
/* out, own: index object */
|
||||
const char* table_name, /* in: table name */
|
||||
const char* index_name, /* in: index name */
|
||||
ulint space, /* in: space where the index tree is
|
||||
placed, ignored if the index is of
|
||||
the clustered type */
|
||||
ulint type, /* in: DICT_UNIQUE,
|
||||
DICT_CLUSTERED, ... ORed */
|
||||
ulint n_fields) /* in: number of fields */
|
||||
{
|
||||
dict_index_t* index;
|
||||
mem_heap_t* heap;
|
||||
|
||||
ut_ad(table_name && index_name);
|
||||
|
||||
heap = mem_heap_create(DICT_HEAP_SIZE);
|
||||
index = mem_heap_zalloc(heap, sizeof(dict_index_t));
|
||||
|
||||
index->heap = heap;
|
||||
|
||||
index->type = type;
|
||||
index->space = (unsigned int) space;
|
||||
index->name = mem_heap_strdup(heap, index_name);
|
||||
index->table_name = table_name;
|
||||
index->n_fields = (unsigned int) n_fields;
|
||||
index->fields = mem_heap_alloc(heap, 1 + n_fields
|
||||
* sizeof(dict_field_t));
|
||||
/* The '1 +' above prevents allocation
|
||||
of an empty mem block */
|
||||
#ifdef UNIV_DEBUG
|
||||
index->magic_n = DICT_INDEX_MAGIC_N;
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(index);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Creates and initializes a foreign constraint memory object. */
|
||||
UNIV_INTERN
|
||||
dict_foreign_t*
|
||||
dict_mem_foreign_create(void)
|
||||
/*=========================*/
|
||||
/* out, own: foreign constraint struct */
|
||||
{
|
||||
dict_foreign_t* foreign;
|
||||
mem_heap_t* heap;
|
||||
|
||||
heap = mem_heap_create(100);
|
||||
|
||||
foreign = mem_heap_zalloc(heap, sizeof(dict_foreign_t));
|
||||
|
||||
foreign->heap = heap;
|
||||
|
||||
return(foreign);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Adds a field definition to an index. NOTE: does not take a copy
|
||||
of the column name if the field is a column. The memory occupied
|
||||
by the column name may be released only after publishing the index. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_mem_index_add_field(
|
||||
/*=====================*/
|
||||
dict_index_t* index, /* in: index */
|
||||
const char* name, /* in: column name */
|
||||
ulint prefix_len) /* in: 0 or the column prefix length
|
||||
in a MySQL index like
|
||||
INDEX (textcol(25)) */
|
||||
{
|
||||
dict_field_t* field;
|
||||
|
||||
ut_ad(index);
|
||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||
|
||||
index->n_def++;
|
||||
|
||||
field = dict_index_get_nth_field(index, index->n_def - 1);
|
||||
|
||||
field->name = name;
|
||||
field->prefix_len = (unsigned int) prefix_len;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Frees an index memory object. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_mem_index_free(
|
||||
/*================*/
|
||||
dict_index_t* index) /* in: index */
|
||||
{
|
||||
ut_ad(index);
|
||||
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
|
||||
|
||||
mem_heap_free(index->heap);
|
||||
}
|
64
storage/xtradb/dyn/dyn0dyn.c
Normal file
64
storage/xtradb/dyn/dyn0dyn.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
The dynamically allocated array
|
||||
|
||||
Created 2/5/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "dyn0dyn.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "dyn0dyn.ic"
|
||||
#endif
|
||||
|
||||
/****************************************************************
|
||||
Adds a new block to a dyn array. */
|
||||
UNIV_INTERN
|
||||
dyn_block_t*
|
||||
dyn_array_add_block(
|
||||
/*================*/
|
||||
/* out: created block */
|
||||
dyn_array_t* arr) /* in: dyn array */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
dyn_block_t* block;
|
||||
|
||||
ut_ad(arr);
|
||||
ut_ad(arr->magic_n == DYN_BLOCK_MAGIC_N);
|
||||
|
||||
if (arr->heap == NULL) {
|
||||
UT_LIST_INIT(arr->base);
|
||||
UT_LIST_ADD_FIRST(list, arr->base, arr);
|
||||
|
||||
arr->heap = mem_heap_create(sizeof(dyn_block_t));
|
||||
}
|
||||
|
||||
block = dyn_array_get_last_block(arr);
|
||||
block->used = block->used | DYN_BLOCK_FULL_FLAG;
|
||||
|
||||
heap = arr->heap;
|
||||
|
||||
block = mem_heap_alloc(heap, sizeof(dyn_block_t));
|
||||
|
||||
block->used = 0;
|
||||
|
||||
UT_LIST_ADD_LAST(list, arr->base, block);
|
||||
|
||||
return(block);
|
||||
}
|
851
storage/xtradb/eval/eval0eval.c
Normal file
851
storage/xtradb/eval/eval0eval.c
Normal file
@ -0,0 +1,851 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
SQL evaluator: evaluates simple data structures, like expressions, in
|
||||
a query graph
|
||||
|
||||
Created 12/29/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "eval0eval.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "eval0eval.ic"
|
||||
#endif
|
||||
|
||||
#include "data0data.h"
|
||||
#include "row0sel.h"
|
||||
|
||||
/* The RND function seed */
|
||||
static ulint eval_rnd = 128367121;
|
||||
|
||||
/* Dummy adress used when we should allocate a buffer of size 0 in
|
||||
the function below */
|
||||
|
||||
static byte eval_dummy;
|
||||
|
||||
/*********************************************************************
|
||||
Allocate a buffer from global dynamic memory for a value of a que_node.
|
||||
NOTE that this memory must be explicitly freed when the query graph is
|
||||
freed. If the node already has an allocated buffer, that buffer is freed
|
||||
here. NOTE that this is the only function where dynamic memory should be
|
||||
allocated for a query node val field. */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
eval_node_alloc_val_buf(
|
||||
/*====================*/
|
||||
/* out: pointer to allocated buffer */
|
||||
que_node_t* node, /* in: query graph node; sets the val field
|
||||
data field to point to the new buffer, and
|
||||
len field equal to size */
|
||||
ulint size) /* in: buffer size */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
|
||||
|| que_node_get_type(node) == QUE_NODE_FUNC);
|
||||
|
||||
dfield = que_node_get_val(node);
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
|
||||
if (data && data != &eval_dummy) {
|
||||
mem_free(data);
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
data = &eval_dummy;
|
||||
} else {
|
||||
data = mem_alloc(size);
|
||||
}
|
||||
|
||||
que_node_set_val_buf_size(node, size);
|
||||
|
||||
dfield_set_data(dfield, data, size);
|
||||
|
||||
return(data);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Free the buffer from global dynamic memory for a value of a que_node,
|
||||
if it has been allocated in the above function. The freeing for pushed
|
||||
column values is done in sel_col_prefetch_buf_free. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
eval_node_free_val_buf(
|
||||
/*===================*/
|
||||
que_node_t* node) /* in: query graph node */
|
||||
{
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_SYMBOL
|
||||
|| que_node_get_type(node) == QUE_NODE_FUNC);
|
||||
|
||||
dfield = que_node_get_val(node);
|
||||
|
||||
data = dfield_get_data(dfield);
|
||||
|
||||
if (que_node_get_val_buf_size(node) > 0) {
|
||||
ut_a(data);
|
||||
|
||||
mem_free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a comparison node. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
eval_cmp(
|
||||
/*=====*/
|
||||
/* out: the result of the comparison */
|
||||
func_node_t* cmp_node) /* in: comparison node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
int res;
|
||||
ibool val;
|
||||
int func;
|
||||
|
||||
ut_ad(que_node_get_type(cmp_node) == QUE_NODE_FUNC);
|
||||
|
||||
arg1 = cmp_node->args;
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
res = cmp_dfield_dfield(que_node_get_val(arg1),
|
||||
que_node_get_val(arg2));
|
||||
val = TRUE;
|
||||
|
||||
func = cmp_node->func;
|
||||
|
||||
if (func == '=') {
|
||||
if (res != 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == '<') {
|
||||
if (res != -1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_LE_TOKEN) {
|
||||
if (res == 1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_NE_TOKEN) {
|
||||
if (res == 0) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else if (func == PARS_GE_TOKEN) {
|
||||
if (res == -1) {
|
||||
val = FALSE;
|
||||
}
|
||||
} else {
|
||||
ut_ad(func == '>');
|
||||
|
||||
if (res != 1) {
|
||||
val = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
eval_node_set_ibool_val(cmp_node, val);
|
||||
|
||||
return(val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a logical operation node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_logical(
|
||||
/*=========*/
|
||||
func_node_t* logical_node) /* in: logical operation node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
ibool val1;
|
||||
ibool val2 = 0; /* remove warning */
|
||||
ibool val = 0; /* remove warning */
|
||||
int func;
|
||||
|
||||
ut_ad(que_node_get_type(logical_node) == QUE_NODE_FUNC);
|
||||
|
||||
arg1 = logical_node->args;
|
||||
arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is 'NOT' */
|
||||
|
||||
val1 = eval_node_get_ibool_val(arg1);
|
||||
|
||||
if (arg2) {
|
||||
val2 = eval_node_get_ibool_val(arg2);
|
||||
}
|
||||
|
||||
func = logical_node->func;
|
||||
|
||||
if (func == PARS_AND_TOKEN) {
|
||||
val = val1 & val2;
|
||||
} else if (func == PARS_OR_TOKEN) {
|
||||
val = val1 | val2;
|
||||
} else if (func == PARS_NOT_TOKEN) {
|
||||
val = TRUE - val1;
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
eval_node_set_ibool_val(logical_node, val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates an arithmetic operation node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_arith(
|
||||
/*=======*/
|
||||
func_node_t* arith_node) /* in: arithmetic operation node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
lint val1;
|
||||
lint val2 = 0; /* remove warning */
|
||||
lint val;
|
||||
int func;
|
||||
|
||||
ut_ad(que_node_get_type(arith_node) == QUE_NODE_FUNC);
|
||||
|
||||
arg1 = arith_node->args;
|
||||
arg2 = que_node_get_next(arg1); /* arg2 is NULL if func is unary '-' */
|
||||
|
||||
val1 = eval_node_get_int_val(arg1);
|
||||
|
||||
if (arg2) {
|
||||
val2 = eval_node_get_int_val(arg2);
|
||||
}
|
||||
|
||||
func = arith_node->func;
|
||||
|
||||
if (func == '+') {
|
||||
val = val1 + val2;
|
||||
} else if ((func == '-') && arg2) {
|
||||
val = val1 - val2;
|
||||
} else if (func == '-') {
|
||||
val = -val1;
|
||||
} else if (func == '*') {
|
||||
val = val1 * val2;
|
||||
} else {
|
||||
ut_ad(func == '/');
|
||||
val = val1 / val2;
|
||||
}
|
||||
|
||||
eval_node_set_int_val(arith_node, val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates an aggregate operation node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_aggregate(
|
||||
/*===========*/
|
||||
func_node_t* node) /* in: aggregate operation node */
|
||||
{
|
||||
que_node_t* arg;
|
||||
lint val;
|
||||
lint arg_val;
|
||||
int func;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_FUNC);
|
||||
|
||||
val = eval_node_get_int_val(node);
|
||||
|
||||
func = node->func;
|
||||
|
||||
if (func == PARS_COUNT_TOKEN) {
|
||||
|
||||
val = val + 1;
|
||||
} else {
|
||||
ut_ad(func == PARS_SUM_TOKEN);
|
||||
|
||||
arg = node->args;
|
||||
arg_val = eval_node_get_int_val(arg);
|
||||
|
||||
val = val + arg_val;
|
||||
}
|
||||
|
||||
eval_node_set_int_val(node, val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a predefined function node where the function is not relevant
|
||||
in benchmarks. */
|
||||
static
|
||||
void
|
||||
eval_predefined_2(
|
||||
/*==============*/
|
||||
func_node_t* func_node) /* in: predefined function node */
|
||||
{
|
||||
que_node_t* arg;
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2 = 0; /* remove warning (??? bug ???) */
|
||||
lint int_val;
|
||||
byte* data;
|
||||
ulint len1;
|
||||
ulint len2;
|
||||
int func;
|
||||
ulint i;
|
||||
|
||||
ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
|
||||
|
||||
arg1 = func_node->args;
|
||||
|
||||
if (arg1) {
|
||||
arg2 = que_node_get_next(arg1);
|
||||
}
|
||||
|
||||
func = func_node->func;
|
||||
|
||||
if (func == PARS_PRINTF_TOKEN) {
|
||||
|
||||
arg = arg1;
|
||||
|
||||
while (arg) {
|
||||
dfield_print(que_node_get_val(arg));
|
||||
|
||||
arg = que_node_get_next(arg);
|
||||
}
|
||||
|
||||
putc('\n', stderr);
|
||||
|
||||
} else if (func == PARS_ASSERT_TOKEN) {
|
||||
|
||||
if (!eval_node_get_ibool_val(arg1)) {
|
||||
fputs("SQL assertion fails in a stored procedure!\n",
|
||||
stderr);
|
||||
}
|
||||
|
||||
ut_a(eval_node_get_ibool_val(arg1));
|
||||
|
||||
/* This function, or more precisely, a debug procedure,
|
||||
returns no value */
|
||||
|
||||
} else if (func == PARS_RND_TOKEN) {
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg1);
|
||||
len2 = (ulint)eval_node_get_int_val(arg2);
|
||||
|
||||
ut_ad(len2 >= len1);
|
||||
|
||||
if (len2 > len1) {
|
||||
int_val = (lint) (len1
|
||||
+ (eval_rnd % (len2 - len1 + 1)));
|
||||
} else {
|
||||
int_val = (lint) len1;
|
||||
}
|
||||
|
||||
eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
|
||||
|
||||
eval_node_set_int_val(func_node, int_val);
|
||||
|
||||
} else if (func == PARS_RND_STR_TOKEN) {
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg1);
|
||||
|
||||
data = eval_node_ensure_val_buf(func_node, len1);
|
||||
|
||||
for (i = 0; i < len1; i++) {
|
||||
data[i] = (byte)(97 + (eval_rnd % 3));
|
||||
|
||||
eval_rnd = ut_rnd_gen_next_ulint(eval_rnd);
|
||||
}
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a notfound-function node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_notfound(
|
||||
/*==========*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
sym_node_t* cursor;
|
||||
sel_node_t* sel_node;
|
||||
ibool ibool_val;
|
||||
|
||||
arg1 = func_node->args;
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
ut_ad(func_node->func == PARS_NOTFOUND_TOKEN);
|
||||
|
||||
cursor = arg1;
|
||||
|
||||
ut_ad(que_node_get_type(cursor) == QUE_NODE_SYMBOL);
|
||||
|
||||
if (cursor->token_type == SYM_LIT) {
|
||||
|
||||
ut_ad(ut_memcmp(dfield_get_data(que_node_get_val(cursor)),
|
||||
"SQL", 3) == 0);
|
||||
|
||||
sel_node = cursor->sym_table->query_graph->last_sel_node;
|
||||
} else {
|
||||
sel_node = cursor->alias->cursor_def;
|
||||
}
|
||||
|
||||
if (sel_node->state == SEL_NODE_NO_MORE_ROWS) {
|
||||
ibool_val = TRUE;
|
||||
} else {
|
||||
ibool_val = FALSE;
|
||||
}
|
||||
|
||||
eval_node_set_ibool_val(func_node, ibool_val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a substr-function node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_substr(
|
||||
/*========*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
que_node_t* arg3;
|
||||
dfield_t* dfield;
|
||||
byte* str1;
|
||||
ulint len1;
|
||||
ulint len2;
|
||||
|
||||
arg1 = func_node->args;
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
ut_ad(func_node->func == PARS_SUBSTR_TOKEN);
|
||||
|
||||
arg3 = que_node_get_next(arg2);
|
||||
|
||||
str1 = dfield_get_data(que_node_get_val(arg1));
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg2);
|
||||
len2 = (ulint)eval_node_get_int_val(arg3);
|
||||
|
||||
dfield = que_node_get_val(func_node);
|
||||
|
||||
dfield_set_data(dfield, str1 + len1, len2);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a replstr-procedure node. */
|
||||
static
|
||||
void
|
||||
eval_replstr(
|
||||
/*=========*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
que_node_t* arg3;
|
||||
que_node_t* arg4;
|
||||
byte* str1;
|
||||
byte* str2;
|
||||
ulint len1;
|
||||
ulint len2;
|
||||
|
||||
arg1 = func_node->args;
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
ut_ad(que_node_get_type(arg1) == QUE_NODE_SYMBOL);
|
||||
|
||||
arg3 = que_node_get_next(arg2);
|
||||
arg4 = que_node_get_next(arg3);
|
||||
|
||||
str1 = dfield_get_data(que_node_get_val(arg1));
|
||||
str2 = dfield_get_data(que_node_get_val(arg2));
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg3);
|
||||
len2 = (ulint)eval_node_get_int_val(arg4);
|
||||
|
||||
if ((dfield_get_len(que_node_get_val(arg1)) < len1 + len2)
|
||||
|| (dfield_get_len(que_node_get_val(arg2)) < len2)) {
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
||||
ut_memcpy(str1 + len1, str2, len2);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates an instr-function node. */
|
||||
static
|
||||
void
|
||||
eval_instr(
|
||||
/*=======*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
dfield_t* dfield1;
|
||||
dfield_t* dfield2;
|
||||
lint int_val;
|
||||
byte* str1;
|
||||
byte* str2;
|
||||
byte match_char;
|
||||
ulint len1;
|
||||
ulint len2;
|
||||
ulint i;
|
||||
ulint j;
|
||||
|
||||
arg1 = func_node->args;
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
dfield1 = que_node_get_val(arg1);
|
||||
dfield2 = que_node_get_val(arg2);
|
||||
|
||||
str1 = dfield_get_data(dfield1);
|
||||
str2 = dfield_get_data(dfield2);
|
||||
|
||||
len1 = dfield_get_len(dfield1);
|
||||
len2 = dfield_get_len(dfield2);
|
||||
|
||||
if (len2 == 0) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
match_char = str2[0];
|
||||
|
||||
for (i = 0; i < len1; i++) {
|
||||
/* In this outer loop, the number of matched characters is 0 */
|
||||
|
||||
if (str1[i] == match_char) {
|
||||
|
||||
if (i + len2 > len1) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (j = 1;; j++) {
|
||||
/* We have already matched j characters */
|
||||
|
||||
if (j == len2) {
|
||||
int_val = i + 1;
|
||||
|
||||
goto match_found;
|
||||
}
|
||||
|
||||
if (str1[i + j] != str2[j]) {
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int_val = 0;
|
||||
|
||||
match_found:
|
||||
eval_node_set_int_val(func_node, int_val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a predefined function node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_binary_to_number(
|
||||
/*==================*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
dfield_t* dfield;
|
||||
byte* str1;
|
||||
byte* str2;
|
||||
ulint len1;
|
||||
ulint int_val;
|
||||
|
||||
arg1 = func_node->args;
|
||||
|
||||
dfield = que_node_get_val(arg1);
|
||||
|
||||
str1 = dfield_get_data(dfield);
|
||||
len1 = dfield_get_len(dfield);
|
||||
|
||||
if (len1 > 4) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (len1 == 4) {
|
||||
str2 = str1;
|
||||
} else {
|
||||
int_val = 0;
|
||||
str2 = (byte*)&int_val;
|
||||
|
||||
ut_memcpy(str2 + (4 - len1), str1, len1);
|
||||
}
|
||||
|
||||
eval_node_copy_and_alloc_val(func_node, str2, 4);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a predefined function node. */
|
||||
static
|
||||
void
|
||||
eval_concat(
|
||||
/*========*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg;
|
||||
dfield_t* dfield;
|
||||
byte* data;
|
||||
ulint len;
|
||||
ulint len1;
|
||||
|
||||
arg = func_node->args;
|
||||
len = 0;
|
||||
|
||||
while (arg) {
|
||||
len1 = dfield_get_len(que_node_get_val(arg));
|
||||
|
||||
len += len1;
|
||||
|
||||
arg = que_node_get_next(arg);
|
||||
}
|
||||
|
||||
data = eval_node_ensure_val_buf(func_node, len);
|
||||
|
||||
arg = func_node->args;
|
||||
len = 0;
|
||||
|
||||
while (arg) {
|
||||
dfield = que_node_get_val(arg);
|
||||
len1 = dfield_get_len(dfield);
|
||||
|
||||
ut_memcpy(data + len, dfield_get_data(dfield), len1);
|
||||
|
||||
len += len1;
|
||||
|
||||
arg = que_node_get_next(arg);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a predefined function node. If the first argument is an integer,
|
||||
this function looks at the second argument which is the integer length in
|
||||
bytes, and converts the integer to a VARCHAR.
|
||||
If the first argument is of some other type, this function converts it to
|
||||
BINARY. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_to_binary(
|
||||
/*===========*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
que_node_t* arg2;
|
||||
dfield_t* dfield;
|
||||
byte* str1;
|
||||
ulint len;
|
||||
ulint len1;
|
||||
|
||||
arg1 = func_node->args;
|
||||
|
||||
str1 = dfield_get_data(que_node_get_val(arg1));
|
||||
|
||||
if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
|
||||
|
||||
len = dfield_get_len(que_node_get_val(arg1));
|
||||
|
||||
dfield = que_node_get_val(func_node);
|
||||
|
||||
dfield_set_data(dfield, str1, len);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
arg2 = que_node_get_next(arg1);
|
||||
|
||||
len1 = (ulint)eval_node_get_int_val(arg2);
|
||||
|
||||
if (len1 > 4) {
|
||||
|
||||
ut_error;
|
||||
}
|
||||
|
||||
dfield = que_node_get_val(func_node);
|
||||
|
||||
dfield_set_data(dfield, str1 + (4 - len1), len1);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a predefined function node. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
eval_predefined(
|
||||
/*============*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg1;
|
||||
lint int_val;
|
||||
byte* data;
|
||||
int func;
|
||||
|
||||
func = func_node->func;
|
||||
|
||||
arg1 = func_node->args;
|
||||
|
||||
if (func == PARS_LENGTH_TOKEN) {
|
||||
|
||||
int_val = (lint)dfield_get_len(que_node_get_val(arg1));
|
||||
|
||||
} else if (func == PARS_TO_CHAR_TOKEN) {
|
||||
|
||||
/* Convert number to character string as a
|
||||
signed decimal integer. */
|
||||
|
||||
ulint uint_val;
|
||||
int int_len;
|
||||
|
||||
int_val = eval_node_get_int_val(arg1);
|
||||
|
||||
/* Determine the length of the string. */
|
||||
|
||||
if (int_val == 0) {
|
||||
int_len = 1; /* the number 0 occupies 1 byte */
|
||||
} else {
|
||||
int_len = 0;
|
||||
if (int_val < 0) {
|
||||
uint_val = ((ulint) -int_val - 1) + 1;
|
||||
int_len++; /* reserve space for minus sign */
|
||||
} else {
|
||||
uint_val = (ulint) int_val;
|
||||
}
|
||||
for (; uint_val > 0; int_len++) {
|
||||
uint_val /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate the string */
|
||||
data = eval_node_ensure_val_buf(func_node, int_len + 1);
|
||||
|
||||
/* add terminating NUL character */
|
||||
data[int_len] = 0;
|
||||
|
||||
/* convert the number */
|
||||
|
||||
if (int_val == 0) {
|
||||
data[0] = '0';
|
||||
} else {
|
||||
int tmp;
|
||||
if (int_val < 0) {
|
||||
data[0] = '-'; /* preceding minus sign */
|
||||
uint_val = ((ulint) -int_val - 1) + 1;
|
||||
} else {
|
||||
uint_val = (ulint) int_val;
|
||||
}
|
||||
for (tmp = int_len; uint_val > 0; uint_val /= 10) {
|
||||
data[--tmp] = (byte)
|
||||
('0' + (byte)(uint_val % 10));
|
||||
}
|
||||
}
|
||||
|
||||
dfield_set_len(que_node_get_val(func_node), int_len);
|
||||
|
||||
return;
|
||||
|
||||
} else if (func == PARS_TO_NUMBER_TOKEN) {
|
||||
|
||||
int_val = atoi((char*)
|
||||
dfield_get_data(que_node_get_val(arg1)));
|
||||
|
||||
} else if (func == PARS_SYSDATE_TOKEN) {
|
||||
int_val = (lint)ut_time();
|
||||
} else {
|
||||
eval_predefined_2(func_node);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
eval_node_set_int_val(func_node, int_val);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Evaluates a function node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
eval_func(
|
||||
/*======*/
|
||||
func_node_t* func_node) /* in: function node */
|
||||
{
|
||||
que_node_t* arg;
|
||||
ulint class;
|
||||
ulint func;
|
||||
|
||||
ut_ad(que_node_get_type(func_node) == QUE_NODE_FUNC);
|
||||
|
||||
class = func_node->class;
|
||||
func = func_node->func;
|
||||
|
||||
arg = func_node->args;
|
||||
|
||||
/* Evaluate first the argument list */
|
||||
while (arg) {
|
||||
eval_exp(arg);
|
||||
|
||||
/* The functions are not defined for SQL null argument
|
||||
values, except for eval_cmp and notfound */
|
||||
|
||||
if (dfield_is_null(que_node_get_val(arg))
|
||||
&& (class != PARS_FUNC_CMP)
|
||||
&& (func != PARS_NOTFOUND_TOKEN)
|
||||
&& (func != PARS_PRINTF_TOKEN)) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
arg = que_node_get_next(arg);
|
||||
}
|
||||
|
||||
if (class == PARS_FUNC_CMP) {
|
||||
eval_cmp(func_node);
|
||||
} else if (class == PARS_FUNC_ARITH) {
|
||||
eval_arith(func_node);
|
||||
} else if (class == PARS_FUNC_AGGREGATE) {
|
||||
eval_aggregate(func_node);
|
||||
} else if (class == PARS_FUNC_PREDEFINED) {
|
||||
|
||||
if (func == PARS_NOTFOUND_TOKEN) {
|
||||
eval_notfound(func_node);
|
||||
} else if (func == PARS_SUBSTR_TOKEN) {
|
||||
eval_substr(func_node);
|
||||
} else if (func == PARS_REPLSTR_TOKEN) {
|
||||
eval_replstr(func_node);
|
||||
} else if (func == PARS_INSTR_TOKEN) {
|
||||
eval_instr(func_node);
|
||||
} else if (func == PARS_BINARY_TO_NUMBER_TOKEN) {
|
||||
eval_binary_to_number(func_node);
|
||||
} else if (func == PARS_CONCAT_TOKEN) {
|
||||
eval_concat(func_node);
|
||||
} else if (func == PARS_TO_BINARY_TOKEN) {
|
||||
eval_to_binary(func_node);
|
||||
} else {
|
||||
eval_predefined(func_node);
|
||||
}
|
||||
} else {
|
||||
ut_ad(class == PARS_FUNC_LOGICAL);
|
||||
|
||||
eval_logical(func_node);
|
||||
}
|
||||
}
|
294
storage/xtradb/eval/eval0proc.c
Normal file
294
storage/xtradb/eval/eval0proc.c
Normal file
@ -0,0 +1,294 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1998, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
Executes SQL stored procedures and their control structures
|
||||
|
||||
Created 1/20/1998 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "eval0proc.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "eval0proc.ic"
|
||||
#endif
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of an if-statement node. */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
if_step(
|
||||
/*====*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
if_node_t* node;
|
||||
elsif_node_t* elsif_node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_IF);
|
||||
|
||||
if (thr->prev_node == que_node_get_parent(node)) {
|
||||
|
||||
/* Evaluate the condition */
|
||||
|
||||
eval_exp(node->cond);
|
||||
|
||||
if (eval_node_get_ibool_val(node->cond)) {
|
||||
|
||||
/* The condition evaluated to TRUE: start execution
|
||||
from the first statement in the statement list */
|
||||
|
||||
thr->run_node = node->stat_list;
|
||||
|
||||
} else if (node->else_part) {
|
||||
thr->run_node = node->else_part;
|
||||
|
||||
} else if (node->elsif_list) {
|
||||
elsif_node = node->elsif_list;
|
||||
|
||||
for (;;) {
|
||||
eval_exp(elsif_node->cond);
|
||||
|
||||
if (eval_node_get_ibool_val(
|
||||
elsif_node->cond)) {
|
||||
|
||||
/* The condition evaluated to TRUE:
|
||||
start execution from the first
|
||||
statement in the statement list */
|
||||
|
||||
thr->run_node = elsif_node->stat_list;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
elsif_node = que_node_get_next(elsif_node);
|
||||
|
||||
if (elsif_node == NULL) {
|
||||
thr->run_node = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thr->run_node = NULL;
|
||||
}
|
||||
} else {
|
||||
/* Move to the next statement */
|
||||
ut_ad(que_node_get_next(thr->prev_node) == NULL);
|
||||
|
||||
thr->run_node = NULL;
|
||||
}
|
||||
|
||||
if (thr->run_node == NULL) {
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
}
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of a while-statement node. */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
while_step(
|
||||
/*=======*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
while_node_t* node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_WHILE);
|
||||
|
||||
ut_ad((thr->prev_node == que_node_get_parent(node))
|
||||
|| (que_node_get_next(thr->prev_node) == NULL));
|
||||
|
||||
/* Evaluate the condition */
|
||||
|
||||
eval_exp(node->cond);
|
||||
|
||||
if (eval_node_get_ibool_val(node->cond)) {
|
||||
|
||||
/* The condition evaluated to TRUE: start execution
|
||||
from the first statement in the statement list */
|
||||
|
||||
thr->run_node = node->stat_list;
|
||||
} else {
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
}
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of an assignment statement node. */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
assign_step(
|
||||
/*========*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
assign_node_t* node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_ASSIGNMENT);
|
||||
|
||||
/* Evaluate the value to assign */
|
||||
|
||||
eval_exp(node->val);
|
||||
|
||||
eval_node_copy_val(node->var->alias, node->val);
|
||||
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of a for-loop node. */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
for_step(
|
||||
/*=====*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
for_node_t* node;
|
||||
que_node_t* parent;
|
||||
lint loop_var_value;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_FOR);
|
||||
|
||||
parent = que_node_get_parent(node);
|
||||
|
||||
if (thr->prev_node != parent) {
|
||||
|
||||
/* Move to the next statement */
|
||||
thr->run_node = que_node_get_next(thr->prev_node);
|
||||
|
||||
if (thr->run_node != NULL) {
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/* Increment the value of loop_var */
|
||||
|
||||
loop_var_value = 1 + eval_node_get_int_val(node->loop_var);
|
||||
} else {
|
||||
/* Initialize the loop */
|
||||
|
||||
eval_exp(node->loop_start_limit);
|
||||
eval_exp(node->loop_end_limit);
|
||||
|
||||
loop_var_value = eval_node_get_int_val(node->loop_start_limit);
|
||||
|
||||
node->loop_end_value
|
||||
= (int) eval_node_get_int_val(node->loop_end_limit);
|
||||
}
|
||||
|
||||
/* Check if we should do another loop */
|
||||
|
||||
if (loop_var_value > node->loop_end_value) {
|
||||
|
||||
/* Enough loops done */
|
||||
|
||||
thr->run_node = parent;
|
||||
} else {
|
||||
eval_node_set_int_val(node->loop_var, loop_var_value);
|
||||
|
||||
thr->run_node = node->stat_list;
|
||||
}
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of an exit statement node. */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
exit_step(
|
||||
/*======*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
exit_node_t* node;
|
||||
que_node_t* loop_node;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_EXIT);
|
||||
|
||||
/* Loops exit by setting thr->run_node as the loop node's parent, so
|
||||
find our containing loop node and get its parent. */
|
||||
|
||||
loop_node = que_node_get_containing_loop_node(node);
|
||||
|
||||
/* If someone uses an EXIT statement outside of a loop, this will
|
||||
trigger. */
|
||||
ut_a(loop_node);
|
||||
|
||||
thr->run_node = que_node_get_parent(loop_node);
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Performs an execution step of a return-statement node. */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
return_step(
|
||||
/*========*/
|
||||
/* out: query thread to run next or NULL */
|
||||
que_thr_t* thr) /* in: query thread */
|
||||
{
|
||||
return_node_t* node;
|
||||
que_node_t* parent;
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
node = thr->run_node;
|
||||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_RETURN);
|
||||
|
||||
parent = node;
|
||||
|
||||
while (que_node_get_type(parent) != QUE_NODE_PROC) {
|
||||
|
||||
parent = que_node_get_parent(parent);
|
||||
}
|
||||
|
||||
ut_a(parent);
|
||||
|
||||
thr->run_node = que_node_get_parent(parent);
|
||||
|
||||
return(thr);
|
||||
}
|
4817
storage/xtradb/fil/fil0fil.c
Normal file
4817
storage/xtradb/fil/fil0fil.c
Normal file
File diff suppressed because it is too large
Load Diff
4284
storage/xtradb/fsp/fsp0fsp.c
Normal file
4284
storage/xtradb/fsp/fsp0fsp.c
Normal file
File diff suppressed because it is too large
Load Diff
30
storage/xtradb/fut/fut0fut.c
Normal file
30
storage/xtradb/fut/fut0fut.c
Normal file
@ -0,0 +1,30 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
File-based utilities
|
||||
|
||||
Created 12/13/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "fut0fut.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "fut0fut.ic"
|
||||
#endif
|
||||
|
529
storage/xtradb/fut/fut0lst.c
Normal file
529
storage/xtradb/fut/fut0lst.c
Normal file
@ -0,0 +1,529 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**********************************************************************
|
||||
File-based list utilities
|
||||
|
||||
Created 11/28/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "fut0lst.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "fut0lst.ic"
|
||||
#endif
|
||||
|
||||
#include "buf0buf.h"
|
||||
#include "page0page.h"
|
||||
|
||||
/************************************************************************
|
||||
Adds a node to an empty list. */
|
||||
static
|
||||
void
|
||||
flst_add_to_empty(
|
||||
/*==============*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of
|
||||
empty list */
|
||||
flst_node_t* node, /* in: node to add */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
fil_addr_t node_addr;
|
||||
ulint len;
|
||||
|
||||
ut_ad(mtr && base && node);
|
||||
ut_ad(base != node);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX));
|
||||
len = flst_get_len(base, mtr);
|
||||
ut_a(len == 0);
|
||||
|
||||
buf_ptr_get_fsp_addr(node, &space, &node_addr);
|
||||
|
||||
/* Update first and last fields of base node */
|
||||
flst_write_addr(base + FLST_FIRST, node_addr, mtr);
|
||||
flst_write_addr(base + FLST_LAST, node_addr, mtr);
|
||||
|
||||
/* Set prev and next fields of node to add */
|
||||
flst_write_addr(node + FLST_PREV, fil_addr_null, mtr);
|
||||
flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr);
|
||||
|
||||
/* Update len of base node */
|
||||
mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Adds a node as the last node in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_add_last(
|
||||
/*==========*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node, /* in: node to add */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
fil_addr_t node_addr;
|
||||
ulint len;
|
||||
fil_addr_t last_addr;
|
||||
flst_node_t* last_node;
|
||||
|
||||
ut_ad(mtr && base && node);
|
||||
ut_ad(base != node);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX));
|
||||
len = flst_get_len(base, mtr);
|
||||
last_addr = flst_get_last(base, mtr);
|
||||
|
||||
buf_ptr_get_fsp_addr(node, &space, &node_addr);
|
||||
|
||||
/* If the list is not empty, call flst_insert_after */
|
||||
if (len != 0) {
|
||||
if (last_addr.page == node_addr.page) {
|
||||
last_node = page_align(node) + last_addr.boffset;
|
||||
} else {
|
||||
ulint zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
last_node = fut_get_ptr(space, zip_size, last_addr,
|
||||
RW_X_LATCH, mtr);
|
||||
}
|
||||
|
||||
flst_insert_after(base, last_node, node, mtr);
|
||||
} else {
|
||||
/* else call flst_add_to_empty */
|
||||
flst_add_to_empty(base, node, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Adds a node as the first node in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_add_first(
|
||||
/*===========*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node, /* in: node to add */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
fil_addr_t node_addr;
|
||||
ulint len;
|
||||
fil_addr_t first_addr;
|
||||
flst_node_t* first_node;
|
||||
|
||||
ut_ad(mtr && base && node);
|
||||
ut_ad(base != node);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node, MTR_MEMO_PAGE_X_FIX));
|
||||
len = flst_get_len(base, mtr);
|
||||
first_addr = flst_get_first(base, mtr);
|
||||
|
||||
buf_ptr_get_fsp_addr(node, &space, &node_addr);
|
||||
|
||||
/* If the list is not empty, call flst_insert_before */
|
||||
if (len != 0) {
|
||||
if (first_addr.page == node_addr.page) {
|
||||
first_node = page_align(node) + first_addr.boffset;
|
||||
} else {
|
||||
ulint zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
first_node = fut_get_ptr(space, zip_size, first_addr,
|
||||
RW_X_LATCH, mtr);
|
||||
}
|
||||
|
||||
flst_insert_before(base, node, first_node, mtr);
|
||||
} else {
|
||||
/* else call flst_add_to_empty */
|
||||
flst_add_to_empty(base, node, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Inserts a node after another in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_insert_after(
|
||||
/*==============*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node1, /* in: node to insert after */
|
||||
flst_node_t* node2, /* in: node to add */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
fil_addr_t node1_addr;
|
||||
fil_addr_t node2_addr;
|
||||
flst_node_t* node3;
|
||||
fil_addr_t node3_addr;
|
||||
ulint len;
|
||||
|
||||
ut_ad(mtr && node1 && node2 && base);
|
||||
ut_ad(base != node1);
|
||||
ut_ad(base != node2);
|
||||
ut_ad(node2 != node1);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node1, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
buf_ptr_get_fsp_addr(node1, &space, &node1_addr);
|
||||
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
|
||||
|
||||
node3_addr = flst_get_next_addr(node1, mtr);
|
||||
|
||||
/* Set prev and next fields of node2 */
|
||||
flst_write_addr(node2 + FLST_PREV, node1_addr, mtr);
|
||||
flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);
|
||||
|
||||
if (!fil_addr_is_null(node3_addr)) {
|
||||
/* Update prev field of node3 */
|
||||
ulint zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
node3 = fut_get_ptr(space, zip_size,
|
||||
node3_addr, RW_X_LATCH, mtr);
|
||||
flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
|
||||
} else {
|
||||
/* node1 was last in list: update last field in base */
|
||||
flst_write_addr(base + FLST_LAST, node2_addr, mtr);
|
||||
}
|
||||
|
||||
/* Set next field of node1 */
|
||||
flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
|
||||
|
||||
/* Update len of base node */
|
||||
len = flst_get_len(base, mtr);
|
||||
mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Inserts a node before another in a list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_insert_before(
|
||||
/*===============*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node2, /* in: node to insert */
|
||||
flst_node_t* node3, /* in: node to insert before */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
flst_node_t* node1;
|
||||
fil_addr_t node1_addr;
|
||||
fil_addr_t node2_addr;
|
||||
fil_addr_t node3_addr;
|
||||
ulint len;
|
||||
|
||||
ut_ad(mtr && node2 && node3 && base);
|
||||
ut_ad(base != node2);
|
||||
ut_ad(base != node3);
|
||||
ut_ad(node2 != node3);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node3, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
|
||||
buf_ptr_get_fsp_addr(node3, &space, &node3_addr);
|
||||
|
||||
node1_addr = flst_get_prev_addr(node3, mtr);
|
||||
|
||||
/* Set prev and next fields of node2 */
|
||||
flst_write_addr(node2 + FLST_PREV, node1_addr, mtr);
|
||||
flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);
|
||||
|
||||
if (!fil_addr_is_null(node1_addr)) {
|
||||
ulint zip_size = fil_space_get_zip_size(space);
|
||||
/* Update next field of node1 */
|
||||
node1 = fut_get_ptr(space, zip_size, node1_addr,
|
||||
RW_X_LATCH, mtr);
|
||||
flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
|
||||
} else {
|
||||
/* node3 was first in list: update first field in base */
|
||||
flst_write_addr(base + FLST_FIRST, node2_addr, mtr);
|
||||
}
|
||||
|
||||
/* Set prev field of node3 */
|
||||
flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
|
||||
|
||||
/* Update len of base node */
|
||||
len = flst_get_len(base, mtr);
|
||||
mlog_write_ulint(base + FLST_LEN, len + 1, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Removes a node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_remove(
|
||||
/*========*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node2, /* in: node to remove */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
ulint zip_size;
|
||||
flst_node_t* node1;
|
||||
fil_addr_t node1_addr;
|
||||
fil_addr_t node2_addr;
|
||||
flst_node_t* node3;
|
||||
fil_addr_t node3_addr;
|
||||
ulint len;
|
||||
|
||||
ut_ad(mtr && node2 && base);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
|
||||
zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
node1_addr = flst_get_prev_addr(node2, mtr);
|
||||
node3_addr = flst_get_next_addr(node2, mtr);
|
||||
|
||||
if (!fil_addr_is_null(node1_addr)) {
|
||||
|
||||
/* Update next field of node1 */
|
||||
|
||||
if (node1_addr.page == node2_addr.page) {
|
||||
|
||||
node1 = page_align(node2) + node1_addr.boffset;
|
||||
} else {
|
||||
node1 = fut_get_ptr(space, zip_size,
|
||||
node1_addr, RW_X_LATCH, mtr);
|
||||
}
|
||||
|
||||
ut_ad(node1 != node2);
|
||||
|
||||
flst_write_addr(node1 + FLST_NEXT, node3_addr, mtr);
|
||||
} else {
|
||||
/* node2 was first in list: update first field in base */
|
||||
flst_write_addr(base + FLST_FIRST, node3_addr, mtr);
|
||||
}
|
||||
|
||||
if (!fil_addr_is_null(node3_addr)) {
|
||||
/* Update prev field of node3 */
|
||||
|
||||
if (node3_addr.page == node2_addr.page) {
|
||||
|
||||
node3 = page_align(node2) + node3_addr.boffset;
|
||||
} else {
|
||||
node3 = fut_get_ptr(space, zip_size,
|
||||
node3_addr, RW_X_LATCH, mtr);
|
||||
}
|
||||
|
||||
ut_ad(node2 != node3);
|
||||
|
||||
flst_write_addr(node3 + FLST_PREV, node1_addr, mtr);
|
||||
} else {
|
||||
/* node2 was last in list: update last field in base */
|
||||
flst_write_addr(base + FLST_LAST, node1_addr, mtr);
|
||||
}
|
||||
|
||||
/* Update len of base node */
|
||||
len = flst_get_len(base, mtr);
|
||||
ut_ad(len > 0);
|
||||
|
||||
mlog_write_ulint(base + FLST_LEN, len - 1, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Cuts off the tail of the list, including the node given. The number of
|
||||
nodes which will be removed must be provided by the caller, as this function
|
||||
does not measure the length of the tail. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_cut_end(
|
||||
/*=========*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node2, /* in: first node to remove */
|
||||
ulint n_nodes,/* in: number of nodes to remove,
|
||||
must be >= 1 */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
ulint space;
|
||||
flst_node_t* node1;
|
||||
fil_addr_t node1_addr;
|
||||
fil_addr_t node2_addr;
|
||||
ulint len;
|
||||
|
||||
ut_ad(mtr && node2 && base);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(n_nodes > 0);
|
||||
|
||||
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
|
||||
|
||||
node1_addr = flst_get_prev_addr(node2, mtr);
|
||||
|
||||
if (!fil_addr_is_null(node1_addr)) {
|
||||
|
||||
/* Update next field of node1 */
|
||||
|
||||
if (node1_addr.page == node2_addr.page) {
|
||||
|
||||
node1 = page_align(node2) + node1_addr.boffset;
|
||||
} else {
|
||||
node1 = fut_get_ptr(space,
|
||||
fil_space_get_zip_size(space),
|
||||
node1_addr, RW_X_LATCH, mtr);
|
||||
}
|
||||
|
||||
flst_write_addr(node1 + FLST_NEXT, fil_addr_null, mtr);
|
||||
} else {
|
||||
/* node2 was first in list: update the field in base */
|
||||
flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
|
||||
}
|
||||
|
||||
flst_write_addr(base + FLST_LAST, node1_addr, mtr);
|
||||
|
||||
/* Update len of base node */
|
||||
len = flst_get_len(base, mtr);
|
||||
ut_ad(len >= n_nodes);
|
||||
|
||||
mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Cuts off the tail of the list, not including the given node. The number of
|
||||
nodes which will be removed must be provided by the caller, as this function
|
||||
does not measure the length of the tail. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_truncate_end(
|
||||
/*==============*/
|
||||
flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
flst_node_t* node2, /* in: first node not to remove */
|
||||
ulint n_nodes,/* in: number of nodes to remove */
|
||||
mtr_t* mtr) /* in: mini-transaction handle */
|
||||
{
|
||||
fil_addr_t node2_addr;
|
||||
ulint len;
|
||||
ulint space;
|
||||
|
||||
ut_ad(mtr && node2 && base);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, node2, MTR_MEMO_PAGE_X_FIX));
|
||||
if (n_nodes == 0) {
|
||||
|
||||
ut_ad(fil_addr_is_null(flst_get_next_addr(node2, mtr)));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
|
||||
|
||||
/* Update next field of node2 */
|
||||
flst_write_addr(node2 + FLST_NEXT, fil_addr_null, mtr);
|
||||
|
||||
flst_write_addr(base + FLST_LAST, node2_addr, mtr);
|
||||
|
||||
/* Update len of base node */
|
||||
len = flst_get_len(base, mtr);
|
||||
ut_ad(len >= n_nodes);
|
||||
|
||||
mlog_write_ulint(base + FLST_LEN, len - n_nodes, MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Validates a file-based list. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
flst_validate(
|
||||
/*==========*/
|
||||
/* out: TRUE if ok */
|
||||
const flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
mtr_t* mtr1) /* in: mtr */
|
||||
{
|
||||
ulint space;
|
||||
ulint zip_size;
|
||||
const flst_node_t* node;
|
||||
fil_addr_t node_addr;
|
||||
fil_addr_t base_addr;
|
||||
ulint len;
|
||||
ulint i;
|
||||
mtr_t mtr2;
|
||||
|
||||
ut_ad(base);
|
||||
ut_ad(mtr_memo_contains_page(mtr1, base, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
/* We use two mini-transaction handles: the first is used to
|
||||
lock the base node, and prevent other threads from modifying the
|
||||
list. The second is used to traverse the list. We cannot run the
|
||||
second mtr without committing it at times, because if the list
|
||||
is long, then the x-locked pages could fill the buffer resulting
|
||||
in a deadlock. */
|
||||
|
||||
/* Find out the space id */
|
||||
buf_ptr_get_fsp_addr(base, &space, &base_addr);
|
||||
zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
len = flst_get_len(base, mtr1);
|
||||
node_addr = flst_get_first(base, mtr1);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
mtr_start(&mtr2);
|
||||
|
||||
node = fut_get_ptr(space, zip_size,
|
||||
node_addr, RW_X_LATCH, &mtr2);
|
||||
node_addr = flst_get_next_addr(node, &mtr2);
|
||||
|
||||
mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer
|
||||
becoming full */
|
||||
}
|
||||
|
||||
ut_a(fil_addr_is_null(node_addr));
|
||||
|
||||
node_addr = flst_get_last(base, mtr1);
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
mtr_start(&mtr2);
|
||||
|
||||
node = fut_get_ptr(space, zip_size,
|
||||
node_addr, RW_X_LATCH, &mtr2);
|
||||
node_addr = flst_get_prev_addr(node, &mtr2);
|
||||
|
||||
mtr_commit(&mtr2); /* Commit mtr2 each round to prevent buffer
|
||||
becoming full */
|
||||
}
|
||||
|
||||
ut_a(fil_addr_is_null(node_addr));
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Prints info of a file-based list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
flst_print(
|
||||
/*=======*/
|
||||
const flst_base_node_t* base, /* in: pointer to base node of list */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
const buf_frame_t* frame;
|
||||
ulint len;
|
||||
|
||||
ut_ad(base && mtr);
|
||||
ut_ad(mtr_memo_contains_page(mtr, base, MTR_MEMO_PAGE_X_FIX));
|
||||
frame = page_align((byte*) base);
|
||||
|
||||
len = flst_get_len(base, mtr);
|
||||
|
||||
fprintf(stderr,
|
||||
"FILE-BASED LIST:\n"
|
||||
"Base node in space %lu page %lu byte offset %lu; len %lu\n",
|
||||
(ulong) page_get_space_id(frame),
|
||||
(ulong) page_get_page_no(frame),
|
||||
(ulong) page_offset(base), (ulong) len);
|
||||
}
|
442
storage/xtradb/ha/ha0ha.c
Normal file
442
storage/xtradb/ha/ha0ha.c
Normal file
@ -0,0 +1,442 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/************************************************************************
|
||||
The hash table with external chains
|
||||
|
||||
Created 8/22/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "ha0ha.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "ha0ha.ic"
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
# include "buf0buf.h"
|
||||
#endif /* UNIV_DEBUG */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
# include "btr0sea.h"
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
#include "page0page.h"
|
||||
|
||||
/*****************************************************************
|
||||
Creates a hash table with >= n array cells. The actual number of cells is
|
||||
chosen to be a prime number slightly bigger than n. */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
ha_create_func(
|
||||
/*===========*/
|
||||
/* out, own: created table */
|
||||
ulint n, /* in: number of array cells */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint mutex_level, /* in: level of the mutexes in the latching
|
||||
order: this is used in the debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_mutexes) /* in: number of mutexes to protect the
|
||||
hash table: must be a power of 2, or 0 */
|
||||
{
|
||||
hash_table_t* table;
|
||||
ulint i;
|
||||
|
||||
table = hash_create(n);
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
table->adaptive = TRUE;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
/* Creating MEM_HEAP_BTR_SEARCH type heaps can potentially fail,
|
||||
but in practise it never should in this case, hence the asserts. */
|
||||
|
||||
if (n_mutexes == 0) {
|
||||
table->heap = mem_heap_create_in_btr_search(
|
||||
ut_min(4096, MEM_MAX_ALLOC_IN_BUF));
|
||||
ut_a(table->heap);
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
hash_create_mutexes(table, n_mutexes, mutex_level);
|
||||
|
||||
table->heaps = mem_alloc(n_mutexes * sizeof(void*));
|
||||
|
||||
for (i = 0; i < n_mutexes; i++) {
|
||||
table->heaps[i] = mem_heap_create_in_btr_search(4096);
|
||||
ut_a(table->heaps[i]);
|
||||
}
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Empties a hash table and frees the memory heaps. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_clear(
|
||||
/*=====*/
|
||||
hash_table_t* table) /* in, own: hash table */
|
||||
{
|
||||
ulint i;
|
||||
ulint n;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
/* Free the memory heaps. */
|
||||
n = table->n_mutexes;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
mem_heap_free(table->heaps[i]);
|
||||
}
|
||||
|
||||
/* Clear the hash table. */
|
||||
n = hash_get_n_cells(table);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
hash_get_nth_cell(table, i)->node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Inserts an entry into a hash table. If an entry with the same fold number
|
||||
is found, its node is updated to point to the new data, and no new node
|
||||
is inserted. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_insert_for_fold_func(
|
||||
/*====================*/
|
||||
/* out: TRUE if succeed, FALSE if no more
|
||||
memory could be allocated */
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold, /* in: folded value of data; if a node with
|
||||
the same fold value already exists, it is
|
||||
updated to point to the same data, and no new
|
||||
node is created! */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* block, /* in: buffer block containing the data */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
void* data) /* in: data, must not be NULL */
|
||||
{
|
||||
hash_cell_t* cell;
|
||||
ha_node_t* node;
|
||||
ha_node_t* prev_node;
|
||||
ulint hash;
|
||||
|
||||
ut_ad(table && data);
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
ut_a(block->frame == page_align(data));
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
|
||||
hash = hash_calc_hash(fold, table);
|
||||
|
||||
cell = hash_get_nth_cell(table, hash);
|
||||
|
||||
prev_node = cell->node;
|
||||
|
||||
while (prev_node != NULL) {
|
||||
if (prev_node->fold == fold) {
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
if (table->adaptive) {
|
||||
buf_block_t* prev_block = prev_node->block;
|
||||
ut_a(prev_block->frame
|
||||
== page_align(prev_node->data));
|
||||
ut_a(prev_block->n_pointers > 0);
|
||||
prev_block->n_pointers--;
|
||||
block->n_pointers++;
|
||||
}
|
||||
|
||||
prev_node->block = block;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
prev_node->data = data;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
prev_node = prev_node->next;
|
||||
}
|
||||
|
||||
/* We have to allocate a new chain node */
|
||||
|
||||
node = mem_heap_alloc(hash_get_heap(table, fold), sizeof(ha_node_t));
|
||||
|
||||
if (node == NULL) {
|
||||
/* It was a btr search type memory heap and at the moment
|
||||
no more memory could be allocated: return */
|
||||
|
||||
ut_ad(hash_get_heap(table, fold)->type & MEM_HEAP_BTR_SEARCH);
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
ha_node_set_data(node, block, data);
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
if (table->adaptive) {
|
||||
block->n_pointers++;
|
||||
}
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
node->fold = fold;
|
||||
|
||||
node->next = NULL;
|
||||
|
||||
prev_node = cell->node;
|
||||
|
||||
if (prev_node == NULL) {
|
||||
|
||||
cell->node = node;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
while (prev_node->next != NULL) {
|
||||
|
||||
prev_node = prev_node->next;
|
||||
}
|
||||
|
||||
prev_node->next = node;
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
Deletes a hash node. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_delete_hash_node(
|
||||
/*================*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ha_node_t* del_node) /* in: node to be deleted */
|
||||
{
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
if (table->adaptive) {
|
||||
ut_a(del_node->block->frame = page_align(del_node->data));
|
||||
ut_a(del_node->block->n_pointers > 0);
|
||||
del_node->block->n_pointers--;
|
||||
}
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_node);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Deletes an entry from a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_delete(
|
||||
/*======*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold, /* in: folded value of data */
|
||||
void* data) /* in: data, must not be NULL and must exist
|
||||
in the hash table */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
|
||||
node = ha_search_with_data(table, fold, data);
|
||||
|
||||
ut_a(node);
|
||||
|
||||
ha_delete_hash_node(table, node);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
Looks for an element when we know the pointer to the data, and updates
|
||||
the pointer to data, if found. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_search_and_update_if_found_func(
|
||||
/*===============================*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold, /* in: folded value of the searched data */
|
||||
void* data, /* in: pointer to the data */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
buf_block_t* new_block,/* in: block containing new_data */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
void* new_data)/* in: new pointer to the data */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
ut_a(new_block->frame == page_align(new_data));
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
|
||||
node = ha_search_with_data(table, fold, data);
|
||||
|
||||
if (node) {
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
if (table->adaptive) {
|
||||
ut_a(node->block->n_pointers > 0);
|
||||
node->block->n_pointers--;
|
||||
new_block->n_pointers++;
|
||||
}
|
||||
|
||||
node->block = new_block;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
node->data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Removes from the chain determined by fold all nodes whose data pointer
|
||||
points to the page given. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_remove_all_nodes_to_page(
|
||||
/*========================*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold, /* in: fold value */
|
||||
const page_t* page) /* in: buffer page */
|
||||
{
|
||||
ha_node_t* node;
|
||||
|
||||
ut_ad(!table->mutexes || mutex_own(hash_get_mutex(table, fold)));
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
|
||||
while (node) {
|
||||
if (page_align(ha_node_get_data(node)) == page) {
|
||||
|
||||
/* Remove the hash node */
|
||||
|
||||
ha_delete_hash_node(table, node);
|
||||
|
||||
/* Start again from the first node in the chain
|
||||
because the deletion may compact the heap of
|
||||
nodes and move other nodes! */
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
} else {
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
}
|
||||
#ifdef UNIV_DEBUG
|
||||
/* Check that all nodes really got deleted */
|
||||
|
||||
node = ha_chain_get_first(table, fold);
|
||||
|
||||
while (node) {
|
||||
ut_a(page_align(ha_node_get_data(node)) != page);
|
||||
|
||||
node = ha_chain_get_next(node);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Validates a given range of the cells in hash table. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_validate(
|
||||
/*========*/
|
||||
/* out: TRUE if ok */
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint start_index, /* in: start index */
|
||||
ulint end_index) /* in: end index */
|
||||
{
|
||||
hash_cell_t* cell;
|
||||
ha_node_t* node;
|
||||
ibool ok = TRUE;
|
||||
ulint i;
|
||||
|
||||
ut_a(start_index <= end_index);
|
||||
ut_a(start_index < hash_get_n_cells(table));
|
||||
ut_a(end_index < hash_get_n_cells(table));
|
||||
|
||||
for (i = start_index; i <= end_index; i++) {
|
||||
|
||||
cell = hash_get_nth_cell(table, i);
|
||||
|
||||
node = cell->node;
|
||||
|
||||
while (node) {
|
||||
if (hash_calc_hash(node->fold, table) != i) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: hash table node"
|
||||
" fold value %lu does not\n"
|
||||
"InnoDB: match the cell number %lu.\n",
|
||||
(ulong) node->fold, (ulong) i);
|
||||
|
||||
ok = FALSE;
|
||||
}
|
||||
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
||||
return(ok);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Prints info of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
ha_print_info(
|
||||
/*==========*/
|
||||
FILE* file, /* in: file where to print */
|
||||
hash_table_t* table) /* in: hash table */
|
||||
{
|
||||
#ifdef UNIV_DEBUG
|
||||
/* Some of the code here is disabled for performance reasons in production
|
||||
builds, see http://bugs.mysql.com/36941 */
|
||||
#define PRINT_USED_CELLS
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
#ifdef PRINT_USED_CELLS
|
||||
hash_cell_t* cell;
|
||||
ulint cells = 0;
|
||||
ulint i;
|
||||
#endif /* PRINT_USED_CELLS */
|
||||
ulint n_bufs;
|
||||
|
||||
#ifdef PRINT_USED_CELLS
|
||||
for (i = 0; i < hash_get_n_cells(table); i++) {
|
||||
|
||||
cell = hash_get_nth_cell(table, i);
|
||||
|
||||
if (cell->node) {
|
||||
|
||||
cells++;
|
||||
}
|
||||
}
|
||||
#endif /* PRINT_USED_CELLS */
|
||||
|
||||
fprintf(file, "Hash table size %lu",
|
||||
(ulong) hash_get_n_cells(table));
|
||||
|
||||
#ifdef PRINT_USED_CELLS
|
||||
fprintf(file, ", used cells %lu", (ulong) cells);
|
||||
#endif /* PRINT_USED_CELLS */
|
||||
|
||||
if (table->heaps == NULL && table->heap != NULL) {
|
||||
|
||||
/* This calculation is intended for the adaptive hash
|
||||
index: how many buffer frames we have reserved? */
|
||||
|
||||
n_bufs = UT_LIST_GET_LEN(table->heap->base) - 1;
|
||||
|
||||
if (table->heap->free_block) {
|
||||
n_bufs++;
|
||||
}
|
||||
|
||||
fprintf(file, ", node heap has %lu buffer(s)\n",
|
||||
(ulong) n_bufs);
|
||||
}
|
||||
}
|
183
storage/xtradb/ha/ha0storage.c
Normal file
183
storage/xtradb/ha/ha0storage.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
Hash storage.
|
||||
Provides a data structure that stores chunks of data in
|
||||
its own storage, avoiding duplicates.
|
||||
|
||||
Created September 22, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#include "univ.i"
|
||||
#include "ha0storage.h"
|
||||
#include "hash0hash.h"
|
||||
#include "mem0mem.h"
|
||||
#include "ut0rnd.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "ha0storage.ic"
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
Retrieves a data from a storage. If it is present, a pointer to the
|
||||
stored copy of data is returned, otherwise NULL is returned. */
|
||||
static
|
||||
const void*
|
||||
ha_storage_get(
|
||||
/*===========*/
|
||||
ha_storage_t* storage, /* in: hash storage */
|
||||
const void* data, /* in: data to check for */
|
||||
ulint data_len) /* in: data length */
|
||||
{
|
||||
ha_storage_node_t* node;
|
||||
ulint fold;
|
||||
|
||||
/* avoid repetitive calls to ut_fold_binary() in the HASH_SEARCH
|
||||
macro */
|
||||
fold = ut_fold_binary(data, data_len);
|
||||
|
||||
#define IS_FOUND \
|
||||
node->data_len == data_len && memcmp(node->data, data, data_len) == 0
|
||||
|
||||
HASH_SEARCH(
|
||||
next, /* node->"next" */
|
||||
storage->hash, /* the hash table */
|
||||
fold, /* key */
|
||||
ha_storage_node_t*, /* type of node->next */
|
||||
node, /* auxiliary variable */
|
||||
, /* assertion */
|
||||
IS_FOUND); /* search criteria */
|
||||
|
||||
if (node == NULL) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
/* else */
|
||||
|
||||
return(node->data);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Copies data into the storage and returns a pointer to the copy. If the
|
||||
same data chunk is already present, then pointer to it is returned.
|
||||
Data chunks are considered to be equal if len1 == len2 and
|
||||
memcmp(data1, data2, len1) == 0. If "data" is not present (and thus
|
||||
data_len bytes need to be allocated) and the size of storage is going to
|
||||
become more than "memlim" then "data" is not added and NULL is returned.
|
||||
To disable this behavior "memlim" can be set to 0, which stands for
|
||||
"no limit". */
|
||||
UNIV_INTERN
|
||||
const void*
|
||||
ha_storage_put_memlim(
|
||||
/*==================*/
|
||||
ha_storage_t* storage, /* in/out: hash storage */
|
||||
const void* data, /* in: data to store */
|
||||
ulint data_len, /* in: data length */
|
||||
ulint memlim) /* in: memory limit to obey */
|
||||
{
|
||||
void* raw;
|
||||
ha_storage_node_t* node;
|
||||
const void* data_copy;
|
||||
ulint fold;
|
||||
|
||||
/* check if data chunk is already present */
|
||||
data_copy = ha_storage_get(storage, data, data_len);
|
||||
if (data_copy != NULL) {
|
||||
|
||||
return(data_copy);
|
||||
}
|
||||
|
||||
/* not present */
|
||||
|
||||
/* check if we are allowed to allocate data_len bytes */
|
||||
if (memlim > 0
|
||||
&& ha_storage_get_size(storage) + data_len > memlim) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* we put the auxiliary node struct and the data itself in one
|
||||
continuous block */
|
||||
raw = mem_heap_alloc(storage->heap,
|
||||
sizeof(ha_storage_node_t) + data_len);
|
||||
|
||||
node = (ha_storage_node_t*) raw;
|
||||
data_copy = (byte*) raw + sizeof(*node);
|
||||
|
||||
memcpy((byte*) raw + sizeof(*node), data, data_len);
|
||||
|
||||
node->data_len = data_len;
|
||||
node->data = data_copy;
|
||||
|
||||
/* avoid repetitive calls to ut_fold_binary() in the HASH_INSERT
|
||||
macro */
|
||||
fold = ut_fold_binary(data, data_len);
|
||||
|
||||
HASH_INSERT(
|
||||
ha_storage_node_t, /* type used in the hash chain */
|
||||
next, /* node->"next" */
|
||||
storage->hash, /* the hash table */
|
||||
fold, /* key */
|
||||
node); /* add this data to the hash */
|
||||
|
||||
/* the output should not be changed because it will spoil the
|
||||
hash table */
|
||||
return(data_copy);
|
||||
}
|
||||
|
||||
#ifdef UNIV_COMPILE_TEST_FUNCS
|
||||
|
||||
void
|
||||
test_ha_storage()
|
||||
{
|
||||
ha_storage_t* storage;
|
||||
char buf[1024];
|
||||
int i;
|
||||
const void* stored[256];
|
||||
const void* p;
|
||||
|
||||
storage = ha_storage_create(0, 0);
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
|
||||
memset(buf, i, sizeof(buf));
|
||||
stored[i] = ha_storage_put(storage, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
//ha_storage_empty(&storage);
|
||||
|
||||
for (i = 255; i >= 0; i--) {
|
||||
|
||||
memset(buf, i, sizeof(buf));
|
||||
p = ha_storage_put(storage, buf, sizeof(buf));
|
||||
|
||||
if (p != stored[i]) {
|
||||
|
||||
fprintf(stderr, "ha_storage_put() returned %p "
|
||||
"instead of %p, i=%d\n", p, stored[i], i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "all ok\n");
|
||||
|
||||
ha_storage_free(storage);
|
||||
}
|
||||
|
||||
#endif /* UNIV_COMPILE_TEST_FUNCS */
|
165
storage/xtradb/ha/hash0hash.c
Normal file
165
storage/xtradb/ha/hash0hash.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
The simple hash table utility
|
||||
|
||||
Created 5/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "hash0hash.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "hash0hash.ic"
|
||||
#endif
|
||||
|
||||
#include "mem0mem.h"
|
||||
|
||||
/****************************************************************
|
||||
Reserves the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter(
|
||||
/*=============*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold) /* in: fold */
|
||||
{
|
||||
mutex_enter(hash_get_mutex(table, fold));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Releases the mutex for a fold value in a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit(
|
||||
/*============*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
ulint fold) /* in: fold */
|
||||
{
|
||||
mutex_exit(hash_get_mutex(table, fold));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Reserves all the mutexes of a hash table, in an ascending order. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_enter_all(
|
||||
/*=================*/
|
||||
hash_table_t* table) /* in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < table->n_mutexes; i++) {
|
||||
|
||||
mutex_enter(table->mutexes + i);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Releases all the mutexes of a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_mutex_exit_all(
|
||||
/*================*/
|
||||
hash_table_t* table) /* in: hash table */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < table->n_mutexes; i++) {
|
||||
|
||||
mutex_exit(table->mutexes + i);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Creates a hash table with >= n array cells. The actual number of cells is
|
||||
chosen to be a prime number slightly bigger than n. */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
hash_create(
|
||||
/*========*/
|
||||
/* out, own: created table */
|
||||
ulint n) /* in: number of array cells */
|
||||
{
|
||||
hash_cell_t* array;
|
||||
ulint prime;
|
||||
hash_table_t* table;
|
||||
|
||||
prime = ut_find_prime(n);
|
||||
|
||||
table = mem_alloc(sizeof(hash_table_t));
|
||||
|
||||
array = ut_malloc(sizeof(hash_cell_t) * prime);
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
table->adaptive = FALSE;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
table->array = array;
|
||||
table->n_cells = prime;
|
||||
table->n_mutexes = 0;
|
||||
table->mutexes = NULL;
|
||||
table->heaps = NULL;
|
||||
table->heap = NULL;
|
||||
table->magic_n = HASH_TABLE_MAGIC_N;
|
||||
|
||||
/* Initialize the cell array */
|
||||
hash_table_clear(table);
|
||||
|
||||
return(table);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Frees a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_table_free(
|
||||
/*============*/
|
||||
hash_table_t* table) /* in, own: hash table */
|
||||
{
|
||||
ut_a(table->mutexes == NULL);
|
||||
|
||||
ut_free(table->array);
|
||||
mem_free(table);
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
Creates a mutex array to protect a hash table. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
hash_create_mutexes_func(
|
||||
/*=====================*/
|
||||
hash_table_t* table, /* in: hash table */
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ulint sync_level, /* in: latching order level of the
|
||||
mutexes: used in the debug version */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
ulint n_mutexes) /* in: number of mutexes, must be a
|
||||
power of 2 */
|
||||
{
|
||||
ulint i;
|
||||
|
||||
ut_a(n_mutexes > 0);
|
||||
ut_a(ut_is_2pow(n_mutexes));
|
||||
|
||||
table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t));
|
||||
|
||||
for (i = 0; i < n_mutexes; i++) {
|
||||
mutex_create(table->mutexes + i, sync_level);
|
||||
}
|
||||
|
||||
table->n_mutexes = n_mutexes;
|
||||
}
|
4
storage/xtradb/ha_innodb.def
Normal file
4
storage/xtradb/ha_innodb.def
Normal file
@ -0,0 +1,4 @@
|
||||
EXPORTS
|
||||
_mysql_plugin_interface_version_
|
||||
_mysql_sizeof_struct_st_plugin_
|
||||
_mysql_plugin_declarations_
|
10394
storage/xtradb/handler/ha_innodb.cc
Normal file
10394
storage/xtradb/handler/ha_innodb.cc
Normal file
File diff suppressed because it is too large
Load Diff
283
storage/xtradb/handler/ha_innodb.h
Normal file
283
storage/xtradb/handler/ha_innodb.h
Normal file
@ -0,0 +1,283 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
This file is based on ha_berkeley.h of MySQL distribution
|
||||
|
||||
This file defines the Innodb handler: the interface between MySQL and
|
||||
Innodb
|
||||
*/
|
||||
|
||||
#ifdef USE_PRAGMA_INTERFACE
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
typedef struct st_innobase_share {
|
||||
THR_LOCK lock;
|
||||
pthread_mutex_t mutex;
|
||||
const char* table_name;
|
||||
uint use_count;
|
||||
void* table_name_hash;
|
||||
} INNOBASE_SHARE;
|
||||
|
||||
|
||||
struct dict_index_struct;
|
||||
struct row_prebuilt_struct;
|
||||
|
||||
typedef struct dict_index_struct dict_index_t;
|
||||
typedef struct row_prebuilt_struct row_prebuilt_t;
|
||||
|
||||
/* The class defining a handle to an Innodb table */
|
||||
class ha_innobase: public handler
|
||||
{
|
||||
row_prebuilt_t* prebuilt; /* prebuilt struct in InnoDB, used
|
||||
to save CPU time with prebuilt data
|
||||
structures*/
|
||||
THD* user_thd; /* the thread handle of the user
|
||||
currently using the handle; this is
|
||||
set in external_lock function */
|
||||
THR_LOCK_DATA lock;
|
||||
INNOBASE_SHARE *share;
|
||||
|
||||
uchar* upd_buff; /* buffer used in updates */
|
||||
uchar* key_val_buff; /* buffer used in converting
|
||||
search key values from MySQL format
|
||||
to Innodb format */
|
||||
ulong upd_and_key_val_buff_len;
|
||||
/* the length of each of the previous
|
||||
two buffers */
|
||||
Table_flags int_table_flags;
|
||||
uint primary_key;
|
||||
ulong start_of_scan; /* this is set to 1 when we are
|
||||
starting a table scan but have not
|
||||
yet fetched any row, else 0 */
|
||||
uint last_match_mode;/* match mode of the latest search:
|
||||
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
|
||||
or undefined */
|
||||
uint num_write_row; /* number of write_row() calls */
|
||||
|
||||
uint store_key_val_for_row(uint keynr, char* buff, uint buff_len,
|
||||
const uchar* record);
|
||||
inline void update_thd(THD* thd);
|
||||
void update_thd();
|
||||
int change_active_index(uint keynr);
|
||||
int general_fetch(uchar* buf, uint direction, uint match_mode);
|
||||
ulint innobase_lock_autoinc();
|
||||
ulonglong innobase_peek_autoinc();
|
||||
ulint innobase_set_max_autoinc(ulonglong auto_inc);
|
||||
ulint innobase_reset_autoinc(ulonglong auto_inc);
|
||||
ulint innobase_get_autoinc(ulonglong* value);
|
||||
ulint innobase_update_autoinc(ulonglong auto_inc);
|
||||
ulint innobase_initialize_autoinc();
|
||||
dict_index_t* innobase_get_index(uint keynr);
|
||||
ulonglong innobase_get_int_col_max_value(const Field* field);
|
||||
|
||||
/* Init values for the class: */
|
||||
public:
|
||||
ha_innobase(handlerton *hton, TABLE_SHARE *table_arg);
|
||||
~ha_innobase();
|
||||
/*
|
||||
Get the row type from the storage engine. If this method returns
|
||||
ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used.
|
||||
*/
|
||||
enum row_type get_row_type() const;
|
||||
|
||||
const char* table_type() const;
|
||||
const char* index_type(uint key_number);
|
||||
const char** bas_ext() const;
|
||||
Table_flags table_flags() const;
|
||||
ulong index_flags(uint idx, uint part, bool all_parts) const;
|
||||
uint max_supported_keys() const;
|
||||
uint max_supported_key_length() const;
|
||||
uint max_supported_key_part_length() const;
|
||||
const key_map* keys_to_use_for_scanning();
|
||||
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
int close(void);
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
|
||||
int write_row(uchar * buf);
|
||||
int update_row(const uchar * old_data, uchar * new_data);
|
||||
int delete_row(const uchar * buf);
|
||||
bool was_semi_consistent_read();
|
||||
void try_semi_consistent_read(bool yes);
|
||||
void unlock_row();
|
||||
|
||||
#ifdef ROW_MERGE_IS_INDEX_USABLE
|
||||
/** Check if an index can be used by this transaction.
|
||||
* @param keynr key number to check
|
||||
* @return true if available, false if the index
|
||||
* does not contain old records that exist
|
||||
* in the read view of this transaction */
|
||||
bool is_index_available(uint keynr);
|
||||
#endif /* ROW_MERGE_IS_INDEX_USABLE */
|
||||
int index_init(uint index, bool sorted);
|
||||
int index_end();
|
||||
int index_read(uchar * buf, const uchar * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_idx(uchar * buf, uint index, const uchar * key,
|
||||
uint key_len, enum ha_rkey_function find_flag);
|
||||
int index_read_last(uchar * buf, const uchar * key, uint key_len);
|
||||
int index_next(uchar * buf);
|
||||
int index_next_same(uchar * buf, const uchar *key, uint keylen);
|
||||
int index_prev(uchar * buf);
|
||||
int index_first(uchar * buf);
|
||||
int index_last(uchar * buf);
|
||||
|
||||
int rnd_init(bool scan);
|
||||
int rnd_end();
|
||||
int rnd_next(uchar *buf);
|
||||
int rnd_pos(uchar * buf, uchar *pos);
|
||||
|
||||
void position(const uchar *record);
|
||||
int info(uint);
|
||||
int analyze(THD* thd,HA_CHECK_OPT* check_opt);
|
||||
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
|
||||
int discard_or_import_tablespace(my_bool discard);
|
||||
int extra(enum ha_extra_function operation);
|
||||
int reset();
|
||||
int external_lock(THD *thd, int lock_type);
|
||||
int transactional_table_lock(THD *thd, int lock_type);
|
||||
int start_stmt(THD *thd, thr_lock_type lock_type);
|
||||
void position(uchar *record);
|
||||
ha_rows records_in_range(uint inx, key_range *min_key, key_range
|
||||
*max_key);
|
||||
ha_rows estimate_rows_upper_bound();
|
||||
|
||||
void update_create_info(HA_CREATE_INFO* create_info);
|
||||
int create(const char *name, register TABLE *form,
|
||||
HA_CREATE_INFO *create_info);
|
||||
int delete_all_rows();
|
||||
int delete_table(const char *name);
|
||||
int rename_table(const char* from, const char* to);
|
||||
int check(THD* thd, HA_CHECK_OPT* check_opt);
|
||||
char* update_table_comment(const char* comment);
|
||||
char* get_foreign_key_create_info();
|
||||
int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
|
||||
bool can_switch_engines();
|
||||
uint referenced_by_foreign_key();
|
||||
void free_foreign_key_create_info(char* str);
|
||||
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
|
||||
enum thr_lock_type lock_type);
|
||||
void init_table_handle_for_HANDLER();
|
||||
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
|
||||
ulonglong nb_desired_values,
|
||||
ulonglong *first_value,
|
||||
ulonglong *nb_reserved_values);
|
||||
int reset_auto_increment(ulonglong value);
|
||||
|
||||
virtual bool get_error_message(int error, String *buf);
|
||||
|
||||
uint8 table_cache_type();
|
||||
/*
|
||||
ask handler about permission to cache table during query registration
|
||||
*/
|
||||
my_bool register_query_cache_table(THD *thd, char *table_key,
|
||||
uint key_length,
|
||||
qc_engine_callback *call_back,
|
||||
ulonglong *engine_data);
|
||||
static char *get_mysql_bin_log_name();
|
||||
static ulonglong get_mysql_bin_log_pos();
|
||||
bool primary_key_is_clustered();
|
||||
int cmp_ref(const uchar *ref1, const uchar *ref2);
|
||||
/** Fast index creation (smart ALTER TABLE) @see handler0alter.cc @{ */
|
||||
int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
|
||||
int prepare_drop_index(TABLE *table_arg, uint *key_num,
|
||||
uint num_of_keys);
|
||||
int final_drop_index(TABLE *table_arg);
|
||||
/** @} */
|
||||
bool check_if_incompatible_data(HA_CREATE_INFO *info,
|
||||
uint table_changes);
|
||||
};
|
||||
|
||||
/* Some accessor functions which the InnoDB plugin needs, but which
|
||||
can not be added to mysql/plugin.h as part of the public interface;
|
||||
the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */
|
||||
|
||||
#ifndef INNODB_COMPATIBILITY_HOOKS
|
||||
#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
struct charset_info_st *thd_charset(MYSQL_THD thd);
|
||||
char **thd_query(MYSQL_THD thd);
|
||||
|
||||
/** Get the file name of the MySQL binlog.
|
||||
* @return the name of the binlog file
|
||||
*/
|
||||
const char* mysql_bin_log_file_name(void);
|
||||
|
||||
/** Get the current position of the MySQL binlog.
|
||||
* @return byte offset from the beginning of the binlog
|
||||
*/
|
||||
ulonglong mysql_bin_log_file_pos(void);
|
||||
|
||||
/**
|
||||
Check if a user thread is a replication slave thread
|
||||
@param thd user thread
|
||||
@retval 0 the user thread is not a replication slave thread
|
||||
@retval 1 the user thread is a replication slave thread
|
||||
*/
|
||||
int thd_slave_thread(const MYSQL_THD thd);
|
||||
|
||||
/**
|
||||
Check if a user thread is running a non-transactional update
|
||||
@param thd user thread
|
||||
@retval 0 the user thread is not running a non-transactional update
|
||||
@retval 1 the user thread is running a non-transactional update
|
||||
*/
|
||||
int thd_non_transactional_update(const MYSQL_THD thd);
|
||||
|
||||
/**
|
||||
Get the user thread's binary logging format
|
||||
@param thd user thread
|
||||
@return Value to be used as index into the binlog_format_names array
|
||||
*/
|
||||
int thd_binlog_format(const MYSQL_THD thd);
|
||||
|
||||
/**
|
||||
Mark transaction to rollback and mark error as fatal to a sub-statement.
|
||||
@param thd Thread handle
|
||||
@param all TRUE <=> rollback main transaction.
|
||||
*/
|
||||
void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all);
|
||||
}
|
||||
|
||||
typedef struct trx_struct trx_t;
|
||||
/************************************************************************
|
||||
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
|
||||
about a possible transaction rollback inside InnoDB caused by a lock wait
|
||||
timeout or a deadlock. */
|
||||
extern "C"
|
||||
int
|
||||
convert_error_code_to_mysql(
|
||||
/*========================*/
|
||||
/* out: MySQL error code */
|
||||
int error, /* in: InnoDB error code */
|
||||
ulint flags, /* in: InnoDB table flags, or 0 */
|
||||
MYSQL_THD thd); /* in: user thread handle or NULL */
|
||||
|
||||
/*************************************************************************
|
||||
Allocates an InnoDB transaction for a MySQL handler object. */
|
||||
extern "C"
|
||||
trx_t*
|
||||
innobase_trx_allocate(
|
||||
/*==================*/
|
||||
/* out: InnoDB transaction handle */
|
||||
MYSQL_THD thd); /* in: user thread handle */
|
1214
storage/xtradb/handler/handler0alter.cc
Normal file
1214
storage/xtradb/handler/handler0alter.cc
Normal file
File diff suppressed because it is too large
Load Diff
68
storage/xtradb/handler/handler0vars.h
Normal file
68
storage/xtradb/handler/handler0vars.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2008, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
This file contains accessor functions for dynamic plugin on Windows.
|
||||
***********************************************************************/
|
||||
|
||||
#if defined __WIN__ && defined MYSQL_DYNAMIC_PLUGIN
|
||||
/***********************************************************************
|
||||
This is a list of externals that can not be resolved by delay loading.
|
||||
They have to be resolved indirectly via their addresses in the .map file.
|
||||
All of them are external variables. */
|
||||
extern CHARSET_INFO* wdl_my_charset_bin;
|
||||
extern CHARSET_INFO* wdl_my_charset_latin1;
|
||||
extern CHARSET_INFO* wdl_my_charset_filename;
|
||||
extern CHARSET_INFO** wdl_system_charset_info;
|
||||
extern CHARSET_INFO** wdl_default_charset_info;
|
||||
extern CHARSET_INFO** wdl_all_charsets;
|
||||
extern system_variables* wdl_global_system_variables;
|
||||
extern char* wdl_mysql_real_data_home;
|
||||
extern char** wdl_mysql_data_home;
|
||||
extern char** wdl_tx_isolation_names;
|
||||
extern char** wdl_binlog_format_names;
|
||||
extern char* wdl_reg_ext;
|
||||
extern pthread_mutex_t* wdl_LOCK_thread_count;
|
||||
extern key_map* wdl_key_map_full;
|
||||
extern MY_TMPDIR* wdl_mysql_tmpdir_list;
|
||||
extern bool* wdl_mysqld_embedded;
|
||||
extern uint* wdl_lower_case_table_names;
|
||||
extern ulong* wdl_specialflag;
|
||||
extern int* wdl_my_umask;
|
||||
|
||||
#define my_charset_bin (*wdl_my_charset_bin)
|
||||
#define my_charset_latin1 (*wdl_my_charset_latin1)
|
||||
#define my_charset_filename (*wdl_my_charset_filename)
|
||||
#define system_charset_info (*wdl_system_charset_info)
|
||||
#define default_charset_info (*wdl_default_charset_info)
|
||||
#define all_charsets (wdl_all_charsets)
|
||||
#define global_system_variables (*wdl_global_system_variables)
|
||||
#define mysql_real_data_home (wdl_mysql_real_data_home)
|
||||
#define mysql_data_home (*wdl_mysql_data_home)
|
||||
#define tx_isolation_names (wdl_tx_isolation_names)
|
||||
#define binlog_format_names (wdl_binlog_format_names)
|
||||
#define reg_ext (wdl_reg_ext)
|
||||
#define LOCK_thread_count (*wdl_LOCK_thread_count)
|
||||
#define key_map_full (*wdl_key_map_full)
|
||||
#define mysql_tmpdir_list (*wdl_mysql_tmpdir_list)
|
||||
#define mysqld_embedded (*wdl_mysqld_embedded)
|
||||
#define lower_case_table_names (*wdl_lower_case_table_names)
|
||||
#define specialflag (*wdl_specialflag)
|
||||
#define my_umask (*wdl_my_umask)
|
||||
|
||||
#endif
|
2655
storage/xtradb/handler/i_s.cc
Normal file
2655
storage/xtradb/handler/i_s.cc
Normal file
File diff suppressed because it is too large
Load Diff
41
storage/xtradb/handler/i_s.h
Normal file
41
storage/xtradb/handler/i_s.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
InnoDB INFORMATION SCHEMA tables interface to MySQL.
|
||||
|
||||
Created July 18, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef i_s_h
|
||||
#define i_s_h
|
||||
|
||||
extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages;
|
||||
extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_index;
|
||||
extern struct st_mysql_plugin i_s_innodb_buffer_pool_pages_blob;
|
||||
extern struct st_mysql_plugin i_s_innodb_trx;
|
||||
extern struct st_mysql_plugin i_s_innodb_locks;
|
||||
extern struct st_mysql_plugin i_s_innodb_lock_waits;
|
||||
extern struct st_mysql_plugin i_s_innodb_cmp;
|
||||
extern struct st_mysql_plugin i_s_innodb_cmp_reset;
|
||||
extern struct st_mysql_plugin i_s_innodb_cmpmem;
|
||||
extern struct st_mysql_plugin i_s_innodb_cmpmem_reset;
|
||||
extern struct st_mysql_plugin i_s_innodb_patches;
|
||||
extern struct st_mysql_plugin i_s_innodb_rseg;
|
||||
|
||||
#endif /* i_s_h */
|
35
storage/xtradb/handler/innodb_patch_info.h
Normal file
35
storage/xtradb/handler/innodb_patch_info.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Copyright (C) 2002-2006 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 */
|
||||
|
||||
#ifdef USE_PRAGMA_INTERFACE
|
||||
#pragma interface /* gcc class implementation */
|
||||
#endif
|
||||
|
||||
struct innodb_enhancement {
|
||||
const char *file;
|
||||
const char *name;
|
||||
const char *comment;
|
||||
const char *link;
|
||||
}innodb_enhancements[] = {
|
||||
{"xtradb_show_enhancements","I_S.XTRADB_ENHANCEMENTS","","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_show_status","Improvements to SHOW INNODB STATUS","Memory information and lock info fixes","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_io","Improvements to InnoDB IO","","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_opt_lru_count","Fix of buffer_pool mutex","Decreases contention on buffer_pool mutex on LRU operations","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_buffer_pool_pages","Information of buffer pool content","","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_expand_undo_slots","expandable maximum number of undo slots","from 1024 (default) to about 4000","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_extra_rseg","allow to create extra rollback segments","When create new db, the new parameter allows to create more rollback segments","http://www.percona.com/docs/wiki/percona-xtradb"},
|
||||
{"innodb_overwrite_relay_log_info","overwrite relay-log.info when slave recovery","Building as plugin, it is not used.","http://www.percona.com/docs/wiki/percona-xtradb:innodb_overwrite_relay_log_info"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
41
storage/xtradb/handler/mysql_addons.cc
Normal file
41
storage/xtradb/handler/mysql_addons.cc
Normal file
@ -0,0 +1,41 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2007, 2009, Innobase Oy. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************
|
||||
This file contains functions that need to be added to
|
||||
MySQL code but have not been added yet.
|
||||
|
||||
Whenever you add a function here submit a MySQL bug
|
||||
report (feature request) with the implementation. Then
|
||||
write the bug number in the comment before the
|
||||
function in this file.
|
||||
|
||||
When MySQL commits the function it can be deleted from
|
||||
here. In a perfect world this file exists but is empty.
|
||||
|
||||
Created November 07, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef MYSQL_SERVER
|
||||
#define MYSQL_SERVER
|
||||
#endif /* MYSQL_SERVER */
|
||||
|
||||
#include <mysql_priv.h>
|
||||
|
||||
#include "mysql_addons.h"
|
||||
#include "univ.i"
|
1036
storage/xtradb/handler/win_delay_loader.cc
Normal file
1036
storage/xtradb/handler/win_delay_loader.cc
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user