mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge mysql-5.1-innodb_plugin to mysql-5.1.
This commit is contained in:
160
CMakeLists.txt
160
CMakeLists.txt
@@ -42,56 +42,6 @@ ADD_DEFINITIONS(-DSHAREDIR="share")
|
||||
# Set debug options
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DFORCE_INIT_OF_VARS")
|
||||
|
||||
# Note that some engines are always compiled in, MyISAM, MyISAMMRG and HEAP,
|
||||
# these three plugin defintions are dummys for symmetry
|
||||
|
||||
SET(WITH_HEAP_STORAGE_ENGINE TRUE)
|
||||
ADD_DEFINITIONS(-DWITH_HEAP_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_heap_plugin")
|
||||
|
||||
SET(WITH_MYISAM_STORAGE_ENGINE TRUE)
|
||||
ADD_DEFINITIONS(-DWITH_MYISAM_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisam_plugin")
|
||||
|
||||
SET(WITH_MYISAMMRG_STORAGE_ENGINE TRUE)
|
||||
ADD_DEFINITIONS(-DWITH_MYISAMMRG_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_myisammrg_plugin")
|
||||
|
||||
IF(WITH_COMMUNITY_FEATURES)
|
||||
ADD_DEFINITIONS(-DENABLED_PROFILING -DCOMMUNITY_SERVER)
|
||||
ENDIF(WITH_COMMUNITY_FEATURES)
|
||||
|
||||
IF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_ARCHIVE_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_archive_plugin")
|
||||
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
IF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_blackhole_plugin")
|
||||
ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
IF(WITH_CSV_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_CSV_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_csv_plugin")
|
||||
ENDIF(WITH_CSV_STORAGE_ENGINE)
|
||||
IF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_EXAMPLE_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_example_plugin")
|
||||
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
IF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_INNOBASE_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_innobase_plugin")
|
||||
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
IF(WITH_PARTITION_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_PARTITION_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
|
||||
ENDIF(WITH_PARTITION_STORAGE_ENGINE)
|
||||
IF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
ADD_DEFINITIONS(-DWITH_FEDERATED_STORAGE_ENGINE)
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_federated_plugin")
|
||||
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in
|
||||
${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc @ONLY)
|
||||
|
||||
SET(localstatedir "C:\\mysql\\data")
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/support-files/my-huge.cnf.sh
|
||||
@@ -136,6 +86,16 @@ IF(MSVC AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7")
|
||||
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /wd4996")
|
||||
ENDIF(MSVC AND NOT CMAKE_GENERATOR MATCHES "Visual Studio 7")
|
||||
|
||||
IF(CMAKE_GENERATOR MATCHES "Visual Studio 7")
|
||||
# VS2003 has a bug that prevents linking mysqld with module definition file
|
||||
# (/DEF option for linker). Linker would incorrectly complain about multiply
|
||||
# defined symbols. Workaround is to disable dynamic plugins, so /DEF is not
|
||||
# used.
|
||||
MESSAGE("Warning: Building MySQL with Visual Studio 2003.NET is no more supported.")
|
||||
MESSAGE("Please use a newer version of Visual Studio.")
|
||||
SET(WITHOUT_DYNAMIC_PLUGINS TRUE)
|
||||
ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 7")
|
||||
|
||||
# Settings for Visual Studio 7 and above.
|
||||
IF(MSVC)
|
||||
# replace /MDd with /MTd
|
||||
@@ -179,12 +139,16 @@ IF(WIN32)
|
||||
ADD_DEFINITIONS("-D_WINDOWS -D__WIN__ -D_CRT_SECURE_NO_DEPRECATE")
|
||||
ENDIF(WIN32)
|
||||
|
||||
# default to x86 platform. We'll check for X64 in a bit
|
||||
SET (PLATFORM X86)
|
||||
|
||||
# This definition is necessary to work around a bug with Intellisense described
|
||||
# here: http://tinyurl.com/2cb428. Syntax highlighting is important for proper
|
||||
# debugger functionality.
|
||||
IF(CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
MESSAGE(STATUS "Detected 64-bit platform.")
|
||||
ADD_DEFINITIONS("-D_WIN64")
|
||||
SET (PLATFORM X64)
|
||||
ENDIF(CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
|
||||
IF(EMBED_MANIFESTS)
|
||||
@@ -237,6 +201,81 @@ IF(EMBED_MANIFESTS)
|
||||
ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio 8 2005 Win64")
|
||||
ENDIF(EMBED_MANIFESTS)
|
||||
|
||||
# Figure out what engines to build and how (statically or dynamically),
|
||||
# add preprocessor defines for storage engines.
|
||||
IF(WITHOUT_DYNAMIC_PLUGINS)
|
||||
MESSAGE("Dynamic plugins are disabled.")
|
||||
ENDIF(WITHOUT_DYNAMIC_PLUGINS)
|
||||
|
||||
FILE(GLOB STORAGE_SUBDIRS storage/*)
|
||||
FOREACH(SUBDIR ${STORAGE_SUBDIRS})
|
||||
FILE(RELATIVE_PATH DIRNAME ${PROJECT_SOURCE_DIR}/storage ${SUBDIR})
|
||||
STRING(TOUPPER ${DIRNAME} ENGINE)
|
||||
STRING(TOLOWER ${DIRNAME} ENGINE_LOWER)
|
||||
IF (EXISTS ${SUBDIR}/CMakeLists.txt)
|
||||
# Check MYSQL_STORAGE_ENGINE macro is present
|
||||
FILE(STRINGS ${SUBDIR}/CMakeLists.txt HAVE_STORAGE_ENGINE REGEX MYSQL_STORAGE_ENGINE)
|
||||
IF(HAVE_STORAGE_ENGINE)
|
||||
SET(ENGINE_BUILD_TYPE "DYNAMIC")
|
||||
# Read plug.in to find out if a plugin is mandatory and whether it supports
|
||||
# build as shared library (dynamic).
|
||||
IF(EXISTS ${SUBDIR}/plug.in)
|
||||
FILE(READ ${SUBDIR}/plug.in PLUGIN_FILE_CONTENT)
|
||||
STRING (REGEX MATCH "MYSQL_PLUGIN_DYNAMIC" MYSQL_PLUGIN_DYNAMIC ${PLUGIN_FILE_CONTENT})
|
||||
STRING (REGEX MATCH "MYSQL_PLUGIN_MANDATORY" MYSQL_PLUGIN_MANDATORY ${PLUGIN_FILE_CONTENT})
|
||||
STRING (REGEX MATCH "MYSQL_PLUGIN_STATIC" MYSQL_PLUGIN_STATIC ${PLUGIN_FILE_CONTENT})
|
||||
|
||||
IF(MYSQL_PLUGIN_MANDATORY)
|
||||
SET(WITH_${ENGINE}_STORAGE_ENGINE TRUE)
|
||||
ENDIF(MYSQL_PLUGIN_MANDATORY)
|
||||
|
||||
IF (WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
|
||||
SET(ENGINE_BUILD_TYPE "STATIC")
|
||||
ELSEIF(NOT WITHOUT_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_DYNAMIC AND NOT WITHOUT_DYNAMIC_PLUGINS)
|
||||
SET(ENGINE_BUILD_TYPE "DYNAMIC")
|
||||
ELSE(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
|
||||
SET(ENGINE_BUILD_TYPE "NONE")
|
||||
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
|
||||
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${ENGINE_LOWER}_plugin")
|
||||
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${ENGINE_LOWER})
|
||||
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE")
|
||||
SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE)
|
||||
ENDIF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
|
||||
ENDIF(EXISTS ${SUBDIR}/plug.in)
|
||||
|
||||
IF(NOT ENGINE_BUILD_TYPE STREQUAL "NONE")
|
||||
LIST(APPEND ${ENGINE_BUILD_TYPE}_ENGINE_DIRECTORIES ${SUBDIR})
|
||||
ENDIF(NOT ENGINE_BUILD_TYPE STREQUAL "NONE")
|
||||
|
||||
ENDIF(HAVE_STORAGE_ENGINE)
|
||||
ENDIF(EXISTS ${SUBDIR}/CMakeLists.txt)
|
||||
ENDFOREACH(SUBDIR ${STORAGE_SUBDIRS})
|
||||
|
||||
# Special handling for partition(not really pluggable)
|
||||
IF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
|
||||
SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_PARTITION_STORAGE_ENGINE")
|
||||
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_partition_plugin")
|
||||
ENDIF(NOT WITHOUT_PARTITION_STORAGE_ENGINE)
|
||||
|
||||
ADD_DEFINITIONS(${STORAGE_ENGINE_DEFS})
|
||||
|
||||
# Now write out our mysql_plugin_defs struct
|
||||
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc.in
|
||||
${CMAKE_SOURCE_DIR}/sql/sql_builtin.cc @ONLY)
|
||||
|
||||
# Add subdirectories for storage engines
|
||||
SET (ENGINE_BUILD_TYPE "STATIC")
|
||||
FOREACH(DIR ${STATIC_ENGINE_DIRECTORIES})
|
||||
ADD_SUBDIRECTORY(${DIR})
|
||||
ENDFOREACH(DIR ${STATIC_ENGINE_DIRECTORIES})
|
||||
|
||||
SET (ENGINE_BUILD_TYPE "DYNAMIC")
|
||||
FOREACH(DIR ${DYNAMIC_ENGINE_DIRECTORIES})
|
||||
ADD_SUBDIRECTORY(${DIR})
|
||||
ENDFOREACH(DIR ${DYNAMIC_ENGINE_DIRECTORIES})
|
||||
|
||||
|
||||
# FIXME "debug" only needed if build type is "Debug", but
|
||||
# CMAKE_BUILD_TYPE is not set during configure time.
|
||||
ADD_SUBDIRECTORY(vio)
|
||||
@@ -249,28 +288,7 @@ ADD_SUBDIRECTORY(zlib)
|
||||
ADD_SUBDIRECTORY(extra/yassl)
|
||||
ADD_SUBDIRECTORY(extra/yassl/taocrypt)
|
||||
ADD_SUBDIRECTORY(extra)
|
||||
ADD_SUBDIRECTORY(storage/heap)
|
||||
ADD_SUBDIRECTORY(storage/myisam)
|
||||
ADD_SUBDIRECTORY(storage/myisammrg)
|
||||
ADD_SUBDIRECTORY(client)
|
||||
IF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/archive)
|
||||
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
IF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/blackhole)
|
||||
ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
IF(WITH_CSV_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/csv)
|
||||
ENDIF(WITH_CSV_STORAGE_ENGINE)
|
||||
IF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/example)
|
||||
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
IF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/federated)
|
||||
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
IF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(storage/innobase)
|
||||
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
ADD_SUBDIRECTORY(sql)
|
||||
ADD_SUBDIRECTORY(server-tools/instance-manager)
|
||||
ADD_SUBDIRECTORY(libmysql)
|
||||
|
||||
@@ -285,7 +285,7 @@ typedef struct charset_info_st
|
||||
#define ILLEGAL_CHARSET_INFO_NUMBER (~0U)
|
||||
|
||||
|
||||
extern CHARSET_INFO my_charset_bin;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_bin;
|
||||
extern CHARSET_INFO my_charset_big5_chinese_ci;
|
||||
extern CHARSET_INFO my_charset_big5_bin;
|
||||
extern CHARSET_INFO my_charset_cp932_japanese_ci;
|
||||
@@ -298,7 +298,7 @@ extern CHARSET_INFO my_charset_gb2312_chinese_ci;
|
||||
extern CHARSET_INFO my_charset_gb2312_bin;
|
||||
extern CHARSET_INFO my_charset_gbk_chinese_ci;
|
||||
extern CHARSET_INFO my_charset_gbk_bin;
|
||||
extern CHARSET_INFO my_charset_latin1;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_latin1;
|
||||
extern CHARSET_INFO my_charset_latin1_german2_ci;
|
||||
extern CHARSET_INFO my_charset_latin1_bin;
|
||||
extern CHARSET_INFO my_charset_latin2_czech_ci;
|
||||
@@ -315,7 +315,7 @@ extern CHARSET_INFO my_charset_utf8_general_ci;
|
||||
extern CHARSET_INFO my_charset_utf8_unicode_ci;
|
||||
extern CHARSET_INFO my_charset_utf8_bin;
|
||||
extern CHARSET_INFO my_charset_cp1250_czech_ci;
|
||||
extern CHARSET_INFO my_charset_filename;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO my_charset_filename;
|
||||
|
||||
/* declarations for simple charsets */
|
||||
extern size_t my_strnxfrm_simple(CHARSET_INFO *, uchar *, size_t,
|
||||
|
||||
@@ -1573,4 +1573,17 @@ static inline double rint(double x)
|
||||
}
|
||||
#endif /* HAVE_RINT */
|
||||
|
||||
/*
|
||||
MYSQL_PLUGIN_IMPORT macro is used to export mysqld data
|
||||
(i.e variables) for usage in storage engine loadable plugins.
|
||||
Outside of Windows, it is dummy.
|
||||
*/
|
||||
#ifndef MYSQL_PLUGIN_IMPORT
|
||||
#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN))
|
||||
#define MYSQL_PLUGIN_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#define MYSQL_PLUGIN_IMPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* my_global_h */
|
||||
|
||||
@@ -221,8 +221,8 @@ extern uint my_large_page_size;
|
||||
#endif
|
||||
|
||||
/* charsets */
|
||||
extern CHARSET_INFO *default_charset_info;
|
||||
extern CHARSET_INFO *all_charsets[256];
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *default_charset_info;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *all_charsets[256];
|
||||
extern CHARSET_INFO compiled_charsets[];
|
||||
|
||||
/* statistics */
|
||||
@@ -237,8 +237,8 @@ extern void (*my_sigtstp_cleanup)(void),
|
||||
(*my_sigtstp_restart)(void),
|
||||
(*my_abort_hook)(int);
|
||||
/* Executed when comming from shell */
|
||||
extern int NEAR my_umask, /* Default creation mask */
|
||||
NEAR my_umask_dir,
|
||||
extern MYSQL_PLUGIN_IMPORT int NEAR my_umask; /* Default creation mask */
|
||||
extern int NEAR my_umask_dir,
|
||||
NEAR my_recived_signals, /* Signals we have got */
|
||||
NEAR my_safe_to_handle_signal, /* Set when allowed to SIGTSTP */
|
||||
NEAR my_dont_interrupt; /* call remember_intr when set */
|
||||
|
||||
@@ -16,6 +16,16 @@
|
||||
#ifndef _my_plugin_h
|
||||
#define _my_plugin_h
|
||||
|
||||
|
||||
/*
|
||||
On Windows, exports from DLL need to be declared
|
||||
*/
|
||||
#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN))
|
||||
#define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define MYSQL_PLUGIN_EXPORT
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
class THD;
|
||||
class Item;
|
||||
@@ -90,9 +100,9 @@ int PSIZE= sizeof(struct st_mysql_plugin); \
|
||||
struct st_mysql_plugin DECLS[]= {
|
||||
#else
|
||||
#define __MYSQL_DECLARE_PLUGIN(NAME, VERSION, PSIZE, DECLS) \
|
||||
int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
|
||||
int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
|
||||
struct st_mysql_plugin _mysql_plugin_declarations_[]= {
|
||||
MYSQL_PLUGIN_EXPORT int _mysql_plugin_interface_version_= MYSQL_PLUGIN_INTERFACE_VERSION; \
|
||||
MYSQL_PLUGIN_EXPORT int _mysql_sizeof_struct_st_plugin_= sizeof(struct st_mysql_plugin); \
|
||||
MYSQL_PLUGIN_EXPORT struct st_mysql_plugin _mysql_plugin_declarations_[]= {
|
||||
#endif
|
||||
|
||||
#define mysql_declare_plugin(NAME) \
|
||||
|
||||
@@ -87,63 +87,16 @@ FOREACH(rpath ${VIO_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../vio/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
|
||||
# Engines
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/heap/CMakeLists.txt)
|
||||
FOREACH(rpath ${HEAP_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/heap/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/myisam/CMakeLists.txt)
|
||||
FOREACH(rpath ${MYISAM_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/myisam/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/myisammrg/CMakeLists.txt)
|
||||
FOREACH(rpath ${MYISAMMRG_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/myisammrg/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
|
||||
IF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/archive/CMakeLists.txt)
|
||||
FOREACH(rpath ${ARCHIVE_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/archive/${rpath})
|
||||
FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS})
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/${ENGINE_LIB}/CMakeLists.txt)
|
||||
STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER)
|
||||
FOREACH(rpath ${${ENGINE_LIB_UPPER}_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ${CMAKE_SOURCE_DIR}/storage/${ENGINE_LIB}/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
ENDFOREACH(ENGINE_LIB)
|
||||
|
||||
IF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/blackhole/CMakeLists.txt)
|
||||
FOREACH(rpath ${BLACKHOLE_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/blackhole/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
|
||||
IF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/example/CMakeLists.txt)
|
||||
FOREACH(rpath ${EXAMPLE_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/example/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
|
||||
IF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/federated/CMakeLists.txt)
|
||||
FOREACH(rpath ${FEDERATED_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/federated/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
|
||||
IF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/innobase/CMakeLists.txt)
|
||||
FOREACH(rpath ${INNOBASE_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/innobase/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
|
||||
IF(WITH_CSV_STORAGE_ENGINE)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/storage/csv/CMakeLists.txt)
|
||||
FOREACH(rpath ${CSV_SOURCES})
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ../storage/csv/${rpath})
|
||||
ENDFOREACH(rpath)
|
||||
ENDIF(WITH_CSV_STORAGE_ENGINE)
|
||||
|
||||
SET(SOURCE_SUBLIBS FALSE)
|
||||
|
||||
|
||||
@@ -97,7 +97,8 @@ TEST_DIRS = t r include std_data std_data/parts collections \
|
||||
suite/stress/include suite/stress/t suite/stress/r \
|
||||
suite/ndb suite/ndb/t suite/ndb/r \
|
||||
suite/rpl_ndb suite/rpl_ndb/t suite/rpl_ndb/r \
|
||||
suite/parts suite/parts/t suite/parts/r suite/parts/inc
|
||||
suite/parts suite/parts/t suite/parts/r suite/parts/inc \
|
||||
suite/innodb suite/innodb/t suite/innodb/r suite/innodb/include
|
||||
|
||||
# Used by dist-hook and install-data-local to copy all
|
||||
# test files into either dist or install directory
|
||||
|
||||
@@ -475,6 +475,66 @@ sub collect_one_suite($)
|
||||
#print_testcases(@cases);
|
||||
}
|
||||
}
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Testing InnoDB plugin.
|
||||
# ----------------------------------------------------------------------
|
||||
my $lib_innodb_plugin=
|
||||
mtr_file_exists(::vs_config_dirs('storage/innodb_plugin', 'ha_innodb_plugin.dll'),
|
||||
"$::basedir/storage/innodb_plugin/.libs/ha_innodb_plugin.so",
|
||||
"$::basedir/lib/mysql/plugin/ha_innodb_plugin.so",
|
||||
"$::basedir/lib/mysql/plugin/ha_innodb_plugin.dll");
|
||||
if ($::mysql_version_id >= 50100 && !(IS_WINDOWS && $::opt_embedded_server) &&
|
||||
$lib_innodb_plugin)
|
||||
{
|
||||
my @new_cases;
|
||||
|
||||
foreach my $test (@cases)
|
||||
{
|
||||
next if ($test->{'skip'} || !$test->{'innodb_test'});
|
||||
# Exceptions
|
||||
next if ($test->{'name'} eq 'main.innodb'); # Failed with wrong errno (fk)
|
||||
# innodb_file_per_table is rw with innodb_plugin
|
||||
next if ($test->{'name'} eq 'sys_vars.innodb_file_per_table_basic');
|
||||
# innodb_lock_wait_timeout is rw with innodb_plugin
|
||||
next if ($test->{'name'} eq 'sys_vars.innodb_lock_wait_timeout_basic');
|
||||
# Diff around innodb_thread_concurrency variable
|
||||
next if ($test->{'name'} eq 'sys_vars.innodb_thread_concurrency_basic');
|
||||
# Copy test options
|
||||
my $new_test= My::Test->new();
|
||||
while (my ($key, $value) = each(%$test))
|
||||
{
|
||||
if (ref $value eq "ARRAY")
|
||||
{
|
||||
push(@{$new_test->{$key}}, @$value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_test->{$key}= $value;
|
||||
}
|
||||
}
|
||||
my $plugin_filename= basename($lib_innodb_plugin);
|
||||
push(@{$new_test->{master_opt}}, '--ignore-builtin-innodb');
|
||||
push(@{$new_test->{master_opt}}, '--plugin-dir=' . dirname($lib_innodb_plugin));
|
||||
push(@{$new_test->{master_opt}}, "--plugin_load=innodb=$plugin_filename;innodb_locks=$plugin_filename");
|
||||
push(@{$new_test->{slave_opt}}, '--ignore-builtin-innodb');
|
||||
push(@{$new_test->{slave_opt}}, '--plugin-dir=' . dirname($lib_innodb_plugin));
|
||||
push(@{$new_test->{slave_opt}}, "--plugin_load=innodb=$plugin_filename;innodb_locks=$plugin_filename");
|
||||
if ($new_test->{combination})
|
||||
{
|
||||
$new_test->{combination}.= ' + InnoDB plugin';
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_test->{combination}= 'InnoDB plugin';
|
||||
}
|
||||
push(@new_cases, $new_test);
|
||||
}
|
||||
push(@cases, @new_cases);
|
||||
}
|
||||
# ----------------------------------------------------------------------
|
||||
# End of testing InnoDB plugin.
|
||||
# ----------------------------------------------------------------------
|
||||
optimize_cases(\@cases);
|
||||
#print_testcases(@cases);
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ my $path_config_file; # The generated config file, var/my.cnf
|
||||
# executables will be used by the test suite.
|
||||
our $opt_vs_config = $ENV{'MTR_VS_CONFIG'};
|
||||
|
||||
my $DEFAULT_SUITES= "main,binlog,federated,rpl,rpl_ndb,ndb";
|
||||
my $DEFAULT_SUITES= "main,binlog,federated,rpl,rpl_ndb,ndb,innodb";
|
||||
my $opt_suites;
|
||||
|
||||
our $opt_verbose= 0; # Verbose output, enable with --verbose
|
||||
@@ -1760,15 +1760,26 @@ sub environment_setup {
|
||||
# --------------------------------------------------------------------------
|
||||
# Add the path where mysqld will find ha_example.so
|
||||
# --------------------------------------------------------------------------
|
||||
if ($mysql_version_id >= 50100) {
|
||||
if ($mysql_version_id >= 50100 && !(IS_WINDOWS && $opt_embedded_server)) {
|
||||
my $plugin_filename;
|
||||
if (IS_WINDOWS)
|
||||
{
|
||||
$plugin_filename = "ha_example.dll";
|
||||
}
|
||||
else
|
||||
{
|
||||
$plugin_filename = "ha_example.so";
|
||||
}
|
||||
my $lib_example_plugin=
|
||||
mtr_file_exists(vs_config_dirs('storage/example', 'ha_example.dll'),
|
||||
"$basedir/storage/example/.libs/ha_example.so",);
|
||||
mtr_file_exists(vs_config_dirs('storage/example',$plugin_filename),
|
||||
"$basedir/storage/example/.libs/".$plugin_filename);
|
||||
$ENV{'EXAMPLE_PLUGIN'}=
|
||||
($lib_example_plugin ? basename($lib_example_plugin) : "");
|
||||
$ENV{'EXAMPLE_PLUGIN_OPT'}= "--plugin-dir=".
|
||||
($lib_example_plugin ? dirname($lib_example_plugin) : "");
|
||||
|
||||
$ENV{'HA_EXAMPLE_SO'}="'".$plugin_filename."'";
|
||||
$ENV{'EXAMPLE_PLUGIN_LOAD'}="--plugin_load=;EXAMPLE=".$plugin_filename.";";
|
||||
}
|
||||
|
||||
# ----------------------------------------------------
|
||||
|
||||
4
mysql-test/suite/innodb/include/have_innodb_plugin.inc
Normal file
4
mysql-test/suite/innodb/include/have_innodb_plugin.inc
Normal file
@@ -0,0 +1,4 @@
|
||||
disable_query_log;
|
||||
--require r/true.require
|
||||
select (PLUGIN_LIBRARY LIKE 'ha_innodb_plugin%') as `TRUE` from information_schema.plugins where PLUGIN_NAME='InnoDB';
|
||||
enable_query_log;
|
||||
26
mysql-test/suite/innodb/include/innodb-index.inc
Normal file
26
mysql-test/suite/innodb/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;
|
||||
2
mysql-test/suite/innodb/r/innodb-analyze.result
Normal file
2
mysql-test/suite/innodb/r/innodb-analyze.result
Normal file
@@ -0,0 +1,2 @@
|
||||
Variable_name Value
|
||||
innodb_stats_sample_pages 1
|
||||
1170
mysql-test/suite/innodb/r/innodb-index.result
Normal file
1170
mysql-test/suite/innodb/r/innodb-index.result
Normal file
File diff suppressed because it is too large
Load Diff
116
mysql-test/suite/innodb/r/innodb-index_ucs2.result
Normal file
116
mysql-test/suite/innodb/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/suite/innodb/r/innodb-timeout.result
Normal file
38
mysql-test/suite/innodb/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/suite/innodb/r/innodb-use-sys-malloc.result
Normal file
48
mysql-test/suite/innodb/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/suite/innodb/r/innodb-zip.result
Normal file
421
mysql-test/suite/innodb/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(439)))
|
||||
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;
|
||||
2
mysql-test/suite/innodb/r/innodb_bug36169.result
Normal file
2
mysql-test/suite/innodb/r/innodb_bug36169.result
Normal file
@@ -0,0 +1,2 @@
|
||||
SET GLOBAL innodb_file_format='Barracuda';
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
||||
1
mysql-test/suite/innodb/r/innodb_bug36172.result
Normal file
1
mysql-test/suite/innodb/r/innodb_bug36172.result
Normal file
@@ -0,0 +1 @@
|
||||
SET storage_engine=InnoDB;
|
||||
4
mysql-test/suite/innodb/r/innodb_bug40360.result
Normal file
4
mysql-test/suite/innodb/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/suite/innodb/r/innodb_bug41904.result
Normal file
4
mysql-test/suite/innodb/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;
|
||||
7
mysql-test/suite/innodb/r/innodb_bug44032.result
Normal file
7
mysql-test/suite/innodb/r/innodb_bug44032.result
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE bug44032(c CHAR(3) CHARACTER SET UTF8) ROW_FORMAT=REDUNDANT
|
||||
ENGINE=InnoDB;
|
||||
INSERT INTO bug44032 VALUES('abc'),(0xEFBCA4EFBCA4EFBCA4);
|
||||
UPDATE bug44032 SET c='DDD' WHERE c=0xEFBCA4EFBCA4EFBCA4;
|
||||
UPDATE bug44032 SET c=NULL WHERE c='DDD';
|
||||
UPDATE bug44032 SET c='DDD' WHERE c IS NULL;
|
||||
DROP TABLE bug44032;
|
||||
44
mysql-test/suite/innodb/r/innodb_file_format.result
Normal file
44
mysql-test/suite/innodb/r/innodb_file_format.result
Normal file
@@ -0,0 +1,44 @@
|
||||
select @@innodb_file_format;
|
||||
@@innodb_file_format
|
||||
Antelope
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Antelope
|
||||
set global innodb_file_format=antelope;
|
||||
set global innodb_file_format=barracuda;
|
||||
set global innodb_file_format=cheetah;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
select @@innodb_file_format;
|
||||
@@innodb_file_format
|
||||
Barracuda
|
||||
set global innodb_file_format=default;
|
||||
select @@innodb_file_format;
|
||||
@@innodb_file_format
|
||||
Antelope
|
||||
set global innodb_file_format=on;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=off;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
select @@innodb_file_format;
|
||||
@@innodb_file_format
|
||||
Antelope
|
||||
set global innodb_file_format_check=antelope;
|
||||
set global innodb_file_format_check=barracuda;
|
||||
set global innodb_file_format_check=cheetah;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
set global innodb_file_format_check=default;
|
||||
Warnings:
|
||||
Warning 1210 Ignoring SET innodb_file_format=on
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
set global innodb_file_format=on;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
set global innodb_file_format=off;
|
||||
ERROR HY000: Incorrect arguments to SET
|
||||
select @@innodb_file_format_check;
|
||||
@@innodb_file_format_check
|
||||
Barracuda
|
||||
23
mysql-test/suite/innodb/r/innodb_information_schema.result
Normal file
23
mysql-test/suite/innodb/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
|
||||
1
mysql-test/suite/innodb/t/disabled.def
Normal file
1
mysql-test/suite/innodb/t/disabled.def
Normal file
@@ -0,0 +1 @@
|
||||
innodb-index: InnoDB: Error: table `test`.`t1#1` already exists in InnoDB internal
|
||||
66
mysql-test/suite/innodb/t/innodb-analyze.test
Normal file
66
mysql-test/suite/innodb/t/innodb-analyze.test
Normal file
@@ -0,0 +1,66 @@
|
||||
#
|
||||
# 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
|
||||
-- source suite/innodb/include/have_innodb_plugin.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 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;
|
||||
|
||||
DROP TABLE innodb_analyze;
|
||||
|
||||
SET GLOBAL innodb_stats_sample_pages=DEFAULT;
|
||||
534
mysql-test/suite/innodb/t/innodb-index.test
Normal file
534
mysql-test/suite/innodb/t/innodb-index.test
Normal file
@@ -0,0 +1,534 @@
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
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;
|
||||
|
||||
--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 suite/innodb/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;
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
connection a;
|
||||
CREATE TABLE t1 (a INT, b CHAR(1)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (3,'a'),(3,'b'),(1,'c'),(0,'d'),(1,'e');
|
||||
connection b;
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
connection a;
|
||||
CREATE INDEX t1a ON t1(a);
|
||||
connection b;
|
||||
SELECT * FROM t1;
|
||||
--error ER_TABLE_DEF_CHANGED
|
||||
SELECT * FROM t1 FORCE INDEX(t1a) ORDER BY a;
|
||||
SELECT * FROM t1;
|
||||
COMMIT;
|
||||
SELECT * FROM t1 FORCE INDEX(t1a) ORDER BY a;
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
DROP TABLE t1;
|
||||
5
mysql-test/suite/innodb/t/innodb-index_ucs2.test
Normal file
5
mysql-test/suite/innodb/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 suite/innodb/include/innodb-index.inc
|
||||
65
mysql-test/suite/innodb/t/innodb-timeout.test
Normal file
65
mysql-test/suite/innodb/t/innodb-timeout.test
Normal file
@@ -0,0 +1,65 @@
|
||||
-- source include/have_innodb.inc
|
||||
-- source suite/innodb/include/have_innodb_plugin.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;
|
||||
@@ -0,0 +1,2 @@
|
||||
--loose-innodb-use-sys-malloc=true
|
||||
--loose-innodb-use-sys-malloc=true
|
||||
49
mysql-test/suite/innodb/t/innodb-use-sys-malloc.test
Normal file
49
mysql-test/suite/innodb/t/innodb-use-sys-malloc.test
Normal file
@@ -0,0 +1,49 @@
|
||||
--source include/have_innodb.inc
|
||||
-- source suite/innodb/include/have_innodb_plugin.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;
|
||||
344
mysql-test/suite/innodb/t/innodb-zip.test
Normal file
344
mysql-test/suite/innodb/t/innodb-zip.test
Normal file
@@ -0,0 +1,344 @@
|
||||
-- source include/have_innodb.inc
|
||||
-- source suite/innodb/include/have_innodb_plugin.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;
|
||||
CREATE TABLE t1(c TEXT, PRIMARY KEY (c(439)))
|
||||
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;
|
||||
1159
mysql-test/suite/innodb/t/innodb_bug36169.test
Normal file
1159
mysql-test/suite/innodb/t/innodb_bug36169.test
Normal file
File diff suppressed because it is too large
Load Diff
31
mysql-test/suite/innodb/t/innodb_bug36172.test
Normal file
31
mysql-test/suite/innodb/t/innodb_bug36172.test
Normal file
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Test case for bug 36172
|
||||
#
|
||||
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
-- source suite/innodb/include/have_innodb_plugin.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 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;
|
||||
DROP TABLE table0;
|
||||
|
||||
SET GLOBAL innodb_file_per_table=DEFAULT;
|
||||
SET GLOBAL innodb_file_format='Antelope';
|
||||
SET GLOBAL innodb_file_format_check='Antelope';
|
||||
16
mysql-test/suite/innodb/t/innodb_bug40360.test
Normal file
16
mysql-test/suite/innodb/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/suite/innodb/t/innodb_bug41904.test
Normal file
14
mysql-test/suite/innodb/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;
|
||||
13
mysql-test/suite/innodb/t/innodb_bug44032.test
Normal file
13
mysql-test/suite/innodb/t/innodb_bug44032.test
Normal file
@@ -0,0 +1,13 @@
|
||||
# Bug44032 no update-in-place of UTF-8 columns in ROW_FORMAT=REDUNDANT
|
||||
# (btr_cur_update_in_place not invoked when updating from/to NULL;
|
||||
# the update is performed by delete and insert instead)
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
CREATE TABLE bug44032(c CHAR(3) CHARACTER SET UTF8) ROW_FORMAT=REDUNDANT
|
||||
ENGINE=InnoDB;
|
||||
INSERT INTO bug44032 VALUES('abc'),(0xEFBCA4EFBCA4EFBCA4);
|
||||
UPDATE bug44032 SET c='DDD' WHERE c=0xEFBCA4EFBCA4EFBCA4;
|
||||
UPDATE bug44032 SET c=NULL WHERE c='DDD';
|
||||
UPDATE bug44032 SET c='DDD' WHERE c IS NULL;
|
||||
DROP TABLE bug44032;
|
||||
41
mysql-test/suite/innodb/t/innodb_file_format.test
Normal file
41
mysql-test/suite/innodb/t/innodb_file_format.test
Normal file
@@ -0,0 +1,41 @@
|
||||
-- source include/have_innodb.inc
|
||||
-- source suite/innodb/include/have_innodb_plugin.inc
|
||||
|
||||
let $format=`select @@innodb_file_format`;
|
||||
let $innodb_file_format_check_orig=`select @@innodb_file_format_check`;
|
||||
|
||||
select @@innodb_file_format;
|
||||
select @@innodb_file_format_check;
|
||||
set global innodb_file_format=antelope;
|
||||
set global innodb_file_format=barracuda;
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=cheetah;
|
||||
select @@innodb_file_format;
|
||||
set global innodb_file_format=default;
|
||||
select @@innodb_file_format;
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=on;
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=off;
|
||||
select @@innodb_file_format;
|
||||
set global innodb_file_format_check=antelope;
|
||||
set global innodb_file_format_check=barracuda;
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format_check=cheetah;
|
||||
select @@innodb_file_format_check;
|
||||
set global innodb_file_format_check=default;
|
||||
select @@innodb_file_format_check;
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=on;
|
||||
--error ER_WRONG_ARGUMENTS
|
||||
set global innodb_file_format=off;
|
||||
select @@innodb_file_format_check;
|
||||
|
||||
#
|
||||
# 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_format_check=$innodb_file_format_check_orig;
|
||||
-- enable_query_log
|
||||
146
mysql-test/suite/innodb/t/innodb_information_schema.test
Normal file
146
mysql-test/suite/innodb/t/innodb_information_schema.test
Normal file
@@ -0,0 +1,146 @@
|
||||
#
|
||||
# Test that user data is correctly "visualized" in
|
||||
# INFORMATION_SCHEMA.innodb_locks.lock_data
|
||||
#
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
-- source suite/innodb/include/have_innodb_plugin.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`;
|
||||
@@ -3,13 +3,16 @@
|
||||
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
|
||||
DROP TABLE t1;
|
||||
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
--replace_regex /\.dll/.so/
|
||||
eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO;
|
||||
--replace_regex /\.dll/.so/
|
||||
--error 1125
|
||||
INSTALL PLUGIN EXAMPLE SONAME 'ha_example.so';
|
||||
eval INSTALL PLUGIN EXAMPLE SONAME $HA_EXAMPLE_SO;
|
||||
|
||||
UNINSTALL PLUGIN example;
|
||||
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
--replace_regex /\.dll/.so/
|
||||
eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO;
|
||||
|
||||
CREATE TABLE t1(a int) ENGINE=EXAMPLE;
|
||||
|
||||
@@ -30,8 +33,8 @@ UNINSTALL PLUGIN non_exist;
|
||||
--echo # Bug#32034: check_func_enum() does not check correct values but set it
|
||||
--echo # to impossible int val
|
||||
--echo #
|
||||
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
--replace_regex /\.dll/.so/
|
||||
eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO;
|
||||
|
||||
SET GLOBAL example_enum_var= e1;
|
||||
SET GLOBAL example_enum_var= e2;
|
||||
@@ -45,7 +48,8 @@ UNINSTALL PLUGIN example;
|
||||
#
|
||||
# Bug #32757 hang with sql_mode set when setting some global variables
|
||||
#
|
||||
INSTALL PLUGIN example SONAME 'ha_example.so';
|
||||
--replace_regex /\.dll/.so/
|
||||
eval INSTALL PLUGIN example SONAME $HA_EXAMPLE_SO;
|
||||
|
||||
select @@session.sql_mode into @old_sql_mode;
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
$EXAMPLE_PLUGIN_OPT
|
||||
"--plugin-load=;EXAMPLE=ha_example.so;"
|
||||
$EXAMPLE_PLUGIN_LOAD
|
||||
--loose-plugin-example-enum-var=e2
|
||||
|
||||
@@ -384,7 +384,7 @@ char *get_charsets_dir(char *buf)
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
CHARSET_INFO *all_charsets[256];
|
||||
CHARSET_INFO *all_charsets[256]={NULL};
|
||||
CHARSET_INFO *default_charset_info = &my_charset_latin1;
|
||||
|
||||
void add_compiled_collation(CHARSET_INFO *cs)
|
||||
|
||||
@@ -39,7 +39,8 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/sql/sql_yacc.h
|
||||
|
||||
ADD_DEFINITIONS(-DMYSQL_SERVER -D_CONSOLE -DHAVE_DLOPEN -DHAVE_EVENT_SCHEDULER)
|
||||
|
||||
ADD_EXECUTABLE(mysqld
|
||||
|
||||
SET (SQL_SOURCE
|
||||
../sql-common/client.c derror.cc des_key_file.cc
|
||||
discover.cc ../libmysql/errmsg.c field.cc field_conv.cc
|
||||
filesort.cc gstream.cc
|
||||
@@ -82,54 +83,45 @@ ADD_EXECUTABLE(mysqld
|
||||
${PROJECT_SOURCE_DIR}/include/mysql_version.h
|
||||
${PROJECT_SOURCE_DIR}/sql/sql_builtin.cc
|
||||
${PROJECT_SOURCE_DIR}/sql/lex_hash.h)
|
||||
ADD_LIBRARY(sql ${SQL_SOURCE})
|
||||
|
||||
TARGET_LINK_LIBRARIES(mysqld
|
||||
heap myisam myisammrg mysys yassl zlib debug dbug yassl
|
||||
taocrypt strings vio regex wsock32 ws2_32)
|
||||
IF (NOT EXISTS cmake_dummy.cc)
|
||||
FILE (WRITE cmake_dummy.cc "")
|
||||
ENDIF (NOT EXISTS cmake_dummy.cc)
|
||||
ADD_EXECUTABLE(mysqld cmake_dummy.cc)
|
||||
|
||||
SET_TARGET_PROPERTIES(mysqld PROPERTIES OUTPUT_NAME mysqld${MYSQLD_EXE_SUFFIX})
|
||||
SET_TARGET_PROPERTIES(mysqld PROPERTIES ENABLE_EXPORTS TRUE)
|
||||
|
||||
IF(cmake_version EQUAL 20406)
|
||||
# Work around for 2.4.6 bug, OUTPUT_NAME will not set the right .PDB
|
||||
# file name. Note that COMPILE_FLAGS set some temporary pdb during build,
|
||||
# LINK_FLAGS sets the real one.
|
||||
SET_TARGET_PROPERTIES(mysqld PROPERTIES
|
||||
COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb"
|
||||
LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb")
|
||||
ENDIF(cmake_version EQUAL 20406)
|
||||
SET (MYSQLD_CORE_LIBS mysys zlib dbug strings yassl taocrypt vio regex sql)
|
||||
TARGET_LINK_LIBRARIES(mysqld ${MYSQLD_CORE_LIBS} ${MYSQLD_STATIC_ENGINE_LIBS})
|
||||
TARGET_LINK_LIBRARIES(mysqld ws2_32.lib)
|
||||
|
||||
IF(EMBED_MANIFESTS)
|
||||
MYSQL_EMBED_MANIFEST("mysqld" "asInvoker")
|
||||
ENDIF(EMBED_MANIFESTS)
|
||||
IF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld archive)
|
||||
ENDIF(WITH_ARCHIVE_STORAGE_ENGINE)
|
||||
IF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld blackhole)
|
||||
ENDIF(WITH_BLACKHOLE_STORAGE_ENGINE)
|
||||
IF(WITH_CSV_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld csv)
|
||||
ENDIF(WITH_CSV_STORAGE_ENGINE)
|
||||
IF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld example)
|
||||
ENDIF(WITH_EXAMPLE_STORAGE_ENGINE)
|
||||
IF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld federated)
|
||||
ENDIF(WITH_FEDERATED_STORAGE_ENGINE)
|
||||
IF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
TARGET_LINK_LIBRARIES(mysqld innobase)
|
||||
ENDIF(WITH_INNOBASE_STORAGE_ENGINE)
|
||||
|
||||
ADD_DEPENDENCIES(mysqld GenError)
|
||||
IF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
|
||||
# Set module definition file. Also use non-incremental linker,
|
||||
# incremental appears to crash from time to time,if used with /DEF option
|
||||
SET_TARGET_PROPERTIES(mysqld PROPERTIES LINK_FLAGS "/DEF:mysqld.def /INCREMENTAL:NO")
|
||||
|
||||
# NOTE CMake 2.4.6 creates strange dependencies between files in OUTPUT,
|
||||
# so for now we only list one if more than one
|
||||
FOREACH (CORELIB ${MYSQLD_CORE_LIBS})
|
||||
GET_TARGET_PROPERTY(LOC ${CORELIB} LOCATION)
|
||||
FILE(TO_NATIVE_PATH ${LOC} LOC)
|
||||
SET (LIB_LOCATIONS ${LIB_LOCATIONS} ${LOC})
|
||||
ENDFOREACH (CORELIB ${MYSQLD_CORE_LIBS})
|
||||
|
||||
ADD_CUSTOM_COMMAND(TARGET mysqld PRE_LINK
|
||||
COMMAND cscript ARGS //nologo ${PROJECT_SOURCE_DIR}/win/create_def_file.js
|
||||
${PLATFORM} ${LIB_LOCATIONS} > mysqld.def
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/sql)
|
||||
ENDIF(MSVC AND NOT WITHOUT_DYNAMIC_PLUGINS)
|
||||
|
||||
ADD_DEPENDENCIES(sql GenError)
|
||||
|
||||
# Sql Parser custom command
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
|
||||
# ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
|
||||
COMMAND bison.exe ARGS -y -p MYSQL --defines=sql_yacc.h
|
||||
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
|
||||
COMMAND bison ARGS -y -p MYSQL --defines=sql_yacc.h
|
||||
--output=sql_yacc.cc sql_yacc.yy
|
||||
DEPENDS ${PROJECT_SOURCE_DIR}/sql/sql_yacc.yy)
|
||||
|
||||
@@ -146,16 +138,16 @@ ADD_CUSTOM_COMMAND(
|
||||
ADD_CUSTOM_TARGET(
|
||||
GenServerSource ALL
|
||||
DEPENDS ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
|
||||
# ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
|
||||
${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
|
||||
${PROJECT_SOURCE_DIR}/sql/message.h
|
||||
# ${PROJECT_SOURCE_DIR}/sql/message.rc
|
||||
${PROJECT_SOURCE_DIR}/sql/message.rc
|
||||
${PROJECT_SOURCE_DIR}/sql/lex_hash.h)
|
||||
|
||||
ADD_DEPENDENCIES(mysqld GenServerSource)
|
||||
|
||||
# Remove the auto-generated files as part of 'Clean Solution'
|
||||
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES
|
||||
"lex_hash.h;sql_yacc.h;sql_yacc.cc")
|
||||
"lex_hash.h;sql_yacc.h;sql_yacc.cc;mysqld.def")
|
||||
|
||||
ADD_LIBRARY(udf_example MODULE udf_example.c udf_example.def)
|
||||
ADD_DEPENDENCIES(udf_example strings GenError)
|
||||
|
||||
@@ -1937,8 +1937,8 @@ private:
|
||||
/* Some extern variables used with handlers */
|
||||
|
||||
extern const char *ha_row_type[];
|
||||
extern const char *tx_isolation_names[];
|
||||
extern const char *binlog_format_names[];
|
||||
extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[];
|
||||
extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[];
|
||||
extern TYPELIB tx_isolation_typelib;
|
||||
extern TYPELIB myisam_stats_method_typelib;
|
||||
extern ulong total_ha, total_ha_2pc;
|
||||
|
||||
@@ -82,9 +82,9 @@ extern query_id_t global_query_id;
|
||||
inline query_id_t next_query_id() { return global_query_id++; }
|
||||
|
||||
/* useful constants */
|
||||
extern const key_map key_map_empty;
|
||||
extern key_map key_map_full; /* Should be threaded as const */
|
||||
extern const char *primary_key_name;
|
||||
extern MYSQL_PLUGIN_IMPORT const key_map key_map_empty;
|
||||
extern MYSQL_PLUGIN_IMPORT key_map key_map_full; /* Should be threaded as const */
|
||||
extern MYSQL_PLUGIN_IMPORT const char *primary_key_name;
|
||||
|
||||
#include "mysql_com.h"
|
||||
#include <violite.h>
|
||||
@@ -123,8 +123,10 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
|
||||
"in MySQL %s. Please use %s instead.", (Old), (Ver), (New)); \
|
||||
} while(0)
|
||||
|
||||
extern CHARSET_INFO *system_charset_info, *files_charset_info ;
|
||||
extern CHARSET_INFO *national_charset_info, *table_alias_charset;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *system_charset_info;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *files_charset_info ;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *national_charset_info;
|
||||
extern MYSQL_PLUGIN_IMPORT CHARSET_INFO *table_alias_charset;
|
||||
|
||||
|
||||
enum Derivation
|
||||
@@ -690,14 +692,19 @@ typedef struct st_sql_list {
|
||||
}
|
||||
} SQL_LIST;
|
||||
|
||||
|
||||
#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32)
|
||||
extern "C" THD *_current_thd_noinline();
|
||||
#define _current_thd() _current_thd_noinline()
|
||||
#else
|
||||
extern pthread_key(THD*, THR_THD);
|
||||
inline THD *_current_thd(void)
|
||||
{
|
||||
return my_pthread_getspecific_ptr(THD*,THR_THD);
|
||||
}
|
||||
#endif
|
||||
#define current_thd _current_thd()
|
||||
|
||||
|
||||
/**
|
||||
The meat of thd_proc_info(THD*, char*), a macro that packs the last
|
||||
three calling-info parameters.
|
||||
@@ -1882,8 +1889,12 @@ extern time_t server_start_time, flush_status_time;
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern uint mysql_data_home_len;
|
||||
extern char *mysql_data_home,server_version[SERVER_VERSION_LENGTH],
|
||||
mysql_real_data_home[], mysql_unpacked_real_data_home[];
|
||||
|
||||
extern MYSQL_PLUGIN_IMPORT char *mysql_data_home;
|
||||
extern char server_version[SERVER_VERSION_LENGTH];
|
||||
extern MYSQL_PLUGIN_IMPORT char mysql_real_data_home[];
|
||||
extern char mysql_unpacked_real_data_home[];
|
||||
|
||||
extern CHARSET_INFO *character_set_filesystem;
|
||||
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
|
||||
#ifdef MYSQL_SERVER
|
||||
@@ -1891,10 +1902,13 @@ extern char *opt_mysql_tmpdir, mysql_charsets_dir[],
|
||||
def_ft_boolean_syntax[sizeof(ft_boolean_syntax)];
|
||||
extern int mysql_unpacked_real_data_home_len;
|
||||
#define mysql_tmpdir (my_tmpdir(&mysql_tmpdir_list))
|
||||
extern MY_TMPDIR mysql_tmpdir_list;
|
||||
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
|
||||
extern const LEX_STRING command_name[];
|
||||
extern const char *first_keyword, *my_localhost, *delayed_user, *binary_keyword;
|
||||
extern const char **errmesg; /* Error messages */
|
||||
|
||||
extern const char *first_keyword, *delayed_user, *binary_keyword;
|
||||
extern MYSQL_PLUGIN_IMPORT const char *my_localhost;
|
||||
extern MYSQL_PLUGIN_IMPORT const char **errmesg; /* Error messages */
|
||||
|
||||
extern const char *myisam_recover_options_str;
|
||||
extern const char *in_left_expr_name, *in_additional_cond, *in_having_cond;
|
||||
extern const char * const TRG_EXT;
|
||||
@@ -1908,8 +1922,8 @@ extern Le_creator le_creator;
|
||||
extern char language[FN_REFLEN];
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern char reg_ext[FN_EXTLEN];
|
||||
extern uint reg_ext_length;
|
||||
extern MYSQL_PLUGIN_IMPORT char reg_ext[FN_EXTLEN];
|
||||
extern MYSQL_PLUGIN_IMPORT uint reg_ext_length;
|
||||
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
|
||||
#ifdef MYSQL_SERVER
|
||||
extern char glob_hostname[FN_REFLEN], mysql_home[FN_REFLEN];
|
||||
@@ -1929,7 +1943,8 @@ extern ulong slave_open_temp_tables;
|
||||
extern ulong query_cache_size, query_cache_min_res_unit;
|
||||
extern ulong slow_launch_threads, slow_launch_time;
|
||||
extern ulong table_cache_size, table_def_size;
|
||||
extern ulong max_connections,max_connect_errors, connect_timeout;
|
||||
extern MYSQL_PLUGIN_IMPORT ulong max_connections;
|
||||
extern ulong max_connect_errors, connect_timeout;
|
||||
extern ulong slave_net_timeout, slave_trans_retries;
|
||||
extern uint max_user_connections;
|
||||
extern ulong what_to_log,flush_time;
|
||||
@@ -1943,7 +1958,7 @@ extern ulong rpl_recovery_rank, thread_cache_size, thread_pool_size;
|
||||
extern ulong back_log;
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern ulong specialflag;
|
||||
extern ulong MYSQL_PLUGIN_IMPORT specialflag;
|
||||
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
|
||||
#ifdef MYSQL_SERVER
|
||||
extern ulong current_pid;
|
||||
@@ -1956,7 +1971,7 @@ extern uint protocol_version, mysqld_port, dropping_tables;
|
||||
extern uint delay_key_write_options;
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern uint lower_case_table_names;
|
||||
extern MYSQL_PLUGIN_IMPORT uint lower_case_table_names;
|
||||
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
|
||||
#ifdef MYSQL_SERVER
|
||||
extern bool opt_endinfo, using_udf_functions;
|
||||
@@ -1964,7 +1979,7 @@ extern my_bool locked_in_memory;
|
||||
extern bool opt_using_transactions;
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern bool mysqld_embedded;
|
||||
extern MYSQL_PLUGIN_IMPORT bool mysqld_embedded;
|
||||
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
|
||||
#ifdef MYSQL_SERVER
|
||||
extern bool opt_large_files, server_id_supplied;
|
||||
@@ -2003,7 +2018,7 @@ extern uint opt_large_page_size;
|
||||
extern char *opt_logname, *opt_slow_logname;
|
||||
extern const char *log_output_str;
|
||||
|
||||
extern MYSQL_BIN_LOG mysql_bin_log;
|
||||
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
|
||||
extern LOGGER logger;
|
||||
extern TABLE_LIST general_log, slow_log;
|
||||
extern FILE *bootstrap_file;
|
||||
@@ -2011,13 +2026,14 @@ extern int bootstrap_error;
|
||||
extern FILE *stderror_file;
|
||||
extern pthread_key(MEM_ROOT**,THR_MALLOC);
|
||||
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open, LOCK_lock_db,
|
||||
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
|
||||
LOCK_mapped_file,LOCK_user_locks, LOCK_status,
|
||||
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
|
||||
LOCK_delayed_status, LOCK_delayed_create, LOCK_crypt, LOCK_timezone,
|
||||
LOCK_slave_list, LOCK_active_mi, LOCK_manager, LOCK_global_read_lock,
|
||||
LOCK_global_system_variables, LOCK_user_conn,
|
||||
LOCK_prepared_stmt_count,
|
||||
LOCK_bytes_sent, LOCK_bytes_received, LOCK_connection_count;
|
||||
extern MYSQL_PLUGIN_IMPORT pthread_mutex_t LOCK_thread_count;
|
||||
#ifdef HAVE_OPENSSL
|
||||
extern pthread_mutex_t LOCK_des_key_file;
|
||||
#endif
|
||||
@@ -2037,7 +2053,7 @@ extern const String my_null_string;
|
||||
extern SHOW_VAR status_vars[];
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern struct system_variables global_system_variables;
|
||||
extern MYSQL_PLUGIN_IMPORT struct system_variables global_system_variables;
|
||||
#endif /* MYSQL_SERVER || INNODB_COMPATIBILITY_HOOKS */
|
||||
#ifdef MYSQL_SERVER
|
||||
extern struct system_variables max_system_variables;
|
||||
|
||||
@@ -6787,7 +6787,7 @@ The minimum value for this variable is 4096.",
|
||||
(uchar**) &opt_plugin_dir_ptr, (uchar**) &opt_plugin_dir_ptr, 0,
|
||||
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"plugin-load", OPT_PLUGIN_LOAD,
|
||||
"Optional colon-separated list of plugins to load, where each plugin is "
|
||||
"Optional semicolon-separated list of plugins to load, where each plugin is "
|
||||
"identified as name=library, where name is the plugin name and library "
|
||||
"is the plugin library in plugin_dir.",
|
||||
(uchar**) &opt_plugin_load, (uchar**) &opt_plugin_load, 0,
|
||||
|
||||
@@ -757,6 +757,12 @@ void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
|
||||
*xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
extern "C" THD *_current_thd_noinline(void)
|
||||
{
|
||||
return my_pthread_getspecific_ptr(THD*,THR_THD);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
Init common variables that has to be reset on start and on change_user
|
||||
*/
|
||||
|
||||
@@ -91,7 +91,7 @@ enum enum_mark_columns
|
||||
|
||||
extern char internal_table_name[2];
|
||||
extern char empty_c_string[1];
|
||||
extern const char **errmesg;
|
||||
extern MYSQL_PLUGIN_IMPORT const char **errmesg;
|
||||
|
||||
#define TC_LOG_PAGE_SIZE 8192
|
||||
#define TC_LOG_MIN_SIZE (3*TC_LOG_PAGE_SIZE)
|
||||
|
||||
@@ -86,7 +86,7 @@ struct list_node :public Sql_alloc
|
||||
};
|
||||
|
||||
|
||||
extern list_node end_of_list;
|
||||
extern MYSQL_PLUGIN_IMPORT list_node end_of_list;
|
||||
|
||||
class base_list :public Sql_alloc
|
||||
{
|
||||
|
||||
@@ -16,25 +16,12 @@
|
||||
#ifndef _SQL_PROFILE_H
|
||||
#define _SQL_PROFILE_H
|
||||
|
||||
#if __STDC_VERSION__ < 199901L
|
||||
# if __GNUC__ >= 2
|
||||
# define __func__ __FUNCTION__
|
||||
# else
|
||||
# define __func__ _unknown_func_
|
||||
extern const char * const _unknown_func_;
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER < 1300
|
||||
# define __func__ _unknown_func_
|
||||
extern const char * const _unknown_func_;
|
||||
# else
|
||||
# define __func__ __FUNCTION__
|
||||
# endif
|
||||
#elif defined(__BORLANDC__)
|
||||
# define __func__ __FUNC__
|
||||
#ifndef __func__
|
||||
#ifdef __FUNCTION__
|
||||
#define __func__ __FUNCTION__
|
||||
#else
|
||||
# define __func__ _unknown_func_
|
||||
extern const char * const _unknown_func_;
|
||||
#define __func__ "unknown function"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern ST_FIELD_INFO query_profile_statistics_info[];
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
# These are built from source in the Docs directory
|
||||
EXTRA_DIST =
|
||||
EXTRA_DIST = mysql_storage_engine.cmake
|
||||
SUBDIRS = @mysql_se_dirs@
|
||||
DIST_SUBDIRS = @mysql_se_distdirs@
|
||||
|
||||
|
||||
@@ -13,17 +13,6 @@
|
||||
# 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")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(ARCHIVE_SOURCES azio.c ha_archive.cc ha_archive.h)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(archive ${ARCHIVE_SOURCES})
|
||||
ADD_DEPENDENCIES(archive GenError)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(ARCHIVE)
|
||||
|
||||
@@ -16,13 +16,7 @@
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(BLACKHOLE_SOURCES ha_blackhole.cc ha_blackhole.h)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(blackhole ${BLACKHOLE_SOURCES})
|
||||
ADD_DEPENDENCIES(blackhole GenError)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(BLACKHOLE)
|
||||
|
||||
@@ -16,13 +16,6 @@
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(CSV_SOURCES ha_tina.cc ha_tina.h transparent_file.cc transparent_file.h)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(csv ${CSV_SOURCES})
|
||||
ADD_DEPENDENCIES(csv GenError)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(CSV)
|
||||
@@ -15,14 +15,6 @@
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(EXAMPLE_SOURCES ha_example.cc)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(example ${EXAMPLE_SOURCES})
|
||||
ADD_DEPENDENCIES(example GenError)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(EXAMPLE)
|
||||
|
||||
@@ -13,16 +13,6 @@
|
||||
# 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")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(FEDERATED_SOURCES ha_federated.cc)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(federated ${FEDERATED_SOURCES})
|
||||
ADD_DEPENDENCIES(federated GenError)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(FEDERATED)
|
||||
|
||||
@@ -16,18 +16,10 @@
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(HEAP_SOURCES _check.c _rectest.c hp_block.c hp_clear.c hp_close.c hp_create.c
|
||||
ha_heap.cc
|
||||
hp_delete.c hp_extra.c hp_hash.c hp_info.c hp_open.c hp_panic.c
|
||||
hp_rename.c hp_rfirst.c hp_rkey.c hp_rlast.c hp_rnext.c hp_rprev.c
|
||||
hp_rrnd.c hp_rsame.c hp_scan.c hp_static.c hp_update.c hp_write.c)
|
||||
|
||||
IF(NOT SOURCE_SUBLIBS)
|
||||
ADD_LIBRARY(heap ${HEAP_SOURCES})
|
||||
ADD_DEPENDENCIES(heap GenError)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(HEAP)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -D_LIB)
|
||||
|
||||
# Bug 19424 - InnoDB: Possibly a memory overrun of the buffer being freed (64-bit Visual C)
|
||||
@@ -25,12 +26,10 @@ IF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
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/innobase/include
|
||||
${CMAKE_SOURCE_DIR}/storage/innobase/handler
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
INCLUDE_DIRECTORIES(
|
||||
${CMAKE_SOURCE_DIR}/storage/innobase/include
|
||||
${CMAKE_SOURCE_DIR}/storage/innobase/handler
|
||||
)
|
||||
|
||||
SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
|
||||
buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
|
||||
@@ -64,7 +63,5 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.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)
|
||||
ENDIF(NOT SOURCE_SUBLIBS)
|
||||
MYSQL_STORAGE_ENGINE(INNOBASE)
|
||||
|
||||
|
||||
@@ -906,6 +906,100 @@ innobase_get_charset(
|
||||
return(thd_charset((THD*) mysql_thd));
|
||||
}
|
||||
|
||||
#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN)
|
||||
extern MYSQL_PLUGIN_IMPORT MY_TMPDIR mysql_tmpdir_list;
|
||||
/*******************************************************************//**
|
||||
Map an OS error to an errno value. The OS error number is stored in
|
||||
_doserrno and the mapped value is stored in errno) */
|
||||
extern "C"
|
||||
void __cdecl
|
||||
_dosmaperr(
|
||||
unsigned long); /*!< in: OS error value */
|
||||
|
||||
/*********************************************************************//**
|
||||
Creates a temporary file.
|
||||
@return temporary file descriptor, or < 0 on error */
|
||||
extern "C"
|
||||
int
|
||||
innobase_mysql_tmpfile(void)
|
||||
/*========================*/
|
||||
{
|
||||
int fd; /* handle of opened file */
|
||||
HANDLE osfh; /* OS handle of opened file */
|
||||
char* tmpdir; /* point to the directory
|
||||
where to create file */
|
||||
TCHAR path_buf[MAX_PATH - 14]; /* buffer for tmp file path.
|
||||
The length cannot be longer
|
||||
than MAX_PATH - 14, or
|
||||
GetTempFileName will fail. */
|
||||
char filename[MAX_PATH]; /* name of the tmpfile */
|
||||
DWORD fileaccess = GENERIC_READ /* OS file access */
|
||||
| GENERIC_WRITE
|
||||
| DELETE;
|
||||
DWORD fileshare = FILE_SHARE_READ /* OS file sharing mode */
|
||||
| FILE_SHARE_WRITE
|
||||
| FILE_SHARE_DELETE;
|
||||
DWORD filecreate = CREATE_ALWAYS; /* OS method of open/create */
|
||||
DWORD fileattrib = /* OS file attribute flags */
|
||||
FILE_ATTRIBUTE_NORMAL
|
||||
| FILE_FLAG_DELETE_ON_CLOSE
|
||||
| FILE_ATTRIBUTE_TEMPORARY
|
||||
| FILE_FLAG_SEQUENTIAL_SCAN;
|
||||
|
||||
DBUG_ENTER("innobase_mysql_tmpfile");
|
||||
|
||||
tmpdir = my_tmpdir(&mysql_tmpdir_list);
|
||||
|
||||
/* The tmpdir parameter can not be NULL for GetTempFileName. */
|
||||
if (!tmpdir) {
|
||||
uint ret;
|
||||
|
||||
/* Use GetTempPath to determine path for temporary files. */
|
||||
ret = GetTempPath(sizeof(path_buf), path_buf);
|
||||
if (ret > sizeof(path_buf) || (ret == 0)) {
|
||||
|
||||
_dosmaperr(GetLastError()); /* map error */
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
tmpdir = path_buf;
|
||||
}
|
||||
|
||||
/* Use GetTempFileName to generate a unique filename. */
|
||||
if (!GetTempFileName(tmpdir, "ib", 0, filename)) {
|
||||
|
||||
_dosmaperr(GetLastError()); /* map error */
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
DBUG_PRINT("info", ("filename: %s", filename));
|
||||
|
||||
/* Open/Create the file. */
|
||||
osfh = CreateFile(filename, fileaccess, fileshare, NULL,
|
||||
filecreate, fileattrib, NULL);
|
||||
if (osfh == INVALID_HANDLE_VALUE) {
|
||||
|
||||
/* open/create file failed! */
|
||||
_dosmaperr(GetLastError()); /* map error */
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
|
||||
do {
|
||||
/* Associates a CRT file descriptor with the OS file handle. */
|
||||
fd = _open_osfhandle((intptr_t) osfh, 0);
|
||||
} while (fd == -1 && errno == EINTR);
|
||||
|
||||
if (fd == -1) {
|
||||
/* Open failed, close the file handle. */
|
||||
|
||||
_dosmaperr(GetLastError()); /* map error */
|
||||
CloseHandle(osfh); /* no need to check if
|
||||
CloseHandle fails */
|
||||
}
|
||||
|
||||
DBUG_RETURN(fd);
|
||||
}
|
||||
#else
|
||||
/*************************************************************************
|
||||
Creates a temporary file. */
|
||||
extern "C"
|
||||
@@ -937,6 +1031,7 @@ innobase_mysql_tmpfile(void)
|
||||
}
|
||||
return(fd2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
Wrapper around MySQL's copy_and_convert function, see it for
|
||||
|
||||
78
storage/innodb_plugin/CMakeLists.txt
Normal file
78
storage/innodb_plugin/CMakeLists.txt
Normal file
@@ -0,0 +1,78 @@
|
||||
# Copyright (C) 2009 Oracle/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
|
||||
|
||||
# This is the CMakeLists for InnoDB Plugin
|
||||
|
||||
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
IF (CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
SET(WIN64 TRUE)
|
||||
ENDIF (CMAKE_SIZEOF_VOID_P MATCHES 8)
|
||||
|
||||
# Include directories under innodb_plugin
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innodb_plugin/include
|
||||
${CMAKE_SOURCE_DIR}/storage/innodfb_plugin/handler)
|
||||
|
||||
# Include directories under mysql
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/sql
|
||||
${CMAKE_SOURCE_DIR}/regex
|
||||
${CMAKE_SOURCE_DIR}/zlib
|
||||
${CMAKE_SOURCE_DIR}/extra/yassl/include)
|
||||
|
||||
# Removing compiler optimizations for innodb/mem/* files on 64-bit Windows
|
||||
# due to 64-bit compiler error, See MySQL Bug #19424, #36366, #34297
|
||||
IF(MSVC AND $(WIN64))
|
||||
SET_SOURCE_FILES_PROPERTIES(mem/mem0mem.c mem/mem0pool.c
|
||||
PROPERTIES COMPILE_FLAGS -Od)
|
||||
ENDIF(MSVC AND $(WIN64))
|
||||
|
||||
SET(INNODB_PLUGIN_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)
|
||||
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DINNODB_RW_LOCKS_USE_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION)
|
||||
MYSQL_STORAGE_ENGINE(INNODB_PLUGIN)
|
||||
351
storage/innodb_plugin/COPYING
Normal file
351
storage/innodb_plugin/COPYING
Normal file
@@ -0,0 +1,351 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
========
|
||||
|
||||
The licenses for most software are designed to take away your freedom
|
||||
to share and change it. By contrast, the GNU General Public License is
|
||||
intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not price.
|
||||
Our General Public Licenses are designed to make sure that you have
|
||||
the freedom to distribute copies of free software (and charge for this
|
||||
service if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid anyone
|
||||
to deny you these rights or to ask you to surrender the rights. These
|
||||
restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that you
|
||||
have. You must make sure that they, too, receive or can get the source
|
||||
code. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software patents.
|
||||
We wish to avoid the danger that redistributors of a free program will
|
||||
individually obtain patent licenses, in effect making the program
|
||||
proprietary. To prevent this, we have made it clear that any patent
|
||||
must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
0. This License applies to any program or other work which contains a
|
||||
notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program",
|
||||
below, refers to any such program or work, and a "work based on
|
||||
the Program" means either the Program or any derivative work under
|
||||
copyright law: that is to say, a work containing the Program or a
|
||||
portion of it, either verbatim or with modifications and/or
|
||||
translated into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".) Each
|
||||
licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are
|
||||
not covered by this License; they are outside its scope. The act
|
||||
of running the Program is not restricted, and the output from the
|
||||
Program is covered only if its contents constitute a work based on
|
||||
the Program (independent of having been made by running the
|
||||
Program). Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any
|
||||
warranty; and give any other recipients of the Program a copy of
|
||||
this License along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange
|
||||
for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a. You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b. You must cause any work that you distribute or publish, that
|
||||
in whole or in part contains or is derived from the Program
|
||||
or any part thereof, to be licensed as a whole at no charge
|
||||
to all third parties under the terms of this License.
|
||||
|
||||
c. If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display
|
||||
an announcement including an appropriate copyright notice and
|
||||
a notice that there is no warranty (or else, saying that you
|
||||
provide a warranty) and that users may redistribute the
|
||||
program under these conditions, and telling the user how to
|
||||
view a copy of this License. (Exception: if the Program
|
||||
itself is interactive but does not normally print such an
|
||||
announcement, your work based on the Program is not required
|
||||
to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the
|
||||
Program, and can be reasonably considered independent and separate
|
||||
works in themselves, then this License, and its terms, do not
|
||||
apply to those sections when you distribute them as separate
|
||||
works. But when you distribute the same sections as part of a
|
||||
whole which is a work based on the Program, the distribution of
|
||||
the whole must be on the terms of this License, whose permissions
|
||||
for other licensees extend to the entire whole, and thus to each
|
||||
and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or
|
||||
contest your rights to work written entirely by you; rather, the
|
||||
intent is to exercise the right to control the distribution of
|
||||
derivative or collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the
|
||||
Program with the Program (or with a work based on the Program) on
|
||||
a volume of a storage or distribution medium does not bring the
|
||||
other work under the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms
|
||||
of Sections 1 and 2 above provided that you also do one of the
|
||||
following:
|
||||
|
||||
a. Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Sections 1 and 2 above on a medium customarily used for
|
||||
software interchange; or,
|
||||
|
||||
b. Accompany it with a written offer, valid for at least three
|
||||
years, to give any third-party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange; or,
|
||||
|
||||
c. Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with
|
||||
such an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete
|
||||
source code means all the source code for all modules it contains,
|
||||
plus any associated interface definition files, plus the scripts
|
||||
used to control compilation and installation of the executable.
|
||||
However, as a special exception, the source code distributed need
|
||||
not include anything that is normally distributed (in either
|
||||
source or binary form) with the major components (compiler,
|
||||
kernel, and so on) of the operating system on which the executable
|
||||
runs, unless that component itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this
|
||||
License. However, parties who have received copies, or rights,
|
||||
from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify
|
||||
or distribute the Program or its derivative works. These actions
|
||||
are prohibited by law if you do not accept this License.
|
||||
Therefore, by modifying or distributing the Program (or any work
|
||||
based on the Program), you indicate your acceptance of this
|
||||
License to do so, and all its terms and conditions for copying,
|
||||
distributing or modifying the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program
|
||||
subject to these terms and conditions. You may not impose any
|
||||
further restrictions on the recipients' exercise of the rights
|
||||
granted herein. You are not responsible for enforcing compliance
|
||||
by third parties to this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent
|
||||
issues), conditions are imposed on you (whether by court order,
|
||||
agreement or otherwise) that contradict the conditions of this
|
||||
License, they do not excuse you from the conditions of this
|
||||
License. If you cannot distribute so as to satisfy simultaneously
|
||||
your obligations under this License and any other pertinent
|
||||
obligations, then as a consequence you may not distribute the
|
||||
Program at all. For example, if a patent license would not permit
|
||||
royalty-free redistribution of the Program by all those who
|
||||
receive copies directly or indirectly through you, then the only
|
||||
way you could satisfy both it and this License would be to refrain
|
||||
entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable
|
||||
under any particular circumstance, the balance of the section is
|
||||
intended to apply and the section as a whole is intended to apply
|
||||
in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of
|
||||
any such claims; this section has the sole purpose of protecting
|
||||
the integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is
|
||||
willing to distribute software through any other system and a
|
||||
licensee cannot impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed
|
||||
to be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces,
|
||||
the original copyright holder who places the Program under this
|
||||
License may add an explicit geographical distribution limitation
|
||||
excluding those countries, so that distribution is permitted only
|
||||
in or among countries not thus excluded. In such case, this
|
||||
License incorporates the limitation as if written in the body of
|
||||
this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new
|
||||
versions of the General Public License from time to time. Such
|
||||
new versions will be similar in spirit to the present version, but
|
||||
may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies a version number of this License which applies
|
||||
to it and "any later version", you have the option of following
|
||||
the terms and conditions either of that version or of any later
|
||||
version published by the Free Software Foundation. If the Program
|
||||
does not specify a version number of this License, you may choose
|
||||
any version ever published by the Free Software Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the
|
||||
author to ask for permission. For software which is copyrighted
|
||||
by the Free Software Foundation, write to the Free Software
|
||||
Foundation; we sometimes make exceptions for this. Our decision
|
||||
will be guided by the two goals of preserving the free status of
|
||||
all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
|
||||
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
|
||||
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT
|
||||
NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE
|
||||
QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY
|
||||
SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
|
||||
MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
|
||||
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
|
||||
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
|
||||
INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
|
||||
OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY
|
||||
OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
How to Apply These Terms to Your New Programs
|
||||
=============================================
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these
|
||||
terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest to
|
||||
attach them to the start of each source file to most effectively convey
|
||||
the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES.
|
||||
Copyright (C) YYYY NAME OF AUTHOR
|
||||
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the
|
||||
appropriate parts of the General Public License. Of course, the
|
||||
commands you use may be called something other than `show w' and `show
|
||||
c'; they could even be mouse-clicks or menu items--whatever suits your
|
||||
program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
SIGNATURE OF TY COON, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library,
|
||||
you may consider it more useful to permit linking proprietary
|
||||
applications with the library. If this is what you want to do, use the
|
||||
GNU Library General Public License instead of this License.
|
||||
30
storage/innodb_plugin/COPYING.Google
Normal file
30
storage/innodb_plugin/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.
|
||||
30
storage/innodb_plugin/COPYING.Percona
Normal file
30
storage/innodb_plugin/COPYING.Percona
Normal file
@@ -0,0 +1,30 @@
|
||||
Portions of this software contain modifications contributed by Percona, Inc.
|
||||
These contributions are used with the following license:
|
||||
|
||||
Copyright (c) 2008, 2009, Percona 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 Percona 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.
|
||||
31
storage/innodb_plugin/COPYING.Sun_Microsystems
Normal file
31
storage/innodb_plugin/COPYING.Sun_Microsystems
Normal file
@@ -0,0 +1,31 @@
|
||||
Portions of this software contain modifications contributed by
|
||||
Sun Microsystems, Inc. These contributions are used with the following
|
||||
license:
|
||||
|
||||
Copyright (c) 2009, Sun Microsystems, 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 Sun Microsystems, 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.
|
||||
1149
storage/innodb_plugin/ChangeLog
Normal file
1149
storage/innodb_plugin/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
1419
storage/innodb_plugin/Doxyfile
Normal file
1419
storage/innodb_plugin/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
343
storage/innodb_plugin/Makefile.am
Normal file
343
storage/innodb_plugin/Makefile.am
Normal file
@@ -0,0 +1,343 @@
|
||||
# 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$(srcdir)/include \
|
||||
-I$(top_srcdir)/sql \
|
||||
-I$(srcdir) @ZLIB_INCLUDES@
|
||||
|
||||
DEFS= @DEFS@
|
||||
|
||||
|
||||
noinst_HEADERS= \
|
||||
handler/ha_innodb.h \
|
||||
handler/handler0vars.h \
|
||||
handler/i_s.h \
|
||||
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/fsp0types.h \
|
||||
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/ha_prototypes.h \
|
||||
include/handler0alter.h \
|
||||
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 \
|
||||
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/page0types.h \
|
||||
include/page0zip.h \
|
||||
include/page0zip.ic \
|
||||
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/ut0auxconf.h \
|
||||
include/ut0byte.h \
|
||||
include/ut0byte.ic \
|
||||
include/ut0dbg.h \
|
||||
include/ut0list.h \
|
||||
include/ut0list.ic \
|
||||
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/ut0wqueue.h \
|
||||
mem/mem0dbg.c
|
||||
|
||||
EXTRA_LIBRARIES= libinnobase.a
|
||||
noinst_LIBRARIES= @plugin_innodb_plugin_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 \
|
||||
handler/ha_innodb.cc \
|
||||
handler/handler0alter.cc \
|
||||
handler/i_s.cc \
|
||||
handler/mysql_addons.cc \
|
||||
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
|
||||
|
||||
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
|
||||
libinnobase_a_CFLAGS= $(AM_CFLAGS)
|
||||
|
||||
EXTRA_LTLIBRARIES= ha_innodb_plugin.la
|
||||
pkgplugin_LTLIBRARIES= @plugin_innodb_plugin_shared_target@
|
||||
|
||||
ha_innodb_plugin_la_LDFLAGS= -module -rpath $(pkgplugindir)
|
||||
ha_innodb_plugin_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
|
||||
ha_innodb_plugin_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
|
||||
ha_innodb_plugin_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.%
|
||||
29
storage/innodb_plugin/README
Normal file
29
storage/innodb_plugin/README
Normal file
@@ -0,0 +1,29 @@
|
||||
This is the source of the InnoDB Plugin 1.0.4 for MySQL 5.1
|
||||
===========================================================
|
||||
|
||||
Instructions for compiling the plugin:
|
||||
--------------------------------------
|
||||
|
||||
1. Get the latest MySQL 5.1 sources from
|
||||
http://dev.mysql.com/downloads/mysql/5.1.html#source
|
||||
|
||||
2. Replace the contents of the mysql-5.1.N/storage/innobase/ directory
|
||||
with the contents of this directory.
|
||||
|
||||
3. Optional (only necessary if you are going to run tests from the
|
||||
mysql-test suite): cd into the innobase directory and run ./setup.sh
|
||||
|
||||
4. Compile MySQL as usual.
|
||||
|
||||
5. Enjoy!
|
||||
|
||||
See the online documentation for more detailed instructions:
|
||||
http://www.innodb.com/doc/innodb_plugin-1.0/innodb-plugin-installation.html
|
||||
|
||||
For more information about InnoDB visit
|
||||
http://www.innodb.com
|
||||
|
||||
Please report any problems or issues with the plugin in the InnoDB Forums
|
||||
http://forums.innodb.com/ or in the MySQL Bugs database http://bugs.mysql.com
|
||||
|
||||
Thank you for using the InnoDB plugin!
|
||||
3693
storage/innodb_plugin/btr/btr0btr.c
Normal file
3693
storage/innodb_plugin/btr/btr0btr.c
Normal file
File diff suppressed because it is too large
Load Diff
4847
storage/innodb_plugin/btr/btr0cur.c
Normal file
4847
storage/innodb_plugin/btr/btr0cur.c
Normal file
File diff suppressed because it is too large
Load Diff
582
storage/innodb_plugin/btr/btr0pcur.c
Normal file
582
storage/innodb_plugin/btr/btr0pcur.c
Normal file
@@ -0,0 +1,582 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file btr/btr0pcur.c
|
||||
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.
|
||||
@return own: persistent cursor */
|
||||
UNIV_INTERN
|
||||
btr_pcur_t*
|
||||
btr_pcur_create_for_mysql(void)
|
||||
/*============================*/
|
||||
{
|
||||
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.
|
||||
@return 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 */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_pcur_restore_position(
|
||||
/*======================*/
|
||||
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'.
|
||||
@return TRUE if the cursor was not before first in tree */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_pcur_move_to_prev(
|
||||
/*==================*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
1874
storage/innodb_plugin/btr/btr0sea.c
Normal file
1874
storage/innodb_plugin/btr/btr0sea.c
Normal file
File diff suppressed because it is too large
Load Diff
692
storage/innodb_plugin/buf/buf0buddy.c
Normal file
692
storage/innodb_plugin/buf/buf0buddy.c
Normal file
@@ -0,0 +1,692 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file buf/buf0buddy.c
|
||||
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.
|
||||
@return the buddy relative of page */
|
||||
UNIV_INLINE
|
||||
byte*
|
||||
buf_buddy_get(
|
||||
/*==========*/
|
||||
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_mutex_own());
|
||||
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE);
|
||||
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_pool_mutex_own());
|
||||
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[].
|
||||
@return allocated block, or NULL if buf_pool->zip_free[] was empty */
|
||||
static
|
||||
void*
|
||||
buf_buddy_alloc_zip(
|
||||
/*================*/
|
||||
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);
|
||||
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
|
||||
ut_ad(buf_page_get_state(ut_list_node_313)
|
||||
== BUF_BLOCK_ZIP_FREE)));
|
||||
#endif /* !UNIV_DEBUG_VALGRIND */
|
||||
bpage = UT_LIST_GET_FIRST(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));
|
||||
ut_ad(buf_block_get_state(block) == BUF_BLOCK_READY_FOR_USE);
|
||||
|
||||
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.
|
||||
@return allocated block */
|
||||
static
|
||||
void*
|
||||
buf_buddy_alloc_from(
|
||||
/*=================*/
|
||||
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;
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
|
||||
ut_ad(buf_page_get_state(
|
||||
ut_list_node_313)
|
||||
== BUF_BLOCK_ZIP_FREE)));
|
||||
#endif /* !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.
|
||||
@return allocated block, possibly NULL if lru==NULL */
|
||||
UNIV_INTERN
|
||||
void*
|
||||
buf_buddy_alloc_low(
|
||||
/*================*/
|
||||
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.
|
||||
@return TRUE if relocated */
|
||||
static
|
||||
ibool
|
||||
buf_buddy_relocate_block(
|
||||
/*=====================*/
|
||||
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.
|
||||
@return TRUE if relocated */
|
||||
static
|
||||
ibool
|
||||
buf_buddy_relocate(
|
||||
/*===============*/
|
||||
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[],
|
||||
or BUF_BUDDY_SIZES */
|
||||
{
|
||||
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],
|
||||
ut_ad(buf_page_get_state(ut_list_node_313)
|
||||
== BUF_BLOCK_ZIP_FREE)));
|
||||
#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);
|
||||
|
||||
#ifndef UNIV_DEBUG_VALGRIND
|
||||
/* Valgrind would complain about accessing free memory. */
|
||||
|
||||
/* 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.) */
|
||||
ut_d(UT_LIST_VALIDATE(list, buf_page_t, buf_pool->zip_free[i],
|
||||
ut_ad(buf_page_get_state(
|
||||
ut_list_node_313)
|
||||
== BUF_BLOCK_ZIP_FREE
|
||||
&& ut_list_node_313 != buddy)));
|
||||
#endif /* !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);
|
||||
}
|
||||
3942
storage/innodb_plugin/buf/buf0buf.c
Normal file
3942
storage/innodb_plugin/buf/buf0buf.c
Normal file
File diff suppressed because it is too large
Load Diff
1400
storage/innodb_plugin/buf/buf0flu.c
Normal file
1400
storage/innodb_plugin/buf/buf0flu.c
Normal file
File diff suppressed because it is too large
Load Diff
2066
storage/innodb_plugin/buf/buf0lru.c
Normal file
2066
storage/innodb_plugin/buf/buf0lru.c
Normal file
File diff suppressed because it is too large
Load Diff
819
storage/innodb_plugin/buf/buf0rea.c
Normal file
819
storage/innodb_plugin/buf/buf0rea.c
Normal file
@@ -0,0 +1,819 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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 buf/buf0rea.c
|
||||
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"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/** 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 (1 + BUF_READ_AHEAD_RANDOM_AREA / 2)
|
||||
|
||||
/** The linear read-ahead area size */
|
||||
#define BUF_READ_AHEAD_LINEAR_AREA BUF_READ_AHEAD_AREA
|
||||
|
||||
/** 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.
|
||||
@return 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 */
|
||||
static
|
||||
ulint
|
||||
buf_read_page_low(
|
||||
/*==============*/
|
||||
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.
|
||||
@return 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 positive value! */
|
||||
static
|
||||
ulint
|
||||
buf_read_ahead_random(
|
||||
/*==================*/
|
||||
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;
|
||||
|
||||
/* We have currently disabled random readahead */
|
||||
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.
|
||||
@return number of page read requests issued: this can be greater than
|
||||
1 if read-ahead occurred */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_read_page(
|
||||
/*==========*/
|
||||
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();
|
||||
|
||||
/* 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.
|
||||
@return number of page read requests issued */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_read_ahead_linear(
|
||||
/*==================*/
|
||||
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;
|
||||
ulint threshold;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* How many out of order accessed pages can we ignore
|
||||
when working out the access pattern for linear readahead */
|
||||
threshold = ut_min((64 - srv_read_ahead_threshold),
|
||||
BUF_READ_AHEAD_AREA);
|
||||
|
||||
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) {
|
||||
int res = (ut_ulint_cmp(
|
||||
buf_page_get_LRU_position(bpage),
|
||||
buf_page_get_LRU_position(pred_bpage)));
|
||||
/* Accesses not in the right order */
|
||||
if (res != 0 && res != asc_or_desc) {
|
||||
fail_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail_count > threshold) {
|
||||
/* Too many failures: return */
|
||||
buf_pool_mutex_exit();
|
||||
return(0);
|
||||
}
|
||||
|
||||
if (bpage && buf_page_is_accessed(bpage)) {
|
||||
pred_bpage = bpage;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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();
|
||||
|
||||
#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();
|
||||
|
||||
#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);
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
|
||||
/* It is a single table tablespace and the .ibd file is
|
||||
missing: do nothing */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Recovery applies read-ahead pages %lu\n",
|
||||
(ulong) n_stored);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
24
storage/innodb_plugin/compile-innodb
Executable file
24
storage/innodb_plugin/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
storage/innodb_plugin/compile-innodb-debug
Executable file
24
storage/innodb_plugin/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"
|
||||
764
storage/innodb_plugin/data/data0data.c
Normal file
764
storage/innodb_plugin/data/data0data.c
Normal file
@@ -0,0 +1,764 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file data/data0data.c
|
||||
SQL data field and tuple
|
||||
|
||||
Created 5/30/1994 Heikki Tuuri
|
||||
*************************************************************************/
|
||||
|
||||
#include "data0data.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "data0data.ic"
|
||||
#endif
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "rem0rec.h"
|
||||
#include "rem0cmp.h"
|
||||
#include "page0page.h"
|
||||
#include "page0zip.h"
|
||||
#include "dict0dict.h"
|
||||
#include "btr0cur.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/** Dummy variable to catch access to uninitialized fields. In the
|
||||
debug version, dtuple_create() will make all fields of dtuple_t point
|
||||
to data_error. */
|
||||
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 */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
Tests if dfield data length and content is equal to the given.
|
||||
@return TRUE if equal */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dfield_data_is_binary_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.
|
||||
@return 1, 0 , -1 if tuple1 is greater, equal, less, respectively,
|
||||
than tuple2 */
|
||||
UNIV_INTERN
|
||||
int
|
||||
dtuple_coll_cmp(
|
||||
/*============*/
|
||||
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.
|
||||
@return TRUE if ok */
|
||||
static
|
||||
ibool
|
||||
dfield_check_typed_no_assert(
|
||||
/*=========================*/
|
||||
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.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_check_typed_no_assert(
|
||||
/*=========================*/
|
||||
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);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/**********************************************************//**
|
||||
Checks that a data field is typed. Asserts an error if not.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dfield_check_typed(
|
||||
/*===============*/
|
||||
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.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_check_typed(
|
||||
/*===============*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**********************************************************//**
|
||||
Validates the consistency of a tuple which must be complete, i.e,
|
||||
all fields must have been set.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtuple_validate(
|
||||
/*============*/
|
||||
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 */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************//**
|
||||
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.
|
||||
@return 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 */
|
||||
UNIV_INTERN
|
||||
big_rec_t*
|
||||
dtuple_convert_big_rec(
|
||||
/*===================*/
|
||||
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);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
281
storage/innodb_plugin/data/data0type.c
Normal file
281
storage/innodb_plugin/data/data0type.c
Normal file
@@ -0,0 +1,281 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file data/data0type.c
|
||||
Data types
|
||||
|
||||
Created 1/16/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "data0type.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "data0type.ic"
|
||||
#endif
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "ha_prototypes.h"
|
||||
|
||||
/* 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.
|
||||
@return length of the prefix, in bytes */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
dtype_get_at_most_n_mbchars(
|
||||
/*========================*/
|
||||
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 */
|
||||
{
|
||||
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);
|
||||
}
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
/*********************************************************************//**
|
||||
Checks if a data main type is a string type. Also a BLOB is considered a
|
||||
string type.
|
||||
@return TRUE if string type */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_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.
|
||||
@return TRUE if binary string type */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_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.
|
||||
@return TRUE if non-binary string type */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_is_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.
|
||||
@return precise type, including 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.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dtype_validate(
|
||||
/*===========*/
|
||||
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);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ut_a(type->mbminlen <= type->mbmaxlen);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*********************************************************************//**
|
||||
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);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
462
storage/innodb_plugin/dict/dict0boot.c
Normal file
462
storage/innodb_plugin/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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file dict/dict0boot.c
|
||||
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.
|
||||
@return pointer to the dictionary header, page x-latched */
|
||||
UNIV_INTERN
|
||||
dict_hdr_t*
|
||||
dict_hdr_get(
|
||||
/*=========*/
|
||||
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.
|
||||
@return the new id */
|
||||
UNIV_INTERN
|
||||
dulint
|
||||
dict_hdr_get_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.
|
||||
@return TRUE if succeed */
|
||||
static
|
||||
ibool
|
||||
dict_hdr_create(
|
||||
/*============*/
|
||||
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,
|
||||
dict_ind_redundant, 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,
|
||||
dict_ind_redundant, 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,
|
||||
dict_ind_redundant, 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,
|
||||
dict_ind_redundant, 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,
|
||||
dict_ind_redundant, 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();
|
||||
}
|
||||
1499
storage/innodb_plugin/dict/dict0crea.c
Normal file
1499
storage/innodb_plugin/dict/dict0crea.c
Normal file
File diff suppressed because it is too large
Load Diff
4771
storage/innodb_plugin/dict/dict0dict.c
Normal file
4771
storage/innodb_plugin/dict/dict0dict.c
Normal file
File diff suppressed because it is too large
Load Diff
1450
storage/innodb_plugin/dict/dict0load.c
Normal file
1450
storage/innodb_plugin/dict/dict0load.c
Normal file
File diff suppressed because it is too large
Load Diff
319
storage/innodb_plugin/dict/dict0mem.c
Normal file
319
storage/innodb_plugin/dict/dict0mem.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************//**
|
||||
@file dict/dict0mem.c
|
||||
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"
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# include "lock0lock.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
|
||||
creating a table or index object */
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates a table memory object.
|
||||
@return own: table object */
|
||||
UNIV_INTERN
|
||||
dict_table_t*
|
||||
dict_mem_table_create(
|
||||
/*==================*/
|
||||
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));
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
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;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_d(table->magic_n = DICT_TABLE_MAGIC_N);
|
||||
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);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
mutex_free(&(table->autoinc_mutex));
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
mem_heap_free(table->heap);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Append 'name' to 'col_names'. @see dict_table_t::col_names
|
||||
@return new column names array */
|
||||
static
|
||||
const char*
|
||||
dict_add_col_name(
|
||||
/*==============*/
|
||||
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;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint mbminlen;
|
||||
ulint mbmaxlen;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
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;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen);
|
||||
|
||||
col->mbminlen = (unsigned int) mbminlen;
|
||||
col->mbmaxlen = (unsigned int) mbmaxlen;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Creates an index memory object.
|
||||
@return own: index object */
|
||||
UNIV_INTERN
|
||||
dict_index_t*
|
||||
dict_mem_index_create(
|
||||
/*==================*/
|
||||
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;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
index->space = (unsigned int) space;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
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.
|
||||
@return own: foreign constraint struct */
|
||||
UNIV_INTERN
|
||||
dict_foreign_t*
|
||||
dict_mem_foreign_create(void)
|
||||
/*=========================*/
|
||||
{
|
||||
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);
|
||||
}
|
||||
65
storage/innodb_plugin/dyn/dyn0dyn.c
Normal file
65
storage/innodb_plugin/dyn/dyn0dyn.c
Normal file
@@ -0,0 +1,65 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file dyn/dyn0dyn.c
|
||||
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.
|
||||
@return created block */
|
||||
UNIV_INTERN
|
||||
dyn_block_t*
|
||||
dyn_array_add_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);
|
||||
}
|
||||
852
storage/innodb_plugin/eval/eval0eval.c
Normal file
852
storage/innodb_plugin/eval/eval0eval.c
Normal file
@@ -0,0 +1,852 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file eval/eval0eval.c
|
||||
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
|
||||
eval_node_alloc_val_buf */
|
||||
|
||||
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.
|
||||
@return pointer to allocated buffer */
|
||||
UNIV_INTERN
|
||||
byte*
|
||||
eval_node_alloc_val_buf(
|
||||
/*====================*/
|
||||
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.
|
||||
@return the result of the comparison */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
eval_cmp(
|
||||
/*=====*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
295
storage/innodb_plugin/eval/eval0proc.c
Normal file
295
storage/innodb_plugin/eval/eval0proc.c
Normal file
@@ -0,0 +1,295 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file eval/eval0proc.c
|
||||
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.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
if_step(
|
||||
/*====*/
|
||||
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.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
while_step(
|
||||
/*=======*/
|
||||
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.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
assign_step(
|
||||
/*========*/
|
||||
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.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
for_step(
|
||||
/*=====*/
|
||||
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.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
exit_step(
|
||||
/*======*/
|
||||
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.
|
||||
@return query thread to run next or NULL */
|
||||
UNIV_INTERN
|
||||
que_thr_t*
|
||||
return_step(
|
||||
/*========*/
|
||||
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);
|
||||
}
|
||||
4737
storage/innodb_plugin/fil/fil0fil.c
Normal file
4737
storage/innodb_plugin/fil/fil0fil.c
Normal file
File diff suppressed because it is too large
Load Diff
4244
storage/innodb_plugin/fsp/fsp0fsp.c
Normal file
4244
storage/innodb_plugin/fsp/fsp0fsp.c
Normal file
File diff suppressed because it is too large
Load Diff
31
storage/innodb_plugin/fut/fut0fut.c
Normal file
31
storage/innodb_plugin/fut/fut0fut.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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 fut/fut0fut.c
|
||||
File-based utilities
|
||||
|
||||
Created 12/13/1995 Heikki Tuuri
|
||||
***********************************************************************/
|
||||
|
||||
#include "fut0fut.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "fut0fut.ic"
|
||||
#endif
|
||||
|
||||
530
storage/innodb_plugin/fut/fut0lst.c
Normal file
530
storage/innodb_plugin/fut/fut0lst.c
Normal file
@@ -0,0 +1,530 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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 fut/fut0lst.c
|
||||
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.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
flst_validate(
|
||||
/*==========*/
|
||||
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);
|
||||
}
|
||||
441
storage/innodb_plugin/ha/ha0ha.c
Normal file
441
storage/innodb_plugin/ha/ha0ha.c
Normal file
@@ -0,0 +1,441 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/********************************************************************//**
|
||||
@file ha/ha0ha.c
|
||||
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 at least n array cells. The actual number
|
||||
of cells is chosen to be a prime number slightly bigger than n.
|
||||
@return own: created table */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
ha_create_func(
|
||||
/*===========*/
|
||||
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;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ulint i;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_ad(ut_is_2pow(n_mutexes));
|
||||
table = hash_create(n);
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
table->adaptive = TRUE;
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
#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);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
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]);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
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 */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/* Free the memory heaps. */
|
||||
n = table->n_mutexes;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
mem_heap_free(table->heaps[i]);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* 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.
|
||||
@return TRUE if succeed, FALSE if no more memory could be allocated */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_insert_for_fold_func(
|
||||
/*====================*/
|
||||
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 */
|
||||
ASSERT_HASH_MUTEX_OWN(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
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
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++;
|
||||
}
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
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
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
if (table->adaptive) {
|
||||
block->n_pointers++;
|
||||
}
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
#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
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
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_HOTBACKUP */
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
|
||||
HASH_DELETE_AND_COMPACT(ha_node_t, next, table, del_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/out: 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;
|
||||
|
||||
ASSERT_HASH_MUTEX_OWN(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
|
||||
# ifndef UNIV_HOTBACKUP
|
||||
if (table->adaptive) {
|
||||
ut_a(node->block->n_pointers > 0);
|
||||
node->block->n_pointers--;
|
||||
new_block->n_pointers++;
|
||||
}
|
||||
# endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
node->block = new_block;
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
node->data = new_data;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*****************************************************************//**
|
||||
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;
|
||||
|
||||
ASSERT_HASH_MUTEX_OWN(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.
|
||||
@return TRUE if ok */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
ha_validate(
|
||||
/*========*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
184
storage/innodb_plugin/ha/ha0storage.c
Normal file
184
storage/innodb_plugin/ha/ha0storage.c
Normal file
@@ -0,0 +1,184 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file ha/ha0storage.c
|
||||
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 */
|
||||
174
storage/innodb_plugin/ha/hash0hash.c
Normal file
174
storage/innodb_plugin/ha/hash0hash.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
/**************************************************//**
|
||||
@file ha/hash0hash.c
|
||||
The simple hash table utility
|
||||
|
||||
Created 5/20/1997 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#include "hash0hash.h"
|
||||
#ifdef UNIV_NONINL
|
||||
#include "hash0hash.ic"
|
||||
#endif
|
||||
|
||||
#include "mem0mem.h"
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/************************************************************//**
|
||||
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);
|
||||
}
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/*************************************************************//**
|
||||
Creates a hash table with >= n array cells. The actual number of cells is
|
||||
chosen to be a prime number slightly bigger than n.
|
||||
@return own: created table */
|
||||
UNIV_INTERN
|
||||
hash_table_t*
|
||||
hash_create(
|
||||
/*========*/
|
||||
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);
|
||||
|
||||
table->array = array;
|
||||
table->n_cells = prime;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
table->adaptive = FALSE;
|
||||
# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
table->n_mutexes = 0;
|
||||
table->mutexes = NULL;
|
||||
table->heaps = NULL;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
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 */
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
ut_a(table->mutexes == NULL);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
ut_free(table->array);
|
||||
mem_free(table);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*************************************************************//**
|
||||
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;
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
4
storage/innodb_plugin/ha_innodb.def
Normal file
4
storage/innodb_plugin/ha_innodb.def
Normal file
@@ -0,0 +1,4 @@
|
||||
EXPORTS
|
||||
_mysql_plugin_interface_version_
|
||||
_mysql_sizeof_struct_st_plugin_
|
||||
_mysql_plugin_declarations_
|
||||
10174
storage/innodb_plugin/handler/ha_innodb.cc
Normal file
10174
storage/innodb_plugin/handler/ha_innodb.cc
Normal file
File diff suppressed because it is too large
Load Diff
284
storage/innodb_plugin/handler/ha_innodb.h
Normal file
284
storage/innodb_plugin/handler/ha_innodb.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/*****************************************************************************
|
||||
|
||||
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
|
||||
|
||||
/** InnoDB table share */
|
||||
typedef struct st_innobase_share {
|
||||
THR_LOCK lock; /*!< MySQL lock protecting
|
||||
this structure */
|
||||
const char* table_name; /*!< InnoDB table name */
|
||||
uint use_count; /*!< reference count,
|
||||
incremented in get_share()
|
||||
and decremented in free_share() */
|
||||
void* table_name_hash;/*!< hash table chain node */
|
||||
} INNOBASE_SHARE;
|
||||
|
||||
|
||||
/** InnoDB B-tree index */
|
||||
struct dict_index_struct;
|
||||
/** Prebuilt structures in an Innobase table handle used within MySQL */
|
||||
struct row_prebuilt_struct;
|
||||
|
||||
/** InnoDB B-tree index */
|
||||
typedef struct dict_index_struct dict_index_t;
|
||||
/** Prebuilt structures in an Innobase table handle used within MySQL */
|
||||
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; /*!< information for MySQL
|
||||
table locking */
|
||||
|
||||
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();
|
||||
|
||||
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;
|
||||
/********************************************************************//**
|
||||
@file handler/ha_innodb.h
|
||||
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.
|
||||
@return MySQL error code */
|
||||
extern "C"
|
||||
int
|
||||
convert_error_code_to_mysql(
|
||||
/*========================*/
|
||||
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.
|
||||
@return InnoDB transaction handle */
|
||||
extern "C"
|
||||
trx_t*
|
||||
innobase_trx_allocate(
|
||||
/*==================*/
|
||||
MYSQL_THD thd); /*!< in: user thread handle */
|
||||
1216
storage/innodb_plugin/handler/handler0alter.cc
Normal file
1216
storage/innodb_plugin/handler/handler0alter.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