diff --git a/CMakeLists.txt b/CMakeLists.txt index c9ca4344e5d..1fcc92212bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,14 @@ SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -D_LIB) +# Bug 19424 - InnoDB: Possibly a memory overrun of the buffer being freed (64-bit Visual C) +# Removing Win64 compiler optimizations for all innodb/mem/* files. +IF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 8) + SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_DIR}/storage/innobase/mem/mem0mem.c + ${CMAKE_SOURCE_DIR}/storage/innobase/mem/mem0pool.c + PROPERTIES COMPILE_FLAGS -Od) +ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 8) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/storage/innobase/include ${CMAKE_SOURCE_DIR}/storage/innobase/handler @@ -61,4 +69,28 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c IF(NOT SOURCE_SUBLIBS) ADD_LIBRARY(innobase ${INNOBASE_SOURCES}) ADD_DEPENDENCIES(innobase GenError) + + IF(INNODB_DYNAMIC_PLUGIN) + # The dynamic plugin requires CMake 2.6.0 or later. Otherwise, the /DELAYLOAD property + # will not be set + CMAKE_MINIMUM_REQUIRED(VERSION 2.6.0 FATAL_ERROR) + ADD_LIBRARY(ha_innodb SHARED ${INNOBASE_SOURCES} ha_innodb.def handler/win_delay_loader.cc) + ADD_DEPENDENCIES(ha_innodb GenError mysqld) + # If build type is not specified as Release, default to Debug + # This is a workaround to a problem in CMake 2.6, which does not + # set the path of mysqld.lib correctly + IF(CMAKE_BUILD_TYPE MATCHES Release) + SET(CMAKE_BUILD_TYPE "Release") + ELSE(CMAKE_BUILD_TYPE MATCHES Release) + SET(CMAKE_BUILD_TYPE "Debug") + ENDIF(CMAKE_BUILD_TYPE MATCHES Release) + TARGET_LINK_LIBRARIES(ha_innodb strings zlib) + TARGET_LINK_LIBRARIES(ha_innodb ${CMAKE_SOURCE_DIR}/sql/${CMAKE_BUILD_TYPE}/mysqld.lib) + SET_TARGET_PROPERTIES(ha_innodb PROPERTIES OUTPUT_NAME ha_innodb) + SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/MAP /MAPINFO:EXPORTS") + SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/ENTRY:\"_DllMainCRTStartup@12\"") + SET_TARGET_PROPERTIES(ha_innodb PROPERTIES COMPILE_FLAGS "-DMYSQL_DYNAMIC_PLUGIN") + SET_TARGET_PROPERTIES(ha_innodb PROPERTIES LINK_FLAGS "/DELAYLOAD:mysqld.exe") + ENDIF(INNODB_DYNAMIC_PLUGIN) + ENDIF(NOT SOURCE_SUBLIBS) diff --git a/ChangeLog b/ChangeLog index 95895968192..0a4b01ef406 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,12 +1,53 @@ +2008-10-31 The InnoDB Team + + * dict/dict0mem.c, include/dict0mem.h, include/lock0lock.h, + include/row0mysql.h, include/trx0trx.h, include/univ.i, + include/ut0vec.h, include/ut0vec.ic, lock/lock0lock.c, + row/row0mysql.c, trx/trx0trx.c: + Fix Bug#26316 Triggers create duplicate entries on auto-increment + columns + +2008-10-30 The InnoDB Team + + * handler/ha_innodb.cc, handler/handler0vars.h, + handler/win_delay_loader.cc, mysql-test/innodb_bug40360.result, + mysql-test/innodb_bug40360.test: + Fix Bug#40360 Binlog related errors with binlog off + +2008-10-29 The InnoDB Team + + * include/data0type.ic: + Fix Bug#40369 dtype_get_sql_null_size() returns 0 or 1, not the size + +2008-10-29 The InnoDB Team + + * handler/ha_innodb.cc, include/srv0srv.h, srv/srv0srv.c: + Fix Bug#38189 innodb_stats_on_metadata missing + +2008-10-28 The InnoDB Team + + * CMakeLists.txt, ha_innodb.def, handler/ha_innodb.cc, + handler/handler0alter.cc, handler/handler0vars.h, handler/i_s.cc, + handler/win_delay_loader.cc, win-plugin/*: + Implemented the delayloading of externals for the plugin on Windows. + This makes it possible to build a dynamic plugin (ha_innodb.dll) on + Windows. + +2008-10-27 The InnoDB Team + + * CMakeLists.txt: + Fix Bug#19424 InnoDB: Possibly a memory overrun of the buffer being + freed (64-bit Visual C) + 2008-10-23 The InnoDB Team * ibuf/ibuf0ibuf.c: - ibuf_delete_rec(): When the cursor to the insert buffer record cannot be restored, do not complain if the tablespace does not exist, because the insert buffer record may have been discarded by - some other thread. This bug has existed in MySQL/InnoDB since + some other thread. This bug has existed in MySQL/InnoDB since version 4.1, when innodb_file_per_table was implemented. + This may fix Bug#27276 InnoDB Error: ibuf cursor restoration fails. 2008-10-22 The InnoDB Team @@ -27,25 +68,25 @@ 2008-10-16 The InnoDB Team - * dict/dict0dict.c, - mysql-test/innodb-index.result, mysql-test/innodb-index.test: + * dict/dict0dict.c, mysql-test/innodb-index.result, + mysql-test/innodb-index.test: Skip the undo log size check when creating REDUNDANT and COMPACT - tables. In ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED, column + tables. In ROW_FORMAT=DYNAMIC and ROW_FORMAT=COMPRESSED, column prefix indexes require that prefixes of externally stored columns be written to the undo log. This may make the undo log record - bigger than the record on the B-tree page. The maximum size of an - undo log record is the page size. That must be checked for, in - dict_index_add_to_cache(). However, this restriction must not + bigger than the record on the B-tree page. The maximum size of an + undo log record is the page size. That must be checked for, in + dict_index_add_to_cache(). However, this restriction must not be enforced on REDUNDANT or COMPACT tables. 2008-10-15 The InnoDB Team - * btr/btr0cur.c, include/btr0cur.h, row/row0ext.c, - row/row0sel.c, row/row0upd.c: + * btr/btr0cur.c, include/btr0cur.h, row/row0ext.c, row/row0sel.c, + row/row0upd.c: When the server crashes while freeing an externally stored column of a compressed table, the BTR_EXTERN_LEN field in the BLOB - pointer will be written as 0. Tolerate this in the functions that - deal with externally stored columns. This fixes problems after + pointer will be written as 0. Tolerate this in the functions that + deal with externally stored columns. This fixes problems after crash recovery, in the rollback of incomplete transactions, and in the purge of delete-marked records. @@ -53,12 +94,12 @@ * btr/btr0btr.c, include/page0zip.h, page/page0zip.c, include/univ.i: When a B-tree node of a compressed table is split or merged, the - compression may fail. In this case, the entire compressed page - will be copied and the excess records will be deleted. However, + compression may fail. In this case, the entire compressed page + will be copied and the excess records will be deleted. However, page_zip_copy(), now renamed to page_zip_copy_recs(), copied too many fields in the page header, overwriting PAGE_BTR_SEG_LEAF and - PAGE_BTR_SEG_TOP when splitting the B-tree root. This caused - corruption of compressed tables. Furthermore, the lock table and + PAGE_BTR_SEG_TOP when splitting the B-tree root. This caused + corruption of compressed tables. Furthermore, the lock table and the adaptive hash index would be corrupted, because we forgot to update them when invoking page_zip_copy_recs(). @@ -69,10 +110,10 @@ * handler/handler0alter.cc, include/row0merge.h, row/row0merge.c, row/row0mysql.c: - Fix some locking issues, mainly in fast index creation. The + Fix some locking issues, mainly in fast index creation. The InnoDB data dictionary cache should be latched whenever a transaction is holding locks on any data dictionary tables. - Otherwise, lock waits or deadlocks could occur. Furthermore, the + Otherwise, lock waits or deadlocks could occur. Furthermore, the data dictionary transaction must be committed (and the locks released) before the data dictionary latch is released. @@ -92,13 +133,14 @@ 2008-10-08 The InnoDB Team * dict/dict0crea.c, trx/trx0roll.c, include/row0mysql.h, - row/row0merge.c, row/row0mysql.c: When dropping a table, hold the - data dictionary latch until the transaction has been committed. - The data dictionary latch is supposed to prevent lock waits and - deadlocks in the data dictionary tables. Due to this bug, - DROP TABLE could cause a deadlock or hang. Note that because of - Bug#33650 and Bug#39833, MySQL may also drop a (temporary) table - when executing CREATE INDEX or ALTER TABLE ... ADD INDEX. + row/row0merge.c, row/row0mysql.c: + When dropping a table, hold the data dictionary latch until the + transaction has been committed. The data dictionary latch is + supposed to prevent lock waits and deadlocks in the data + dictionary tables. Due to this bug, DROP TABLE could cause a + deadlock or hang. Note that because of Bug#33650 and Bug#39833, + MySQL may also drop a (temporary) table when executing CREATE INDEX + or ALTER TABLE ... ADD INDEX. 2008-10-04 The InnoDB Team @@ -137,8 +179,8 @@ * mysql-test/innodb-index.test, mysql-test/innodb-index.result, mysql-test/innodb-timeout.test, mysql-test/innodb-timeout.result, - srv/srv0srv.c, include/srv0srv.h, - handler/ha_innodb.cc, include/ha_prototypes.h: + srv/srv0srv.c, include/srv0srv.h, handler/ha_innodb.cc, + include/ha_prototypes.h: Fix Bug#36285 innodb_lock_wait_timeout is not dynamic, not per session 2008-09-19 The InnoDB Team @@ -151,15 +193,14 @@ 2008-09-17 The InnoDB Team * mysql-test/innodb.result, mysql-test/innodb-zip.result, - mysql-test/innodb-zip.test, mysql-test/innodb.test, - ibuf/ibuf0ibuf.c, dict/dict0crea.c, dict/dict0load.c, dict/dict0boot.c, - include/dict0dict.h, include/trx0trx.h, - dict/dict0dict.c, trx/trx0trx.c, - include/ha_prototypes.h, handler/ha_innodb.cc: + mysql-test/innodb-zip.test, mysql-test/innodb.test, ibuf/ibuf0ibuf.c, + dict/dict0crea.c, dict/dict0load.c, dict/dict0boot.c, + include/dict0dict.h, include/trx0trx.h, dict/dict0dict.c, + trx/trx0trx.c, include/ha_prototypes.h, handler/ha_innodb.cc: When creating an index in innodb_strict_mode, check that the maximum record size will never exceed the B-tree page size limit. For uncompressed tables, there should always be enough space for - two records in an empty B-tree page. For compressed tables, there + two records in an empty B-tree page. For compressed tables, there should be enough space for storing two node pointer records or one data record in an empty page in uncompressed format. The purpose of this check is to guarantee that INSERT or UPDATE @@ -168,12 +209,11 @@ 2008-09-17 The InnoDB Team * btr/btr0cur.c, data/data0data.c, include/page0zip.h, - include/page0zip.ic, page/page0zip.c, - mysql-test/innodb_bug36172.test: + include/page0zip.ic, page/page0zip.c, mysql-test/innodb_bug36172.test: Prevent infinite B-tree page splits in compressed tables by ensuring that there will always be enough space for two node - pointer records in an empty B-tree page. Also, require that at - least one data record will fit in an empty compressed page. This + pointer records in an empty B-tree page. Also, require that at + least one data record will fit in an empty compressed page. This will reduce the maximum size of records in compressed tables. 2008-09-09 The InnoDB Team @@ -429,7 +469,7 @@ 2008-04-29 The InnoDB Team - * handler/i_s.cc, include/srv0start.h, srv/srv0start.c: + * handler/i_s.cc, include/srv0start.h, srv/srv0start.c: Fix Bug#36310 InnoDB plugin crash 2008-04-23 The InnoDB Team diff --git a/dict/dict0dict.c b/dict/dict0dict.c index 23822d7f9f7..0f5eef60059 100644 --- a/dict/dict0dict.c +++ b/dict/dict0dict.c @@ -3648,25 +3648,6 @@ try_find_index: goto loop; } -/************************************************************************** -Determines whether a string starts with the specified keyword. */ -UNIV_INTERN -ibool -dict_str_starts_with_keyword( -/*=========================*/ - /* out: TRUE if str starts - with keyword */ - void* mysql_thd, /* in: MySQL thread handle */ - const char* str, /* in: string to scan for keyword */ - const char* keyword) /* in: keyword to look for */ -{ - struct charset_info_st* cs = innobase_get_charset(mysql_thd); - ibool success; - - dict_accept(cs, str, keyword, &success); - return(success); -} - /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after diff --git a/dict/dict0mem.c b/dict/dict0mem.c index bf0e14304dd..15372d8e261 100644 --- a/dict/dict0mem.c +++ b/dict/dict0mem.c @@ -58,7 +58,7 @@ dict_mem_table_create( table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS) * sizeof(dict_col_t)); - table->auto_inc_lock = mem_heap_alloc(heap, lock_get_size()); + table->autoinc_lock = mem_heap_alloc(heap, lock_get_size()); mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); diff --git a/ha_innodb.def b/ha_innodb.def new file mode 100644 index 00000000000..e0faa62deb1 --- /dev/null +++ b/ha_innodb.def @@ -0,0 +1,4 @@ +EXPORTS + _mysql_plugin_interface_version_ + _mysql_sizeof_struct_st_plugin_ + _mysql_plugin_declarations_ diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index a05cfdee3a2..f680a41f1dd 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -69,6 +69,8 @@ extern "C" { #include "ha_innodb.h" #include "i_s.h" +#include "handler0vars.h" +#include "mysql_addons.h" #ifndef MYSQL_SERVER /* This is needed because of Bug #3596. Let us hope that pthread_mutex_t @@ -107,7 +109,11 @@ undefined. Map it to NULL. */ #ifdef MYSQL_DYNAMIC_PLUGIN /* These must be weak global variables in the dynamic plugin. */ struct handlerton* innodb_hton_ptr; +#ifdef __WIN__ +struct st_mysql_plugin* builtin_innobase_plugin_ptr; +#else int builtin_innobase_plugin; +#endif /* __WIN__ */ /******************************************************************** Copy InnoDB system variables from the static InnoDB to the dynamic plugin. */ @@ -163,7 +169,7 @@ static my_bool innobase_use_checksums = TRUE; static my_bool innobase_locks_unsafe_for_binlog = FALSE; static my_bool innobase_rollback_on_timeout = FALSE; static my_bool innobase_create_status_file = FALSE; -static my_bool innobase_stats_on_metadata = TRUE; +static my_bool innobase_stats_on_metadata = TRUE; static my_bool innobase_adaptive_hash_index = TRUE; static char* internal_innobase_data_file_path = NULL; @@ -520,7 +526,7 @@ thd_is_replication_slave_thread( /********************************************************************** Save some CPU by testing the value of srv_thread_concurrency in inline functions. */ -inline +static inline void innodb_srv_conc_enter_innodb( /*=========================*/ @@ -537,7 +543,7 @@ innodb_srv_conc_enter_innodb( /********************************************************************** Save some CPU by testing the value of srv_thread_concurrency in inline functions. */ -inline +static inline void innodb_srv_conc_exit_innodb( /*========================*/ @@ -556,7 +562,7 @@ Releases possible search latch and InnoDB thread FIFO ticket. These should be released at each SQL statement end, and also when mysqld passes the control to the client. It does no harm to release these also in the middle of an SQL statement. */ -inline +static inline void innobase_release_stat_resources( /*============================*/ @@ -630,7 +636,7 @@ thd_lock_wait_timeout( /************************************************************************ Obtain the InnoDB transaction of a MySQL thread. */ -inline +static inline trx_t*& thd_to_trx( /*=======*/ @@ -674,7 +680,7 @@ Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used when a single database operation may introduce a small need for server utility activity, like checkpointing. */ -inline +static inline void innobase_active_small(void) /*=======================*/ @@ -948,6 +954,99 @@ innobase_get_charset( return(thd_charset((THD*) mysql_thd)); } +#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) +/*********************************************************************** +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. */ +extern "C" UNIV_INTERN +int +innobase_mysql_tmpfile(void) +/*========================*/ + /* out: temporary file descriptor, or < 0 on error */ +{ + 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" UNIV_INTERN @@ -979,6 +1078,7 @@ innobase_mysql_tmpfile(void) } return(fd2); } +#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */ /************************************************************************* Wrapper around MySQL's copy_and_convert function, see it for @@ -1194,7 +1294,7 @@ ha_innobase::~ha_innobase() Updates the user_thd field in a handle and also allocates a new InnoDB transaction handle if needed, and updates the transaction fields in the prebuilt struct. */ -inline +UNIV_INTERN inline void ha_innobase::update_thd( /*====================*/ @@ -1231,7 +1331,7 @@ Registers that InnoDB takes part in an SQL statement, so that MySQL knows to roll back the statement if the statement results in an error. This MUST be called for every SQL statement that may be rolled back by MySQL. Calling this several times to register the same statement is allowed, too. */ -inline +static inline void innobase_register_stmt( /*===================*/ @@ -1250,7 +1350,7 @@ MUST be called for every transaction for which the user may call commit or rollback. Calling this several times to register the same transaction is allowed, too. This function also registers the current SQL statement. */ -inline +static inline void innobase_register_trx_and_stmt( /*===========================*/ @@ -1984,8 +2084,6 @@ innobase_init( srv_max_n_open_files = (ulint) innobase_open_files; srv_innodb_status = (ibool) innobase_create_status_file; - srv_stats_on_metadata = (ibool) innobase_stats_on_metadata; - btr_search_disabled = (ibool) !innobase_adaptive_hash_index; srv_print_verbose_log = mysqld_embedded ? 0 : 1; @@ -3038,7 +3136,7 @@ ha_innobase::close(void) /****************************************************************** Gets field offset for a field in a table. */ -inline +static inline uint get_field_offset( /*=============*/ @@ -3082,7 +3180,7 @@ field_in_record_is_null( /****************************************************************** Sets a field in a record to SQL NULL. Uses the record format information in table to track the null bit in record. */ -inline +static inline void set_field_in_record_to_null( /*========================*/ @@ -3291,7 +3389,7 @@ get_innobase_type_from_mysql_type( /*********************************************************************** Writes an unsigned integer value < 64k to 2 bytes, in the little-endian storage format. */ -inline +static inline void innobase_write_to_2_little_endian( /*==============================*/ @@ -3307,7 +3405,7 @@ innobase_write_to_2_little_endian( /*********************************************************************** Reads an unsigned integer value < 64k from 2 bytes, in the little-endian storage format. */ -inline +static inline uint innobase_read_from_2_little_endian( /*===============================*/ @@ -4637,7 +4735,7 @@ ha_innobase::index_end(void) /************************************************************************* Converts a search mode flag understood by MySQL to a flag understood by InnoDB. */ -inline +static inline ulint convert_search_mode_to_innobase( /*============================*/ @@ -5875,40 +5973,21 @@ ha_innobase::create( if (create_info->key_block_size || (create_info->used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE)) { - switch (create_info->key_block_size) { - case 1: - flags = 1 << DICT_TF_ZSSIZE_SHIFT - | DICT_TF_COMPACT - | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; - break; - case 2: - flags = 2 << DICT_TF_ZSSIZE_SHIFT - | DICT_TF_COMPACT - | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; - break; - case 4: - flags = 3 << DICT_TF_ZSSIZE_SHIFT - | DICT_TF_COMPACT - | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; - break; - case 8: - flags = 4 << DICT_TF_ZSSIZE_SHIFT - | DICT_TF_COMPACT - | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; - break; - case 16: - flags = 5 << DICT_TF_ZSSIZE_SHIFT - | DICT_TF_COMPACT - | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; - break; -#if DICT_TF_ZSSIZE_MAX != 5 -# error "DICT_TF_ZSSIZE_MAX != 5" -#endif + /* Determine the page_zip.ssize corresponding to the + requested page size (key_block_size) in kilobytes. */ + + ulint ssize, ksize; + ulint key_block_size = create_info->key_block_size; + + for (ssize = ksize = 1; ssize <= DICT_TF_ZSSIZE_MAX; + ssize++, ksize <<= 1) { + if (key_block_size == ksize) { + flags = ssize << DICT_TF_ZSSIZE_SHIFT + | DICT_TF_COMPACT + | DICT_TF_FORMAT_ZIP + << DICT_TF_FORMAT_SHIFT; + break; + } } if (!srv_file_per_table) { @@ -5960,12 +6039,16 @@ ha_innobase::create( /* No KEY_BLOCK_SIZE */ if (form->s->row_type == ROW_TYPE_COMPRESSED) { /* ROW_FORMAT=COMPRESSED without - KEY_BLOCK_SIZE implies - KEY_BLOCK_SIZE=8. */ - flags = 4 << DICT_TF_ZSSIZE_SHIFT + KEY_BLOCK_SIZE implies half the + maximum KEY_BLOCK_SIZE. */ + flags = (DICT_TF_ZSSIZE_MAX - 1) + << DICT_TF_ZSSIZE_SHIFT | DICT_TF_COMPACT | DICT_TF_FORMAT_ZIP - << DICT_TF_FORMAT_SHIFT; + << DICT_TF_FORMAT_SHIFT; +#if DICT_TF_ZSSIZE_MAX < 1 +# error "DICT_TF_ZSSIZE_MAX < 1" +#endif } } @@ -6777,7 +6860,7 @@ ha_innobase::info( ib_table = prebuilt->table; if (flag & HA_STATUS_TIME) { - if (srv_stats_on_metadata) { + if (innobase_stats_on_metadata) { /* In sql_show we call with this flag: update then statistics so that they are up-to-date */ @@ -7553,7 +7636,7 @@ ha_innobase::start_stmt( /********************************************************************** Maps a MySQL trx isolation level code to the InnoDB isolation level code */ -inline +static inline ulint innobase_map_isolation_level( /*=========================*/ @@ -7596,12 +7679,12 @@ ha_innobase::external_lock( READ UNCOMMITTED and READ COMMITTED since the necessary locks cannot be taken. In this case, we print an informative error message and return with an error. */ - if (lock_type == F_WRLCK) + if (lock_type == F_WRLCK && ib_bin_log_is_engaged(thd)) { ulong const binlog_format= thd_binlog_format(thd); ulong const tx_isolation = thd_tx_isolation(ha_thd()); - if (tx_isolation <= ISO_READ_COMMITTED && - binlog_format == BINLOG_FORMAT_STMT) + if (tx_isolation <= ISO_READ_COMMITTED + && binlog_format == BINLOG_FORMAT_STMT) { char buf[256]; my_snprintf(buf, sizeof(buf), @@ -9343,7 +9426,7 @@ static MYSQL_SYSVAR_BOOL(status_file, innobase_create_status_file, NULL, NULL, FALSE); static MYSQL_SYSVAR_BOOL(stats_on_metadata, innobase_stats_on_metadata, - PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_NOSYSVAR, + PLUGIN_VAR_OPCMDARG, "Enable statistics gathering for metadata commands such as SHOW TABLE STATUS (on by default)", NULL, NULL, TRUE); @@ -9568,6 +9651,20 @@ innodb_plugin_init(void) #error "MYSQL_STORAGE_ENGINE_PLUGIN must be nonzero." #endif + /* Copy the system variables. */ + + struct st_mysql_plugin* builtin; + struct st_mysql_sys_var** sta; /* static parameters */ + struct st_mysql_sys_var** dyn; /* dynamic parameters */ + +#ifdef __WIN__ + if (!builtin_innobase_plugin_ptr) { + + return(true); + } + + builtin = builtin_innobase_plugin_ptr; +#else switch (builtin_innobase_plugin) { case 0: return(true); @@ -9577,34 +9674,34 @@ innodb_plugin_init(void) return(false); } - /* Copy the system variables. */ - - struct st_mysql_plugin* builtin; - struct st_mysql_sys_var** sta; /* static parameters */ - struct st_mysql_sys_var** dyn; /* dynamic parameters */ - builtin = (struct st_mysql_plugin*) &builtin_innobase_plugin; +#endif for (sta = builtin->system_vars; *sta != NULL; sta++) { - /* do not copy session variables */ - if ((*sta)->flags & PLUGIN_VAR_THDLOCAL) { - continue; - } - for (dyn = innobase_system_variables; *dyn != NULL; dyn++) { + /* do not copy session variables */ + if (((*sta)->flags | (*dyn)->flags) + & PLUGIN_VAR_THDLOCAL) { + continue; + } + if (innobase_match_parameter((*sta)->name, (*dyn)->name)) { /* found the corresponding parameter */ /* check if the flags are the same, - ignoring differences in the READONLY flag; + ignoring differences in the READONLY or + NOSYSVAR flags; e.g. we are not copying string variable to - an integer one */ - if (((*sta)->flags & ~PLUGIN_VAR_READONLY) - != ((*dyn)->flags & ~PLUGIN_VAR_READONLY)) { + an integer one, but we do not care if it is + readonly in the static and not in the + dynamic */ + if (((*sta)->flags ^ (*dyn)->flags) + & ~(PLUGIN_VAR_READONLY + | PLUGIN_VAR_NOSYSVAR)) { fprintf(stderr, "InnoDB: %s in static InnoDB " diff --git a/handler/handler0alter.cc b/handler/handler0alter.cc index 5d20e068702..4ffacb8d5e8 100644 --- a/handler/handler0alter.cc +++ b/handler/handler0alter.cc @@ -18,6 +18,7 @@ extern "C" { } #include "ha_innodb.h" +#include "handler0vars.h" /***************************************************************** Copies an InnoDB column to a MySQL field. This function is diff --git a/handler/handler0vars.h b/handler/handler0vars.h new file mode 100644 index 00000000000..2e34d6ba85e --- /dev/null +++ b/handler/handler0vars.h @@ -0,0 +1,51 @@ +/*********************************************************************** +This file contains accessor functions for dynamic plugin on Windows. + +(c) 2008 Innobase Oy +***********************************************************************/ +#if defined __WIN__ && defined MYSQL_DYNAMIC_PLUGIN +/*********************************************************************** +This is a list of externals that can not be resolved by delay loading. +They have to be resolved indirectly via their addresses in the .map file. +All of them are external variables. */ +extern CHARSET_INFO* wdl_my_charset_bin; +extern CHARSET_INFO* wdl_my_charset_latin1; +extern CHARSET_INFO* wdl_my_charset_filename; +extern CHARSET_INFO** wdl_system_charset_info; +extern CHARSET_INFO** wdl_default_charset_info; +extern CHARSET_INFO** wdl_all_charsets; +extern system_variables* wdl_global_system_variables; +extern char* wdl_mysql_real_data_home; +extern char** wdl_mysql_data_home; +extern char** wdl_tx_isolation_names; +extern char** wdl_binlog_format_names; +extern char* wdl_reg_ext; +extern pthread_mutex_t* wdl_LOCK_thread_count; +extern key_map* wdl_key_map_full; +extern MY_TMPDIR* wdl_mysql_tmpdir_list; +extern bool* wdl_mysqld_embedded; +extern uint* wdl_lower_case_table_names; +extern ulong* wdl_specialflag; +extern int* wdl_my_umask; + +#define my_charset_bin (*wdl_my_charset_bin) +#define my_charset_latin1 (*wdl_my_charset_latin1) +#define my_charset_filename (*wdl_my_charset_filename) +#define system_charset_info (*wdl_system_charset_info) +#define default_charset_info (*wdl_default_charset_info) +#define all_charsets (wdl_all_charsets) +#define global_system_variables (*wdl_global_system_variables) +#define mysql_real_data_home (wdl_mysql_real_data_home) +#define mysql_data_home (*wdl_mysql_data_home) +#define tx_isolation_names (wdl_tx_isolation_names) +#define binlog_format_names (wdl_binlog_format_names) +#define reg_ext (wdl_reg_ext) +#define LOCK_thread_count (*wdl_LOCK_thread_count) +#define key_map_full (*wdl_key_map_full) +#define mysql_tmpdir_list (*wdl_mysql_tmpdir_list) +#define mysqld_embedded (*wdl_mysqld_embedded) +#define lower_case_table_names (*wdl_lower_case_table_names) +#define specialflag (*wdl_specialflag) +#define my_umask (*wdl_my_umask) + +#endif diff --git a/handler/i_s.cc b/handler/i_s.cc index 081abce8198..478a564b01e 100644 --- a/handler/i_s.cc +++ b/handler/i_s.cc @@ -25,6 +25,7 @@ extern "C" { #include "ha_prototypes.h" /* for innobase_convert_name() */ #include "srv0start.h" /* for srv_was_started */ } +#include "handler0vars.h" static const char plugin_author[] = "Innobase Oy"; diff --git a/handler/mysql_addons.cc b/handler/mysql_addons.cc index 66dc2675973..6dfdf6ced76 100644 --- a/handler/mysql_addons.cc +++ b/handler/mysql_addons.cc @@ -36,3 +36,16 @@ ib_thd_get_thread_id( { return((unsigned long) ((THD*) thd)->thread_id); } + +/* http://bugs.mysql.com/40360 */ +/* http://lists.mysql.com/commits/57450 */ +/** + See if the binary log is engaged for a thread, i.e., open and + LOG_BIN is set. + + @return @c true if the binlog is active, @c false otherwise. +*/ +my_bool ib_bin_log_is_engaged(const MYSQL_THD thd) +{ + return mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG); +} diff --git a/handler/win_delay_loader.cc b/handler/win_delay_loader.cc new file mode 100644 index 00000000000..7cee5cf3f36 --- /dev/null +++ b/handler/win_delay_loader.cc @@ -0,0 +1,1012 @@ +/*********************************************************************** +This file contains functions that implement the delay loader on Windows. + +This is a customized version of delay loader with limited functionalities. +It does not support: + +* (manual) unloading +* multiple delay loaded DLLs +* multiple loading of the same DLL + +This delay loader is used only by the InnoDB plugin. Other components (DLLs) +can still use the default delay loader, provided by MSVC. + +Several acronyms used by Microsoft: + * IAT: import address table + * INT: import name table + * RVA: Relative Virtual Address + +See http://msdn.microsoft.com/en-us/magazine/bb985992.aspx for details of +PE format. + +(c) 2008 Innobase Oy +***********************************************************************/ +#if defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) +# define WIN32_LEAN_AND_MEAN +# include +# include +# include + +extern "C" { +# include "univ.i" +# include "hash0hash.h" +} + +/*********************************************************************** +This following contains a list of externals that can not be resolved by +delay loading. They have to be resolved indirectly via their addresses +in the .map file. All of them are external variables. */ +CHARSET_INFO* wdl_my_charset_bin; +CHARSET_INFO* wdl_my_charset_latin1; +CHARSET_INFO* wdl_my_charset_filename; +CHARSET_INFO** wdl_system_charset_info; +CHARSET_INFO** wdl_default_charset_info; +CHARSET_INFO** wdl_all_charsets; +system_variables* wdl_global_system_variables; +char* wdl_mysql_real_data_home; +char** wdl_mysql_data_home; +char** wdl_tx_isolation_names; +char** wdl_binlog_format_names; +char* wdl_reg_ext; +pthread_mutex_t* wdl_LOCK_thread_count; +key_map* wdl_key_map_full; +MY_TMPDIR* wdl_mysql_tmpdir_list; +bool* wdl_mysqld_embedded; +uint* wdl_lower_case_table_names; +ulong* wdl_specialflag; +int* wdl_my_umask; + +/*********************************************************************** +The following is defined in ha_innodb.cc. It is used for copying the +system variables from the builtin innodb plugin to the dynamic plugin. +*/ +extern struct st_mysql_plugin* builtin_innobase_plugin_ptr; + +/*********************************************************************** +The preffered load-address defined in PE (portable executable format).*/ +#if defined(_M_IA64) +#pragma section(".base", long, read) +extern "C" +__declspec(allocate(".base")) +const IMAGE_DOS_HEADER __ImageBase; +#else +extern "C" +const IMAGE_DOS_HEADER __ImageBase; +#endif + +/*********************************************************************** +A template function for converting a relative address (RVA) to an +absolute address (VA). This is due to the pointers in the delay +descriptor (ImgDelayDescr in delayimp.h) have been changed from +VAs to RVAs to work on both 32- and 64-bit platforms. */ +template +X PFromRva(RVA rva) { + return X(PBYTE(&__ImageBase) + rva); +} + +/*********************************************************************** +Convert to the old format for convenience. The structure as well as its +element names follow the definition of ImgDelayDescr in delayimp.h. */ +struct InternalImgDelayDescr { + DWORD grAttrs; /* attributes */ + LPCSTR szName; /* pointer to dll name */ + HMODULE* phmod; /* address of module handle */ + PImgThunkData pIAT; /* address of the IAT */ + PCImgThunkData pINT; /* address of the INT */ + PCImgThunkData pBoundIAT; /* address of the optional bound IAT */ + PCImgThunkData pUnloadIAT; /* address of optional copy of + original IAT */ + DWORD dwTimeStamp; /* 0 if not bound, + otherwise date/time stamp of DLL + bound to (Old BIND) */ +}; + +typedef struct map_hash_chain_struct map_hash_chain_t; + +struct map_hash_chain_struct { + char* symbol; /* pointer to a symbol */ + ulint value; /* address of the symbol */ + map_hash_chain_t* next; /* pointer to the next cell + in the same folder. */ + map_hash_chain_t* chain; /* a linear chain used for + cleanup. */ +}; + +static HMODULE my_hmod = 0; +static struct hash_table_struct* m_htbl = NULL ; +static map_hash_chain_t* chain_header = NULL; +static ibool wdl_init = FALSE; +const ulint MAP_HASH_CELLS_NUM = 10000; + +#ifndef DBUG_OFF +/*********************************************************************** +In the dynamic plugin, it is required to call the following dbug functions +in the server: + _db_pargs_ + _db_doprnt_ + _db_enter_ + _db_return_ + _db_dump_ + +The plugin will get those function pointers during the initialization. +*/ +typedef void (__cdecl* pfn_db_enter_)( + const char* _func_, + const char* _file_, + uint _line_, + const char** _sfunc_, + const char** _sfile_, + uint* _slevel_, + char***); + +typedef void (__cdecl* pfn_db_return_)( + uint _line_, + const char** _sfunc_, + const char** _sfile_, + uint* _slevel_); + +typedef void (__cdecl* pfn_db_pargs_)( + uint _line_, + const char* keyword); + +typedef void (__cdecl* pfn_db_doprnt_)( + const char* format, + ...); + +typedef void (__cdecl* pfn_db_dump_)( + uint _line_, + const char* keyword, + const unsigned char* memory, + size_t length); + +static pfn_db_enter_ wdl_db_enter_; +static pfn_db_return_ wdl_db_return_; +static pfn_db_pargs_ wdl_db_pargs_; +static pfn_db_doprnt_ wdl_db_doprnt_; +static pfn_db_dump_ wdl_db_dump_; +#endif /* !DBUG_OFF */ + +/***************************************************************** +Creates a hash table with >= n array cells. The actual number of cells is +chosen to be a prime number slightly bigger than n. + +This is the same function as hash_create in hash0hash.c, except the +memory allocation. This function is invoked before the engine is +initialized, and buffer pools are not ready yet. */ +static +hash_table_t* +wdl_hash_create( +/*============*/ + /* out, own: created hash table */ + ulint n) /* in: number of array cells */ +{ + hash_cell_t* array; + ulint prime; + hash_table_t* table; + + prime = ut_find_prime(n); + + table = (hash_table_t*) malloc(sizeof(hash_table_t)); + if (table == NULL) { + return(NULL); + } + + array = (hash_cell_t*) malloc(sizeof(hash_cell_t) * prime); + if (array == NULL) { + free(table); + return(NULL); + } + + table->array = array; + table->n_cells = prime; + table->n_mutexes = 0; + table->mutexes = NULL; + table->heaps = NULL; + table->heap = NULL; + table->magic_n = HASH_TABLE_MAGIC_N; + + /* Initialize the cell array */ + hash_table_clear(table); + + return(table); +} + +/***************************************************************** +Frees a hash table. */ +static +void +wdl_hash_table_free( +/*================*/ + hash_table_t* table) /* in, own: hash table */ +{ + ut_a(table != NULL); + ut_a(table->mutexes == NULL); + + free(table->array); + free(table); +} + +/*********************************************************************** +Function for calculating the count of imports given the base of the IAT. */ +static +ulint +wdl_import_count( +/*=============*/ + /* out: number of imports */ + PCImgThunkData pitd_base) /* in: base of the IAT */ +{ + ulint ret = 0; + PCImgThunkData pitd = pitd_base; + + while (pitd->u1.Function) { + pitd++; + ret++; + } + + return(ret); +} + +/*********************************************************************** +Read Mapfile to a hashtable for faster access */ +static +ibool +wdl_load_mapfile( +/*=============*/ + /* out: TRUE if the mapfile is + loaded successfully. */ + const char* filename) /* in: name of the mapfile. */ +{ + FILE* fp; + const size_t nSize = 256; + char tmp_buf[nSize]; + char* func_name; + char* func_addr; + ulint load_addr = 0; + ibool valid_load_addr = FALSE; + + fp = fopen(filename, "r"); + if (fp == NULL) { + + return(FALSE); + } + + /* Check whether to create the hashtable */ + if (m_htbl == NULL) { + + m_htbl = wdl_hash_create(MAP_HASH_CELLS_NUM); + + if (m_htbl == NULL) { + + fclose(fp); + return(FALSE); + } + } + + /* Search start of symbol list and get the preferred load address */ + while (fgets(tmp_buf, sizeof(tmp_buf), fp)) { + + if (sscanf(tmp_buf, " Preferred load address is %16X", + &load_addr) == 1) { + + valid_load_addr = TRUE; + } + + if (strstr(tmp_buf, "Rva+Base") != NULL) { + + break; + } + } + + if (valid_load_addr == FALSE) { + + /* No "Preferred load address", the map file is wrong. */ + fclose(fp); + return(FALSE); + } + + /* Read symbol list */ + while (fgets(tmp_buf, sizeof(tmp_buf), fp)) + { + map_hash_chain_t* map_cell; + ulint map_fold; + + if (*tmp_buf == 0) { + + continue; + } + + func_name = strtok(tmp_buf, " "); + func_name = strtok(NULL, " "); + func_addr = strtok(NULL, " "); + + if (func_name && func_addr) { + + ut_snprintf(tmp_buf, nSize, "0x%s", func_addr); + if (*func_name == '_') { + + func_name++; + } + + map_cell = (map_hash_chain_t*) + malloc(sizeof(map_hash_chain_t)); + if (map_cell == NULL) { + return(FALSE); + } + + /* Chain all cells together */ + map_cell->chain = chain_header; + chain_header = map_cell; + + map_cell->symbol = strdup(func_name); + map_cell->value = strtoul(tmp_buf, NULL, 0) + - load_addr; + map_fold = ut_fold_string(map_cell->symbol); + + HASH_INSERT(map_hash_chain_t, + next, + m_htbl, + map_fold, + map_cell); + } + } + + fclose(fp); + + return(TRUE); +} + +/***************************************************************** +Cleanup.during DLL unload */ +static +void +wdl_cleanup(void) +/*=============*/ +{ + while (chain_header != NULL) { + map_hash_chain_t* tmp; + + tmp = chain_header->chain; + free(chain_header->symbol); + free(chain_header); + chain_header = tmp; + } + + if (m_htbl != NULL) { + + wdl_hash_table_free(m_htbl); + } +} + +/*********************************************************************** +Load the mapfile mysqld.map. */ +static +HMODULE +wdl_get_mysqld_mapfile(void) +/*========================*/ + /* out: the module handle */ +{ + char file_name[MAX_PATH]; + char* ext; + ulint err; + + if (my_hmod == 0) { + + size_t nSize = MAX_PATH - strlen(".map") -1; + + /* First find out the name of current executable */ + my_hmod = GetModuleHandle(NULL); + if (my_hmod == 0) { + + return(my_hmod); + } + + err = GetModuleFileName(my_hmod, file_name, nSize); + if (err == 0) { + + my_hmod = 0; + return(my_hmod); + } + + ext = strrchr(file_name, '.'); + if (ext != NULL) { + + *ext = 0; + strcat(file_name, ".map"); + + err = wdl_load_mapfile(file_name); + if (err == 0) { + + my_hmod = 0; + } + } else { + + my_hmod = 0; + } + } + + return(my_hmod); +} + +/*********************************************************************** +Retrieves the address of an exported function. It follows the convention +of GetProcAddress(). */ +static +FARPROC +wdl_get_procaddr_from_map( +/*======================*/ + /* out: address of exported + function. */ + HANDLE m_handle, /* in: module handle */ + const char* import_proc) /* in: procedure name */ +{ + map_hash_chain_t* hash_chain; + ulint map_fold; + + map_fold = ut_fold_string(import_proc); + HASH_SEARCH( + next, + m_htbl, + map_fold, + map_hash_chain_t*, + hash_chain, + (ut_strcmp(hash_chain->symbol, import_proc) == 0)); + + if (hash_chain == NULL) { + +#ifdef _WIN64 + /* On Win64, the leading '_' may not be taken out. In this + case, search again without the leading '_'. */ + if (*import_proc == '_') { + + import_proc++; + } + + map_fold = ut_fold_string(import_proc); + HASH_SEARCH( + next, + m_htbl, + map_fold, + map_hash_chain_t*, + hash_chain, + (ut_strcmp(hash_chain->symbol, import_proc) == 0)); + + if (hash_chain == NULL) { +#endif + if (wdl_init == TRUE) { + + sql_print_error( + "InnoDB: the procedure pointer of %s" + " is not found.", + import_proc); + } + + return(0); +#ifdef _WIN64 + } +#endif + } + + return((FARPROC) ((ulint) m_handle + hash_chain->value)); +} + +/*********************************************************************** +Retrieves the address of an exported variable. +Note: It does not follow the Windows call convention FARPROC. */ +static +void* +wdl_get_varaddr_from_map( +/*=====================*/ + /* out: address of exported + variable. */ + HANDLE m_handle, /* in: module handle */ + const char* import_variable) /* in: variable name */ +{ + map_hash_chain_t* hash_chain; + ulint map_fold; + + map_fold = ut_fold_string(import_variable); + HASH_SEARCH( + next, + m_htbl, + map_fold, + map_hash_chain_t*, + hash_chain, + (ut_strcmp(hash_chain->symbol, import_variable) == 0)); + + if (hash_chain == NULL) { + +#ifdef _WIN64 + /* On Win64, the leading '_' may not be taken out. In this + case, search again without the leading '_'. */ + if (*import_variable == '_') { + + import_variable++; + } + + map_fold = ut_fold_string(import_variable); + HASH_SEARCH( + next, + m_htbl, + map_fold, + map_hash_chain_t*, + hash_chain, + (ut_strcmp(hash_chain->symbol, import_variable) == 0)); + + if (hash_chain == NULL) { +#endif + if (wdl_init == TRUE) { + + sql_print_error( + "InnoDB: the variable address of %s" + " is not found.", + import_variable); + } + + return(0); +#ifdef _WIN64 + } +#endif + } + + return((void*) ((ulint) m_handle + hash_chain->value)); +} + +/*********************************************************************** +Bind all unresolved external variables from the MySQL executable. */ +static +bool +wdl_get_external_variables(void) +/*============================*/ + /* out: TRUE if successful */ +{ + HMODULE hmod = wdl_get_mysqld_mapfile(); + + if (hmod == 0) { + + return(FALSE); + } + +#define GET_SYM(sym, var, type) \ + var = (type*) wdl_get_varaddr_from_map(hmod, sym); \ + if (var == NULL) return(FALSE) +#ifdef _WIN64 +#define GET_SYM2(sym1, sym2, var, type) \ + var = (type*) wdl_get_varaddr_from_map(hmod, sym1); \ + if (var == NULL) return(FALSE) +#else +#define GET_SYM2(sym1, sym2, var, type) \ + var = (type*) wdl_get_varaddr_from_map(hmod, sym2); \ + if (var == NULL) return(FALSE) +#endif // (_WIN64) +#define GET_C_SYM(sym, type) GET_SYM(#sym, wdl_##sym, type) +#define GET_PROC_ADDR(sym) \ + wdl##sym = (pfn##sym) wdl_get_procaddr_from_map(hmod, #sym) + + GET_C_SYM(my_charset_bin, CHARSET_INFO); + GET_C_SYM(my_charset_latin1, CHARSET_INFO); + GET_C_SYM(my_charset_filename, CHARSET_INFO); + GET_C_SYM(default_charset_info, CHARSET_INFO*); + GET_C_SYM(all_charsets, CHARSET_INFO*); + GET_C_SYM(my_umask, int); + + GET_SYM("?global_system_variables@@3Usystem_variables@@A", + wdl_global_system_variables, struct system_variables); + GET_SYM("?mysql_real_data_home@@3PADA", + wdl_mysql_real_data_home, char); + GET_SYM("?reg_ext@@3PADA", wdl_reg_ext, char); + GET_SYM("?LOCK_thread_count@@3U_RTL_CRITICAL_SECTION@@A", + wdl_LOCK_thread_count, pthread_mutex_t); + GET_SYM("?key_map_full@@3V?$Bitmap@$0EA@@@A", + wdl_key_map_full, key_map); + GET_SYM("?mysql_tmpdir_list@@3Ust_my_tmpdir@@A", + wdl_mysql_tmpdir_list, MY_TMPDIR); + GET_SYM("?mysqld_embedded@@3_NA", + wdl_mysqld_embedded, bool); + GET_SYM("?lower_case_table_names@@3IA", + wdl_lower_case_table_names, uint); + GET_SYM("?specialflag@@3KA", wdl_specialflag, ulong); + + GET_SYM2("?system_charset_info@@3PEAUcharset_info_st@@EA", + "?system_charset_info@@3PAUcharset_info_st@@A", + wdl_system_charset_info, CHARSET_INFO*); + GET_SYM2("?mysql_data_home@@3PEADEA", + "?mysql_data_home@@3PADA", + wdl_mysql_data_home, char*); + GET_SYM2("?tx_isolation_names@@3PAPEBDA", + "?tx_isolation_names@@3PAPBDA", + wdl_tx_isolation_names, char*); + GET_SYM2("?binlog_format_names@@3PAPEBDA", + "?binlog_format_names@@3PAPBDA", + wdl_binlog_format_names, char*); + + /* It is fine if builtin_innobase_plugin is not available. */ + builtin_innobase_plugin_ptr = (struct st_mysql_plugin*) + wdl_get_varaddr_from_map( + hmod, + "?builtin_innobase_plugin@@3PAUst_mysql_plugin@@A"); + +#ifndef DBUG_OFF + GET_PROC_ADDR(_db_enter_); + GET_PROC_ADDR(_db_return_); + GET_PROC_ADDR(_db_pargs_); + GET_PROC_ADDR(_db_doprnt_); + GET_PROC_ADDR(_db_dump_); + + /* If any of the dbug functions is not available, just make them + all invalid. This is the case when working with a non-debug + version of the server. */ + if (wdl_db_enter_ == NULL || wdl_db_return_ == NULL + || wdl_db_pargs_ == NULL || wdl_db_doprnt_ == NULL + || wdl_db_dump_ == NULL) { + + wdl_db_enter_ = NULL; + wdl_db_return_ = NULL; + wdl_db_pargs_ = NULL; + wdl_db_doprnt_ = NULL; + wdl_db_dump_ = NULL; + } +#endif /* !DBUG_OFF */ + + wdl_init = TRUE; + return(TRUE); + +#undef GET_SYM +#undef GET_SYM2 +#undef GET_C_SYM +#undef GET_PROC_ADDR +} + +/*********************************************************************** +The DLL Delayed Loading Helper Function for resolving externals. + +The function may fail due to one of the three reasons: + +* Invalid parameter, which happens if the attributes in pidd aren't + specified correctly. +* Failed to load the map file mysqld.map. +* Failed to find an external name in the map file mysqld.map. + +Note: this function is called by run-time as well as __HrLoadAllImportsForDll. +So, it has to follow Windows call convention. */ +extern "C" +FARPROC WINAPI +__delayLoadHelper2( +/*===============*/ + /* out: the address of the imported + function*/ + PCImgDelayDescr pidd, /* in: a const pointer to a + ImgDelayDescr, see delayimp.h. */ + FARPROC* iat_entry) /* in/out: A pointer to the slot in + the delay load import address table + to be updated with the address of the + imported function. */ +{ + ulint iIAT, iINT; + HMODULE hmod; + PCImgThunkData pitd; + FARPROC fun = NULL; + + /* Set up data used for the hook procs */ + InternalImgDelayDescr idd = { + pidd->grAttrs, + PFromRva(pidd->rvaDLLName), + PFromRva(pidd->rvaHmod), + PFromRva(pidd->rvaIAT), + PFromRva(pidd->rvaINT), + PFromRva(pidd->rvaBoundIAT), + PFromRva(pidd->rvaUnloadIAT), + pidd->dwTimeStamp + }; + + DelayLoadInfo dli = { + sizeof(DelayLoadInfo), + pidd, + iat_entry, + idd.szName, + {0}, + 0, + 0, + 0 + }; + + /* Check the Delay Load Attributes, log an error of invalid + parameter, which happens if the attributes in pidd are not + specified correctly. */ + if ((idd.grAttrs & dlattrRva) == 0) { + + sql_print_error("InnoDB: invalid parameter for delay loader."); + return(0); + } + + hmod = *idd.phmod; + + /* Calculate the index for the IAT entry in the import address table. + The INT entries are ordered the same as the IAT entries so the + calculation can be done on the IAT side. */ + iIAT = (PCImgThunkData) iat_entry - idd.pIAT; + iINT = iIAT; + + pitd = &(idd.pINT[iINT]); + + dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal); + + if (dli.dlp.fImportByName) { + + dli.dlp.szProcName = (LPCSTR) (PFromRva + ((RVA) ((UINT_PTR) pitd->u1.AddressOfData))->Name); + } else { + + dli.dlp.dwOrdinal = (ulint) IMAGE_ORDINAL(pitd->u1.Ordinal); + } + + /* Now, load the mapfile, if it has not been done yet */ + if (hmod == 0) { + + hmod = wdl_get_mysqld_mapfile(); + } + + if (hmod == 0) { + /* LoadLibrary failed. */ + PDelayLoadInfo rgpdli[1] = {&dli}; + + dli.dwLastError = ::GetLastError(); + + sql_print_error( + "InnoDB: failed to load mysqld.map with error %d.", + dli.dwLastError); + + return(0); + } + + /* Store the library handle. */ + idd.phmod = &hmod; + + /* Go for the procedure now. */ + dli.hmodCur = hmod; + + if (pidd->rvaBoundIAT && pidd->dwTimeStamp) { + + /* Bound imports exist, check the timestamp from the target + image */ + PIMAGE_NT_HEADERS pinh; + + pinh = (PIMAGE_NT_HEADERS) ((byte*) hmod + + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew); + + if (pinh->Signature == IMAGE_NT_SIGNATURE + && pinh->FileHeader.TimeDateStamp == idd.dwTimeStamp + && (DWORD) hmod == pinh->OptionalHeader.ImageBase) { + + /* We have a decent address in the bound IAT. */ + fun = (FARPROC) (UINT_PTR) + idd.pBoundIAT[iIAT].u1.Function; + + if (fun) { + + *iat_entry = fun; + return(fun); + } + } + } + + fun = wdl_get_procaddr_from_map(hmod, dli.dlp.szProcName); + + if (fun == 0) { + + return(0); + } + + *iat_entry = fun; + return(fun); +} + +/*********************************************************************** +Unload a DLL that was delay loaded. This function is called by run-time. */ +extern "C" +BOOL WINAPI +__FUnloadDelayLoadedDLL2( +/*=====================*/ + /* out: TRUE is returned if the DLL is found + and the IAT matches the original one. */ + LPCSTR module_name) /* in: DLL name */ +{ + return(TRUE); +} + +/****************************************************************** +Load all imports from a DLL that was specified with the /delayload linker +option. +Note: this function is called by run-time. So, it has to follow Windows call +convention. */ +extern "C" +HRESULT WINAPI +__HrLoadAllImportsForDll( +/*=====================*/ + /* out: S_OK if the DLL matches, otherwise + ERROR_MOD_NOT_FOUND is returned. */ + LPCSTR module_name) /* in: DLL name */ +{ + PIMAGE_NT_HEADERS img; + PCImgDelayDescr pidd; + IMAGE_DATA_DIRECTORY* image_data; + LPCSTR current_module; + HRESULT ret = ERROR_MOD_NOT_FOUND; + HMODULE hmod = (HMODULE) &__ImageBase; + + img = (PIMAGE_NT_HEADERS) ((byte*) hmod + + ((PIMAGE_DOS_HEADER) hmod)->e_lfanew); + image_data = + &img->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; + + /* Scan the delay load IAT/INT for the DLL */ + if (image_data->Size) { + + pidd = PFromRva(image_data->VirtualAddress); + + /* Check all of the listed DLLs we want to load. */ + while (pidd->rvaDLLName) { + + current_module = PFromRva(pidd->rvaDLLName); + + if (stricmp(module_name, current_module) == 0) { + + /* Found it, break out with pidd and + current_module set appropriately */ + break; + } + + /* To the next delay import descriptor */ + pidd++; + } + + if (pidd->rvaDLLName) { + + /* Found a matching DLL, now process it. */ + FARPROC* iat_entry; + size_t count; + + iat_entry = PFromRva(pidd->rvaIAT); + count = wdl_import_count((PCImgThunkData) iat_entry); + + /* now load all the imports from the DLL */ + while (count > 0) { + + /* No need to check the return value */ + __delayLoadHelper2(pidd, iat_entry); + iat_entry++; + count--; + } + + ret = S_OK; + } + } + + return ret; +} + +/****************************************************************** +The main function of a DLL */ +BOOL +WINAPI +DllMain( +/*====*/ + /* out: TRUE if the call succeeds */ + HINSTANCE hinstDLL, /* in: handle to the DLL module */ + DWORD fdwReason, /* Reason code that indicates why the + DLL entry-point function is being + called.*/ + LPVOID lpvReserved) /* in: additional parameter based on + fdwReason */ +{ + BOOL success = TRUE; + + switch (fdwReason) { + + case DLL_PROCESS_ATTACH: + success = wdl_get_external_variables(); + break; + + case DLL_PROCESS_DETACH: + wdl_cleanup(); + break; + } + + return(success); +} + +#ifndef DBUG_OFF +/****************************************************************** +Process entry point to user function. It makes the call to _db_enter_ +in mysqld.exe. The DBUG functions are defined in my_dbug.h. */ +extern "C" UNIV_INTERN +void +_db_enter_( + const char* _func_, /* in: current function name */ + const char* _file_, /* in: current file name */ + uint _line_, /* in: current source line number */ + const char** _sfunc_, /* out: previous _func_ */ + const char** _sfile_, /* out: previous _file_ */ + uint* _slevel_, /* out: previous nesting level */ + char*** _sframep_) /* out: previous frame pointer */ +{ + if (wdl_db_enter_ != NULL) { + + wdl_db_enter_(_func_, _file_, _line_, _sfunc_, _sfile_, + _slevel_, _sframep_); + } +} + +/****************************************************************** +Process exit from user function. It makes the call to _db_return_() +in the server. */ +extern "C" UNIV_INTERN +void +_db_return_( + uint _line_, /* in: current source line number */ + const char** _sfunc_, /* out: previous _func_ */ + const char** _sfile_, /* out: previous _file_ */ + uint* _slevel_) /* out: previous level */ +{ + if (wdl_db_return_ != NULL) { + + wdl_db_return_(_line_, _sfunc_, _sfile_, _slevel_); + } +} + +/****************************************************************** +Log arguments for subsequent use. It makes the call to _db_pargs_() +in the server. */ +extern "C" UNIV_INTERN +void +_db_pargs_( + uint _line_, /* in: current source line number */ + const char* keyword) /* in: keyword for current macro */ +{ + if (wdl_db_pargs_ != NULL) { + + wdl_db_pargs_(_line_, keyword); + } +} + +/****************************************************************** +Handle print of debug lines. It saves the text into a buffer first, +then makes the call to _db_doprnt_() in the server. The text is +truncated to the size of buffer. */ +extern "C" UNIV_INTERN +void +_db_doprnt_( + const char* format, /* in: the format string */ + ...) /* in: list of arguments */ +{ + va_list argp; + char buffer[512]; + + if (wdl_db_doprnt_ != NULL) { + + va_start(argp, format); + /* it is ok to ignore the trunction. */ + _vsnprintf(buffer, sizeof(buffer), format, argp); + wdl_db_doprnt_(buffer); + va_end(argp); + } +} + +/****************************************************************** +Dump a string in hex. It makes the call to _db_dump_() in the server. */ +extern "C" UNIV_INTERN +void +_db_dump_( + uint _line_, /* in: current source line + number */ + const char* keyword, /* in: keyword list */ + const unsigned char* memory, /* in: memory to dump */ + size_t length) /* in: bytes to dump */ +{ + if (wdl_db_dump_ != NULL) { + + wdl_db_dump_(_line_, keyword, memory, length); + } +} + +#endif /* !DBUG_OFF */ +#endif /* defined (__WIN__) && defined (MYSQL_DYNAMIC_PLUGIN) */ diff --git a/include/data0type.ic b/include/data0type.ic index 55036d4faf5..965b1c39373 100644 --- a/include/data0type.ic +++ b/include/data0type.ic @@ -567,5 +567,5 @@ dtype_get_sql_null_size( const dtype_t* type) /* in: type */ { return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminlen, type->mbmaxlen) > 0); + type->mbminlen, type->mbmaxlen)); } diff --git a/include/dict0dict.h b/include/dict0dict.h index 31482f92cd3..bb9f257583c 100644 --- a/include/dict0dict.h +++ b/include/dict0dict.h @@ -299,17 +299,6 @@ dict_table_replace_index_in_foreign_list( /*=====================================*/ dict_table_t* table, /* in/out: table */ dict_index_t* index); /* in: index to be replaced */ -/************************************************************************** -Determines whether a string starts with the specified keyword. */ -UNIV_INTERN -ibool -dict_str_starts_with_keyword( -/*=========================*/ - /* out: TRUE if str starts - with keyword */ - void* mysql_thd, /* in: MySQL thread handle */ - const char* str, /* in: string to scan for keyword */ - const char* keyword); /* in: keyword to look for */ /************************************************************************* Checks if a index is defined for a foreign key constraint. Index is a part of a foreign key constraint if the index is referenced by foreign key diff --git a/include/dict0mem.h b/include/dict0mem.h index 6c4c7c768ae..bfa0636aee5 100644 --- a/include/dict0mem.h +++ b/include/dict0mem.h @@ -24,6 +24,7 @@ Created 1/8/1996 Heikki Tuuri #include "lock0types.h" #include "hash0hash.h" #include "que0types.h" +#include "trx0types.h" /* Type flags of an index: OR'ing of the flags is allowed to define a combination of types */ @@ -381,13 +382,6 @@ struct dict_table_struct{ on the table: we cannot drop the table while there are foreign key checks running on it! */ - lock_t* auto_inc_lock;/* a buffer for an auto-inc lock - for this table: we allocate the memory here - so that individual transactions can get it - and release it without a need to allocate - space from the lock heap of the trx: - otherwise the lock heap would grow rapidly - if we do a large insert from a select */ dulint query_cache_inv_trx_id; /* transactions whose trx id < than this number are not allowed to store to the MySQL @@ -438,12 +432,33 @@ struct dict_table_struct{ any latch, because this is only used for heuristics */ /*----------------------*/ + /* The following fields are used by the + AUTOINC code. The actual collection of + tables locked during AUTOINC read/write is + kept in trx_t. In order to quickly determine + whether a transaction has locked the AUTOINC + lock we keep a pointer to the transaction + here in the autoinc_trx variable. This is to + avoid acquiring the kernel mutex and scanning + the vector in trx_t. + + When an AUTOINC lock has to wait, the + corresponding lock instance is created on + the trx lock heap rather than use the + pre-allocated instance in autoinc_lock below.*/ + lock_t* autoinc_lock; + /* a buffer for an AUTOINC lock + for this table: we allocate the memory here + so that individual transactions can get it + and release it without a need to allocate + space from the lock heap of the trx: + otherwise the lock heap would grow rapidly + if we do a large insert from a select */ mutex_t autoinc_mutex; /* mutex protecting the autoincrement counter */ ib_uint64_t autoinc;/* autoinc counter value to give to the next inserted row */ - /*----------------------*/ ulong n_waiting_or_granted_auto_inc_locks; /* This counter is used to track the number of granted and pending autoinc locks on this @@ -453,6 +468,9 @@ struct dict_table_struct{ acquired the AUTOINC lock or not. Of course only one transaction can be granted the lock but there can be multiple waiters. */ + const trx_t* autoinc_trx; + /* The transaction that currently holds the + the AUTOINC lock on this table. */ /*----------------------*/ #ifdef UNIV_DEBUG diff --git a/include/lock0lock.h b/include/lock0lock.h index 27c21ccd9cc..1c9ee9c5442 100644 --- a/include/lock0lock.h +++ b/include/lock0lock.h @@ -18,6 +18,7 @@ Created 5/7/1996 Heikki Tuuri #include "lock0types.h" #include "read0types.h" #include "hash0hash.h" +#include "ut0vec.h" #ifdef UNIV_DEBUG extern ibool lock_print_waits; @@ -490,14 +491,6 @@ lock_table_unlock( /*==============*/ lock_t* lock); /* in: lock */ /************************************************************************* -Releases an auto-inc lock a transaction possibly has on a table. -Releases possible other transactions waiting for this lock. */ -UNIV_INTERN -void -lock_table_unlock_auto_inc( -/*=======================*/ - trx_t* trx); /* in: transaction */ -/************************************************************************* Releases transaction locks, and releases possible other transactions waiting because of these locks. */ UNIV_INTERN @@ -653,6 +646,13 @@ ulint lock_number_of_rows_locked( /*=======================*/ trx_t* trx); /* in: transaction */ +/*********************************************************************** +Release all the transaction's autoinc locks. */ +UNIV_INTERN +void +lock_release_autoinc_locks( +/*=======================*/ + trx_t* trx); /* in/out: transaction */ /*********************************************************************** Gets the type of a lock. Non-inline version for using outside of the diff --git a/include/mysql_addons.h b/include/mysql_addons.h index 6d4bad0aebf..3c2933742c8 100644 --- a/include/mysql_addons.h +++ b/include/mysql_addons.h @@ -15,6 +15,9 @@ here. In a perfect world this file exists but is empty. Created November 07, 2007 Vasil Dimov *******************************************************/ +#include /* for my_bool */ +#include /* for MYSQL_THD */ + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -32,3 +35,13 @@ ib_thd_get_thread_id( #ifdef __cplusplus } #endif /* __cplusplus */ + +/* http://bugs.mysql.com/40360 */ +/* http://lists.mysql.com/commits/57450 */ +/** + See if the binary log is engaged for a thread, i.e., open and + LOG_BIN is set. + + @return @c true if the binlog is active, @c false otherwise. +*/ +my_bool ib_bin_log_is_engaged(const MYSQL_THD thd); diff --git a/include/row0mysql.h b/include/row0mysql.h index 579414715fe..696adfc8cbf 100644 --- a/include/row0mysql.h +++ b/include/row0mysql.h @@ -163,12 +163,12 @@ row_update_prebuilt_trx( handle */ trx_t* trx); /* in: transaction handle */ /************************************************************************* -Unlocks an AUTO_INC type lock possibly reserved by trx. */ +Unlocks AUTO_INC type locks that were possibly reserved by a trx. */ UNIV_INTERN void row_unlock_table_autoinc_for_mysql( /*===============================*/ - trx_t* trx); /* in: transaction */ + trx_t* trx); /* in/out: transaction */ /************************************************************************* Sets an AUTO_INC type lock on the table mentioned in prebuilt. The AUTO_INC lock gives exclusive access to the auto-inc counter of the diff --git a/include/srv0srv.h b/include/srv0srv.h index 4561b6d2f17..52be5357bbd 100644 --- a/include/srv0srv.h +++ b/include/srv0srv.h @@ -132,8 +132,6 @@ extern ulint srv_fast_shutdown; /* If this is 1, do not do a transactions). */ extern ibool srv_innodb_status; -extern ibool srv_stats_on_metadata; - extern unsigned long long srv_stats_sample_pages; extern ibool srv_use_doublewrite_buf; diff --git a/include/trx0trx.h b/include/trx0trx.h index e625f958a9c..f1bdd9cc979 100644 --- a/include/trx0trx.h +++ b/include/trx0trx.h @@ -18,6 +18,7 @@ Created 3/26/1996 Heikki Tuuri #include "read0types.h" #include "dict0types.h" #include "trx0xa.h" +#include "ut0vec.h" /* Dummy session used currently in MySQL interface */ extern sess_t* trx_dummy_sess; @@ -601,9 +602,6 @@ struct trx_struct{ to srv_conc_innodb_enter, if the value here is > 0, we decrement this by 1 */ /*------------------------------*/ - lock_t* auto_inc_lock; /* possible auto-inc lock reserved by - the transaction; note that it is also - in the lock list trx_locks */ dict_index_t* new_rec_locks[2];/* these are normally NULL; if srv_locks_unsafe_for_binlog is TRUE or session is using READ COMMITTED @@ -735,9 +733,15 @@ struct trx_struct{ trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log records which are currently processed by a rollback operation */ + /*------------------------------*/ ulint n_autoinc_rows; /* no. of AUTO-INC rows required for an SQL statement. This is useful for multi-row INSERTs */ + ib_vector_t* autoinc_locks; /* AUTOINC locks held by this + transaction. Note that these are + also in the lock list trx_locks. This + vector needs to be freed explicitly + when the trx_t instance is desrtoyed */ /*------------------------------*/ char detailed_error[256]; /* detailed error message for last error, or empty. */ diff --git a/include/univ.i b/include/univ.i index 0c67dc7632d..356b0f36a61 100644 --- a/include/univ.i +++ b/include/univ.i @@ -11,7 +11,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 1 #define INNODB_VERSION_MINOR 0 -#define INNODB_VERSION_BUGFIX 1 +#define INNODB_VERSION_BUGFIX 2 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; diff --git a/include/ut0rnd.ic b/include/ut0rnd.ic index d9fb34a1e13..1f82989d64e 100644 --- a/include/ut0rnd.ic +++ b/include/ut0rnd.ic @@ -175,20 +175,11 @@ ut_fold_string( /* out: folded value */ const char* str) /* in: null-terminated string */ { -#ifdef UNIV_DEBUG - ulint i = 0; -#endif ulint fold = 0; ut_ad(str); while (*str != '\0') { - -#ifdef UNIV_DEBUG - i++; - ut_a(i < 100); -#endif - fold = ut_fold_ulint_pair(fold, (ulint)(*str)); str++; } diff --git a/include/ut0vec.h b/include/ut0vec.h index 6a52c94a327..60b2b3bbc0e 100644 --- a/include/ut0vec.h +++ b/include/ut0vec.h @@ -46,7 +46,16 @@ ulint ib_vector_size( /*===========*/ /* out: number of elements in vector */ - ib_vector_t* vec); /* in: vector */ + const ib_vector_t* vec); /* in: vector */ + +/******************************************************************** +Test whether a vector is empty or not. */ +UNIV_INLINE +ibool +ib_vector_is_empty( +/*===============*/ + /* out: TRUE if empty */ + const ib_vector_t* vec); /* in: vector */ /******************************************************************** Get the n'th element. */ @@ -58,6 +67,23 @@ ib_vector_get( ib_vector_t* vec, /* in: vector */ ulint n); /* in: element index to get */ +/******************************************************************** +Remove the last element from the vector. */ +UNIV_INLINE +void* +ib_vector_pop( +/*==========*/ + ib_vector_t* vec); /* in: vector */ + +/******************************************************************** +Free the underlying heap of the vector. Note that vec is invalid +after this call. */ +UNIV_INLINE +void +ib_vector_free( +/*===========*/ + ib_vector_t* vec); /* in,own: vector */ + /* See comment at beginning of file. */ struct ib_vector_struct { mem_heap_t* heap; /* heap */ diff --git a/include/ut0vec.ic b/include/ut0vec.ic index 417a17d951f..f89b7826776 100644 --- a/include/ut0vec.ic +++ b/include/ut0vec.ic @@ -5,7 +5,7 @@ ulint ib_vector_size( /*===========*/ /* out: number of elements in vector */ - ib_vector_t* vec) /* in: vector */ + const ib_vector_t* vec) /* in: vector */ { return(vec->used); } @@ -24,3 +24,47 @@ ib_vector_get( return(vec->data[n]); } + +/******************************************************************** +Remove the last element from the vector. */ +UNIV_INLINE +void* +ib_vector_pop( +/*==========*/ + /* out: last vector element */ + ib_vector_t* vec) /* in/out: vector */ +{ + void* elem; + + ut_a(vec->used > 0); + --vec->used; + elem = vec->data[vec->used]; + + ut_d(vec->data[vec->used] = NULL); + UNIV_MEM_INVALID(&vec->data[vec->used], sizeof(*vec->data)); + + return(elem); +} + +/******************************************************************** +Free the underlying heap of the vector. Note that vec is invalid +after this call. */ +UNIV_INLINE +void +ib_vector_free( +/*===========*/ + ib_vector_t* vec) /* in, own: vector */ +{ + mem_heap_free(vec->heap); +} + +/******************************************************************** +Test whether a vector is empty or not. */ +UNIV_INLINE +ibool +ib_vector_is_empty( +/*===============*/ /* out: TRUE if empty else FALSE */ + const ib_vector_t* vec) /* in vector to test */ +{ + return(ib_vector_size(vec) == 0); +} diff --git a/lock/lock0lock.c b/lock/lock0lock.c index 9a307d9b7b4..26700635f93 100644 --- a/lock/lock0lock.c +++ b/lock/lock0lock.c @@ -2166,24 +2166,25 @@ static void lock_grant( /*=======*/ - lock_t* lock) /* in: waiting lock request */ + lock_t* lock) /* in/out: waiting lock request */ { ut_ad(mutex_own(&kernel_mutex)); lock_reset_lock_and_trx_wait(lock); if (lock_get_mode(lock) == LOCK_AUTO_INC) { + trx_t* trx = lock->trx; + dict_table_t* table = lock->un_member.tab_lock.table; - if (lock->trx->auto_inc_lock != NULL) { + if (table->autoinc_trx == trx) { fprintf(stderr, "InnoDB: Error: trx already had" " an AUTO-INC lock!\n"); - } - - /* Store pointer to lock to trx so that we know to - release it at the end of the SQL statement */ + } else { + table->autoinc_trx = trx; - lock->trx->auto_inc_lock = lock; + ib_vector_push(trx->autoinc_locks, lock); + } } #ifdef UNIV_DEBUG @@ -3531,15 +3532,16 @@ lock_table_create( ++table->n_waiting_or_granted_auto_inc_locks; } + /* For AUTOINC locking we reuse the lock instance only if + there is no wait involved else we allocate the waiting lock + from the transaction lock heap. */ if (type_mode == LOCK_AUTO_INC) { - /* Only one trx can have the lock on the table - at a time: we may use the memory preallocated - to the table object */ - lock = table->auto_inc_lock; + lock = table->autoinc_lock; + + table->autoinc_trx = trx; - ut_a(trx->auto_inc_lock == NULL); - trx->auto_inc_lock = lock; + ib_vector_push(trx->autoinc_locks, lock); } else { lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t)); } @@ -3571,16 +3573,39 @@ lock_table_remove_low( /*==================*/ lock_t* lock) /* in: table lock */ { - dict_table_t* table; trx_t* trx; + dict_table_t* table; ut_ad(mutex_own(&kernel_mutex)); - table = lock->un_member.tab_lock.table; trx = lock->trx; + table = lock->un_member.tab_lock.table; + + /* Remove the table from the transaction's AUTOINC vector, if + the lock that is being release is an AUTOINC lock. */ + if (lock_get_mode(lock) == LOCK_AUTO_INC) { + + /* The table's AUTOINC lock can get transferred to + another transaction before we get here. */ + if (table->autoinc_trx == trx) { + table->autoinc_trx = NULL; + } + + /* The locks must be freed in the reverse order from + the one in which they were acquired. This is to avoid + traversing the AUTOINC lock vector unnecessarily. + + We only store locks that were granted in the + trx->autoinc_locks vector (see lock_table_create() + and lock_grant()). Therefore it can be empty and we + need to check for that. */ - if (lock == trx->auto_inc_lock) { - trx->auto_inc_lock = NULL; + if (!ib_vector_is_empty(trx->autoinc_locks)) { + lock_t* autoinc_lock; + + autoinc_lock = ib_vector_pop(trx->autoinc_locks); + ut_a(autoinc_lock == lock); + } ut_a(table->n_waiting_or_granted_auto_inc_locks > 0); --table->n_waiting_or_granted_auto_inc_locks; @@ -3955,24 +3980,6 @@ lock_table_unlock( mutex_exit(&kernel_mutex); } -/************************************************************************* -Releases an auto-inc lock a transaction possibly has on a table. -Releases possible other transactions waiting for this lock. */ -UNIV_INTERN -void -lock_table_unlock_auto_inc( -/*=======================*/ - trx_t* trx) /* in: transaction */ -{ - if (trx->auto_inc_lock) { - mutex_enter(&kernel_mutex); - - lock_table_dequeue(trx->auto_inc_lock); - - mutex_exit(&kernel_mutex); - } -} - /************************************************************************* Releases transaction locks, and releases possible other transactions waiting because of these locks. */ @@ -4032,9 +4039,9 @@ lock_release_off_kernel( lock = UT_LIST_GET_LAST(trx->trx_locks); } - mem_heap_empty(trx->lock_heap); + ut_a(ib_vector_size(trx->autoinc_locks) == 0); - ut_a(trx->auto_inc_lock == NULL); + mem_heap_empty(trx->lock_heap); } /************************************************************************* @@ -4054,6 +4061,11 @@ lock_cancel_waiting_and_release( } else { ut_ad(lock_get_type_low(lock) & LOCK_TABLE); + if (lock->trx->autoinc_locks != NULL) { + /* Release the transaction's AUTOINC locks/ */ + lock_release_autoinc_locks(lock->trx); + } + lock_table_dequeue(lock); } @@ -5386,6 +5398,60 @@ lock_clust_rec_read_check_and_lock_alt( return(ret); } +/*********************************************************************** +Release the last lock from the transaction's autoinc locks. */ +UNIV_INLINE +void +lock_release_autoinc_last_lock( +/*===========================*/ + ib_vector_t* autoinc_locks) /* in/out: vector of AUTOINC locks */ +{ + ulint last; + lock_t* lock; + + ut_ad(mutex_own(&kernel_mutex)); + ut_a(!ib_vector_is_empty(autoinc_locks)); + + /* The lock to be release must be the last lock acquired. */ + last = ib_vector_size(autoinc_locks) - 1; + lock = ib_vector_get(autoinc_locks, last); + + /* Should have only AUTOINC locks in the vector. */ + ut_a(lock_get_mode(lock) == LOCK_AUTO_INC); + ut_a(lock_get_type(lock) == LOCK_TABLE); + + ut_a(lock->un_member.tab_lock.table != NULL); + + /* This will remove the lock from the trx autoinc_locks too. */ + lock_table_dequeue(lock); +} + +/*********************************************************************** +Release all the transaction's autoinc locks. */ +UNIV_INTERN +void +lock_release_autoinc_locks( +/*=======================*/ + trx_t* trx) /* in/out: transaction */ +{ + ut_ad(mutex_own(&kernel_mutex)); + + ut_a(trx->autoinc_locks != NULL); + + /* We release the locks in the reverse order. This is to + avoid searching the vector for the element to delete at + the lower level. See (lock_table_remove_low()) for details. */ + while (!ib_vector_is_empty(trx->autoinc_locks)) { + + /* lock_table_remove_low() will also remove the lock from + the transaction's autoinc_locks vector. */ + lock_release_autoinc_last_lock(trx->autoinc_locks); + } + + /* Should release all locks. */ + ut_a(ib_vector_is_empty(trx->autoinc_locks)); +} + /*********************************************************************** Gets the type of a lock. Non-inline version for using outside of the lock module. */ diff --git a/mysql-test/innodb-index.result b/mysql-test/innodb-index.result index 21e15705b33..a476d16a5f0 100644 --- a/mysql-test/innodb-index.result +++ b/mysql-test/innodb-index.result @@ -69,8 +69,6 @@ t1 CREATE TABLE `t1` ( 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 10 NULL 4 -drop index c on t1; -ERROR 42000: This table type requires a primary key alter table t1 add primary key (a), drop index c; show create table t1; Table Create Table diff --git a/mysql-test/innodb-index.test b/mysql-test/innodb-index.test index 07f709eee38..0ca02f0538a 100644 --- a/mysql-test/innodb-index.test +++ b/mysql-test/innodb-index.test @@ -30,8 +30,6 @@ 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; ---error ER_REQUIRES_PRIMARY_KEY -drop index c on t1; alter table t1 add primary key (a), drop index c; show create table t1; --error ER_MULTIPLE_PRI_KEY diff --git a/mysql-test/innodb_bug40360.result b/mysql-test/innodb_bug40360.result new file mode 100644 index 00000000000..ef4cf463903 --- /dev/null +++ b/mysql-test/innodb_bug40360.result @@ -0,0 +1,4 @@ +SET TX_ISOLATION='READ-COMMITTED'; +CREATE TABLE bug40360 (a INT) engine=innodb; +INSERT INTO bug40360 VALUES (1); +DROP TABLE bug40360; diff --git a/mysql-test/innodb_bug40360.test b/mysql-test/innodb_bug40360.test new file mode 100644 index 00000000000..e88837aab4f --- /dev/null +++ b/mysql-test/innodb_bug40360.test @@ -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; diff --git a/mysql-test/patches/innodb-index.diff b/mysql-test/patches/innodb-index.diff index 6cc8a989499..0b008c96f25 100644 --- a/mysql-test/patches/innodb-index.diff +++ b/mysql-test/patches/innodb-index.diff @@ -11,7 +11,7 @@ in the MySQL source repository. Index: storage/innobase/mysql-test/innodb-index.result =================================================================== ---- storage/innobase/mysql-test/innodb-index.result (revision 2229) +--- storage/innobase/mysql-test/innodb-index.result (revision 2870) +++ storage/innobase/mysql-test/innodb-index.result (working copy) @@ -43,19 +43,12 @@ t1 CREATE TABLE `t1` ( `b` int(11) DEFAULT NULL, @@ -35,7 +35,7 @@ Index: storage/innobase/mysql-test/innodb-index.result `b` int(11) DEFAULT NULL, Index: storage/innobase/mysql-test/innodb-index.test =================================================================== ---- storage/innobase/mysql-test/innodb-index.test (revision 2229) +--- storage/innobase/mysql-test/innodb-index.test (revision 2870) +++ storage/innobase/mysql-test/innodb-index.test (working copy) @@ -14,22 +14,12 @@ select * from t1 force index (d2) order --error ER_DUP_ENTRY @@ -57,6 +57,6 @@ Index: storage/innobase/mysql-test/innodb-index.test alter table t1 add unique index (c), add index (d); show create table t1; explain select * from t1 force index(c) order by c; - --error ER_REQUIRES_PRIMARY_KEY - drop index c on t1; alter table t1 add primary key (a), drop index c; + show create table t1; + --error ER_MULTIPLE_PRI_KEY diff --git a/row/row0mysql.c b/row/row0mysql.c index ef2d45a37d5..7db55634cfb 100644 --- a/row/row0mysql.c +++ b/row/row0mysql.c @@ -852,19 +852,18 @@ row_update_statistics_if_needed( } /************************************************************************* -Unlocks an AUTO_INC type lock possibly reserved by trx. */ +Unlocks AUTO_INC type locks that were possibly reserved by a trx. */ UNIV_INTERN void row_unlock_table_autoinc_for_mysql( /*===============================*/ - trx_t* trx) /* in: transaction */ + trx_t* trx) /* in/out: transaction */ { - if (!trx->auto_inc_lock) { + mutex_enter(&kernel_mutex); - return; - } + lock_release_autoinc_locks(trx); - lock_table_unlock_auto_inc(trx); + mutex_exit(&kernel_mutex); } /************************************************************************* @@ -881,16 +880,20 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL table handle */ { - trx_t* trx = prebuilt->trx; - ins_node_t* node = prebuilt->ins_node; - que_thr_t* thr; - ulint err; - ibool was_lock_wait; + trx_t* trx = prebuilt->trx; + ins_node_t* node = prebuilt->ins_node; + const dict_table_t* table = prebuilt->table; + que_thr_t* thr; + ulint err; + ibool was_lock_wait; ut_ad(trx); ut_ad(trx->mysql_thread_id == os_thread_get_curr_id()); - if (trx->auto_inc_lock) { + /* If we already hold an AUTOINC lock on the table then do nothing. + Note: We peek at the value of the current owner without acquiring + the kernel mutex. **/ + if (trx == table->autoinc_trx) { return(DB_SUCCESS); } diff --git a/scripts/install_innodb_plugins_win.sql b/scripts/install_innodb_plugins_win.sql new file mode 100644 index 00000000000..8c94b4e240d --- /dev/null +++ b/scripts/install_innodb_plugins_win.sql @@ -0,0 +1,9 @@ +-- execute these to install InnoDB if it is built as a dynamic plugin +INSTALL PLUGIN innodb SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_trx SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_locks SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_lock_waits SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_cmp SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_cmp_reset SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_cmpmem SONAME 'ha_innodb.dll'; +INSTALL PLUGIN innodb_cmpmem_reset SONAME 'ha_innodb.dll'; diff --git a/srv/srv0srv.c b/srv/srv0srv.c index a621959d1fc..1138d1c4490 100644 --- a/srv/srv0srv.c +++ b/srv/srv0srv.c @@ -299,8 +299,6 @@ UNIV_INTERN ulint srv_fast_shutdown = 0; /* Generate a innodb_status. file */ UNIV_INTERN ibool srv_innodb_status = FALSE; -UNIV_INTERN ibool srv_stats_on_metadata = TRUE; - /* When estimating number of different key values in an index, sample this many index pages */ UNIV_INTERN unsigned long long srv_stats_sample_pages = 8; diff --git a/trx/trx0trx.c b/trx/trx0trx.c index 82e41a37f05..108108d7128 100644 --- a/trx/trx0trx.c +++ b/trx/trx0trx.c @@ -169,8 +169,6 @@ trx_create( trx->declared_to_be_inside_innodb = FALSE; trx->n_tickets_to_enter_innodb = 0; - trx->auto_inc_lock = NULL; - trx->global_read_view_heap = mem_heap_create(256); trx->global_read_view = NULL; trx->read_view = NULL; @@ -181,6 +179,10 @@ trx_create( trx->n_autoinc_rows = 0; + /* Remember to free the vector explicitly. */ + trx->autoinc_locks = ib_vector_create( + mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4); + trx_reset_new_rec_lock_info(trx); return(trx); @@ -305,7 +307,6 @@ trx_free( ut_a(UT_LIST_GET_LEN(trx->wait_thrs) == 0); ut_a(!trx->has_search_latch); - ut_a(!trx->auto_inc_lock); ut_a(trx->dict_operation_lock_mode == 0); @@ -323,6 +324,10 @@ trx_free( ut_a(trx->read_view == NULL); + ut_a(ib_vector_is_empty(trx->autoinc_locks)); + /* We allocated a dedicated heap for the vector. */ + ib_vector_free(trx->autoinc_locks); + mem_free(trx); } diff --git a/win-plugin/README b/win-plugin/README new file mode 100644 index 00000000000..9182f2c555c --- /dev/null +++ b/win-plugin/README @@ -0,0 +1,25 @@ +This directory contains patches that need to be applied to the MySQL +source tree in order to build the dynamic plugin on Windows -- +HA_INNODB.DLL. Please note the followings when adding the patches: + +* The patch must be applied from the mysql top-level source directory. + patch -p0 < win-plugin.diff +* The patch filenames end in ".diff". +* All patches here are expected to apply cleanly to the latest MySQL 5.1 + tree when storage/innobase is replaced with this InnoDB branch. + +When applying the patch, the following files will be modified: + + * CMakeLists.txt + * sql/CMakeLists.txt + * win/configure.js + * win/build-vs71.bat + * win/build-vs8.bat + * win/build-vs8_x64.bat + +Also, two new files will be added: + + * sql/mysqld.def + * sql/mysqld_x64.def + +You can get "patch" utility for Windows from http://unxutils.sourceforge.net/ diff --git a/win-plugin/win-plugin.diff b/win-plugin/win-plugin.diff new file mode 100644 index 00000000000..760b184a8fe --- /dev/null +++ b/win-plugin/win-plugin.diff @@ -0,0 +1,310 @@ +diff -Nur CMakeLists.txt.orig CMakeLists.txt +--- CMakeLists.txt.orig 2008-10-03 12:25:41 -05:00 ++++ CMakeLists.txt 2008-09-26 17:32:51 -05:00 +@@ -97,6 +97,10 @@ + IF(CYBOZU) + ADD_DEFINITIONS(-DCYBOZU) + ENDIF(CYBOZU) ++# Checks for 32-bit version. And always use 32-bit time_t for compatibility ++IF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 4) ++ ADD_DEFINITIONS(-D_USE_32BIT_TIME_T) ++ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio" AND CMAKE_SIZEOF_VOID_P MATCHES 4) + + # in some places we use DBUG_OFF + SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF") +@@ -246,9 +250,9 @@ + IF(WITH_FEDERATED_STORAGE_ENGINE) + ADD_SUBDIRECTORY(storage/federated) + ENDIF(WITH_FEDERATED_STORAGE_ENGINE) +-IF(WITH_INNOBASE_STORAGE_ENGINE) ++IF(WITH_INNOBASE_STORAGE_ENGINE OR INNODB_DYNAMIC_PLUGIN) + ADD_SUBDIRECTORY(storage/innobase) +-ENDIF(WITH_INNOBASE_STORAGE_ENGINE) ++ENDIF(WITH_INNOBASE_STORAGE_ENGINE OR INNODB_DYNAMIC_PLUGIN) + ADD_SUBDIRECTORY(sql) + ADD_SUBDIRECTORY(server-tools/instance-manager) + ADD_SUBDIRECTORY(libmysql) + +diff -Nur sql/CMakeLists.txt.orig sql/CMakeLists.txt +--- sql/CMakeLists.txt.orig 2008-10-03 12:25:41 -05:00 ++++ sql/CMakeLists.txt 2008-09-24 03:58:19 -05:00 +@@ -100,6 +100,15 @@ + LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb") + ENDIF(cmake_version EQUAL 20406) + ++# Checks for 64-bit version ++IF(CMAKE_SIZEOF_VOID_P MATCHES 8) ++SET_TARGET_PROPERTIES(mysqld PROPERTIES ++ LINK_FLAGS "/def:\"${PROJECT_SOURCE_DIR}/sql/mysqld_x64.def\"") ++ELSE(CMAKE_SIZEOF_VOID_P MATCHES 8) ++SET_TARGET_PROPERTIES(mysqld PROPERTIES ++ LINK_FLAGS "/def:\"${PROJECT_SOURCE_DIR}/sql/mysqld.def\"") ++ENDIF(CMAKE_SIZEOF_VOID_P MATCHES 8) ++ + IF(EMBED_MANIFESTS) + MYSQL_EMBED_MANIFEST("mysqld" "asInvoker") + ENDIF(EMBED_MANIFESTS) + +diff -Nur sql/mysqld.def.orig sql/mysqld.def +--- sql/mysqld.def.orig 1969-12-31 18:00:00 -06:00 ++++ sql/mysqld.def 2008-10-31 02:20:32 -05:00 +@@ -0,0 +1,99 @@ ++EXPORTS ++ ?use_hidden_primary_key@handler@@UAEXXZ ++ ?get_dynamic_partition_info@handler@@UAEXPAUPARTITION_INFO@@I@Z ++ ?read_first_row@handler@@UAEHPAEI@Z ++ ?read_range_next@handler@@UAEHXZ ++ ?read_range_first@handler@@UAEHPBUst_key_range@@0_N1@Z ++ ?read_multi_range_first@handler@@UAEHPAPAUst_key_multi_range@@PAU2@I_NPAUst_handler_buffer@@@Z ++ ?read_multi_range_next@handler@@UAEHPAPAUst_key_multi_range@@@Z ++ ?index_read_idx_map@handler@@UAEHPAEIPBEKW4ha_rkey_function@@@Z ++ ?print_error@handler@@UAEXHH@Z ++ ?clone@handler@@UAEPAV1@PAUst_mem_root@@@Z ++ ?get_auto_increment@handler@@UAEX_K00PA_K1@Z ++ ?index_next_same@handler@@UAEHPAEPBEI@Z ++ ?get_error_message@handler@@UAE_NHPAVString@@@Z ++ ?ha_thd@handler@@IBEPAVTHD@@XZ ++ ?update_auto_increment@handler@@QAEHXZ ++ ?ha_statistic_increment@handler@@IBEXPQsystem_status_var@@K@Z ++ ?trans_register_ha@@YAXPAVTHD@@_NPAUhandlerton@@@Z ++ ?cmp@Field_blob@@QAEHPBEI0I@Z ++ ?set_time@Field_timestamp@@QAEXXZ ++ ?sql_print_error@@YAXPBDZZ ++ ?sql_print_warning@@YAXPBDZZ ++ ?check_global_access@@YA_NPAVTHD@@K@Z ++ ?schema_table_store_record@@YA_NPAVTHD@@PAUst_table@@@Z ++ ?get_quote_char_for_identifier@@YAHPAVTHD@@PBDI@Z ++ ?copy@String@@QAE_NXZ ++ ?copy@String@@QAE_NABV1@@Z ++ ?copy@String@@QAE_NPBDIPAUcharset_info_st@@@Z ++ ?copy_and_convert@@YAIPADIPAUcharset_info_st@@PBDI1PAI@Z ++ ?filename_to_tablename@@YAIPBDPADI@Z ++ ?strconvert@@YAIPAUcharset_info_st@@PBD0PADIPAI@Z ++ ?calculate_key_len@@YAIPAUst_table@@IPBEK@Z ++ ?sql_alloc@@YAPAXI@Z ++ ?localtime_to_TIME@@YAXPAUst_mysql_time@@PAUtm@@@Z ++ ?push_warning@@YAPAVMYSQL_ERROR@@PAVTHD@@W4enum_warning_level@1@IPBD@Z ++ ?push_warning_printf@@YAXPAVTHD@@W4enum_warning_level@MYSQL_ERROR@@IPBDZZ ++ ?drop_table@handler@@EAEXPBD@Z ++ ?column_bitmaps_signal@handler@@UAEXXZ ++ ?delete_table@handler@@MAEHPBD@Z ++ ?rename_table@handler@@MAEHPBD0@Z ++ ?key_map_empty@@3V?$Bitmap@$0EA@@@B ++ ?THR_THD@@3PAVTHD@@A ++ ?end_of_list@@3Ulist_node@@A ++ ?mysql_tmpdir_list@@3Ust_my_tmpdir@@A ++ ?mysql_bin_log@@3VMYSQL_BIN_LOG@@A ++ ?is_open@MYSQL_LOG@@QAE_NXZ ++ mysql_query_cache_invalidate4 ++ thd_query ++ thd_sql_command ++ thd_get_xid ++ thd_slave_thread ++ thd_non_transactional_update ++ thd_mark_transaction_to_rollback ++ thd_security_context ++ thd_charset ++ thd_test_options ++ thd_ha_data ++ thd_killed ++ thd_tx_isolation ++ thd_tablespace_op ++ thd_sql_command ++ thd_memdup ++ thd_make_lex_string ++ thd_in_lock_tables ++ thd_binlog_format ++ _my_hash_init ++ my_hash_free ++ my_tmpdir ++ check_if_legal_filename ++ my_filename ++ my_sync_dir_by_file ++ alloc_root ++ thr_lock_data_init ++ thr_lock_init ++ thr_lock_delete ++ my_multi_malloc ++ get_charset ++ unpack_filename ++ my_hash_insert ++ my_hash_search ++ my_hash_delete ++ mysql_bin_log_file_pos ++ mysql_bin_log_file_name ++ mysqld_embedded ++ my_thread_name ++ my_malloc ++ my_no_flags_free ++ _sanity ++ _mymalloc ++ _myfree ++ _my_strdup ++ _my_thread_var ++ my_error ++ pthread_cond_init ++ pthread_cond_signal ++ pthread_cond_wait ++ pthread_cond_destroy ++ localtime_r ++ my_strdup + +diff -Nur ../old/sql/mysqld_x64.def.orig ./sql/mysqld_x64.def +--- sql/mysqld_x64.def.orig 1969-12-31 18:00:00 -06:00 ++++ sql/mysqld_x64.def 2008-10-31 02:22:04 -05:00 +@@ -0,0 +1,99 @@ ++EXPORTS ++ ?use_hidden_primary_key@handler@@UEAAXXZ ++ ?get_dynamic_partition_info@handler@@UEAAXPEAUPARTITION_INFO@@I@Z ++ ?read_first_row@handler@@UEAAHPEAEI@Z ++ ?read_range_next@handler@@UEAAHXZ ++ ?read_range_first@handler@@UEAAHPEBUst_key_range@@0_N1@Z ++ ?read_multi_range_first@handler@@UEAAHPEAPEAUst_key_multi_range@@PEAU2@I_NPEAUst_handler_buffer@@@Z ++ ?read_multi_range_next@handler@@UEAAHPEAPEAUst_key_multi_range@@@Z ++ ?index_read_idx_map@handler@@UEAAHPEAEIPEBEKW4ha_rkey_function@@@Z ++ ?print_error@handler@@UEAAXHH@Z ++ ?clone@handler@@UEAAPEAV1@PEAUst_mem_root@@@Z ++ ?get_auto_increment@handler@@UEAAX_K00PEA_K1@Z ++ ?index_next_same@handler@@UEAAHPEAEPEBEI@Z ++ ?get_error_message@handler@@UEAA_NHPEAVString@@@Z ++ ?ha_thd@handler@@IEBAPEAVTHD@@XZ ++ ?update_auto_increment@handler@@QEAAHXZ ++ ?ha_statistic_increment@handler@@IEBAXPEQsystem_status_var@@K@Z ++ ?trans_register_ha@@YAXPEAVTHD@@_NPEAUhandlerton@@@Z ++ ?cmp@Field_blob@@QEAAHPEBEI0I@Z ++ ?set_time@Field_timestamp@@QEAAXXZ ++ ?sql_print_error@@YAXPEBDZZ ++ ?sql_print_warning@@YAXPEBDZZ ++ ?check_global_access@@YA_NPEAVTHD@@K@Z ++ ?schema_table_store_record@@YA_NPEAVTHD@@PEAUst_table@@@Z ++ ?get_quote_char_for_identifier@@YAHPEAVTHD@@PEBDI@Z ++ ?copy@String@@QEAA_NXZ ++ ?copy@String@@QEAA_NAEBV1@@Z ++ ?copy@String@@QEAA_NPEBDIPEAUcharset_info_st@@@Z ++ ?copy_and_convert@@YAIPEADIPEAUcharset_info_st@@PEBDI1PEAI@Z ++ ?filename_to_tablename@@YAIPEBDPEADI@Z ++ ?strconvert@@YAIPEAUcharset_info_st@@PEBD0PEADIPEAI@Z ++ ?calculate_key_len@@YAIPEAUst_table@@IPEBEK@Z ++ ?sql_alloc@@YAPEAX_K@Z ++ ?localtime_to_TIME@@YAXPEAUst_mysql_time@@PEAUtm@@@Z ++ ?push_warning@@YAPEAVMYSQL_ERROR@@PEAVTHD@@W4enum_warning_level@1@IPEBD@Z ++ ?push_warning_printf@@YAXPEAVTHD@@W4enum_warning_level@MYSQL_ERROR@@IPEBDZZ ++ ?drop_table@handler@@EEAAXPEBD@Z ++ ?column_bitmaps_signal@handler@@UEAAXXZ ++ ?delete_table@handler@@MEAAHPEBD@Z ++ ?rename_table@handler@@MEAAHPEBD0@Z ++ ?key_map_empty@@3V?$Bitmap@$0EA@@@B ++ ?THR_THD@@3PEAVTHD@@EA ++ ?end_of_list@@3Ulist_node@@A ++ ?mysql_tmpdir_list@@3Ust_my_tmpdir@@A ++ ?mysql_bin_log@@3VMYSQL_BIN_LOG@@A ++ ?is_open@MYSQL_LOG@@QEAA_NXZ ++ mysql_query_cache_invalidate4 ++ thd_query ++ thd_sql_command ++ thd_get_xid ++ thd_slave_thread ++ thd_non_transactional_update ++ thd_mark_transaction_to_rollback ++ thd_security_context ++ thd_charset ++ thd_test_options ++ thd_ha_data ++ thd_killed ++ thd_tx_isolation ++ thd_tablespace_op ++ thd_sql_command ++ thd_memdup ++ thd_make_lex_string ++ thd_in_lock_tables ++ thd_binlog_format ++ _my_hash_init ++ my_hash_free ++ my_tmpdir ++ check_if_legal_filename ++ my_filename ++ my_sync_dir_by_file ++ alloc_root ++ thr_lock_data_init ++ thr_lock_init ++ thr_lock_delete ++ my_multi_malloc ++ get_charset ++ unpack_filename ++ my_hash_insert ++ my_hash_search ++ my_hash_delete ++ mysql_bin_log_file_pos ++ mysql_bin_log_file_name ++ mysqld_embedded ++ my_thread_name ++ my_malloc ++ my_no_flags_free ++ _sanity ++ _mymalloc ++ _myfree ++ _my_strdup ++ _my_thread_var ++ my_error ++ pthread_cond_init ++ pthread_cond_signal ++ pthread_cond_wait ++ pthread_cond_destroy ++ localtime_r ++ my_strdup + +diff -Nur win/configure.js.orig win/configure.js +--- win/configure.js.orig 2008-09-26 21:18:37 -05:00 ++++ win/configure.js 2008-10-01 11:21:27 -05:00 +@@ -49,6 +49,7 @@ + case "CYBOZU": + case "EMBED_MANIFESTS": + case "WITH_EMBEDDED_SERVER": ++ case "INNODB_DYNAMIC_PLUGIN": + configfile.WriteLine("SET (" + args.Item(i) + " TRUE)"); + break; + case "MYSQL_SERVER_SUFFIX": + +diff -Nur win/build-vs71.bat.orig win/build-vs71.bat +--- win/build-vs71.bat.orig 2008-08-20 10:21:59 -05:00 ++++ win/build-vs71.bat 2008-10-27 10:52:38 -05:00 +@@ -15,8 +15,10 @@ + REM along with this program; if not, write to the Free Software + REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ++REM CMAKE_BUILD_TYPE can be specified as Release or Debug ++ + if exist cmakecache.txt del cmakecache.txt + copy win\vs71cache.txt cmakecache.txt +-cmake -G "Visual Studio 7 .NET 2003" ++cmake -G "Visual Studio 7 .NET 2003" -DCMAKE_BUILD_TYPE=%1 + copy cmakecache.txt win\vs71cache.txt + +diff -Nur win/build-vs8.bat.orig win/build-vs8.bat +--- win/build-vs8.bat.orig 2008-08-20 10:21:59 -05:00 ++++ win/build-vs8.bat 2008-10-27 10:52:31 -05:00 +@@ -15,7 +15,9 @@ + REM along with this program; if not, write to the Free Software + REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ++REM CMAKE_BUILD_TYPE can be specified as Release or Debug ++ + if exist cmakecache.txt del cmakecache.txt + copy win\vs8cache.txt cmakecache.txt +-cmake -G "Visual Studio 8 2005" ++cmake -G "Visual Studio 8 2005" -DCMAKE_BUILD_TYPE=%1 + copy cmakecache.txt win\vs8cache.txt +diff -Nur win/build-vs8_x64.bat.orig win/build-vs8_x64.bat +--- win/build-vs8_x64.bat.orig 2008-08-20 10:21:59 -05:00 ++++ win/build-vs8_x64.bat 2008-10-27 10:53:11 -05:00 +@@ -15,7 +15,9 @@ + REM along with this program; if not, write to the Free Software + REM Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + ++REM CMAKE_BUILD_TYPE can be specified as Release or Debug ++ + if exist cmakecache.txt del cmakecache.txt + copy win\vs8cache.txt cmakecache.txt +-cmake -G "Visual Studio 8 2005 Win64" ++cmake -G "Visual Studio 8 2005 Win64" -DCMAKE_BUILD_TYPE=%1 + copy cmakecache.txt win\vs8cache.txt