From 4b0f010b884cb298a33ed438c2b3688c472dbbf7 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 2 May 2019 14:25:24 +0100 Subject: [PATCH 1/5] MDEV-18544 "missing required privilege PROCESS on *.*" using mariabackup for SST If required privilege is missing, dump the output from "SHOW GRANTS" into mariabackup log. This will help troubleshooting, and make the bug reproducible. --- extra/mariabackup/xtrabackup.cc | 7 +++++++ mysql-test/suite/mariabackup/backup_grants.result | 1 + mysql-test/suite/mariabackup/backup_grants.test | 3 ++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index eae55ddb02e..538d00f0fdb 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -5820,6 +5820,13 @@ check_all_privileges() if (check_result & PRIVILEGE_ERROR) { mysql_close(mysql_connection); + msg("Current privileges, as reported by 'SHOW GRANTS': "); + int n=1; + for (std::list::const_iterator it = granted_privileges.begin(); + it != granted_privileges.end(); + it++,n++) { + msg(" %d.%s", n, it->c_str()); + } die("Insufficient privileges"); } } diff --git a/mysql-test/suite/mariabackup/backup_grants.result b/mysql-test/suite/mariabackup/backup_grants.result index d8869b7ac82..ed793e7ff1a 100644 --- a/mysql-test/suite/mariabackup/backup_grants.result +++ b/mysql-test/suite/mariabackup/backup_grants.result @@ -1,5 +1,6 @@ CREATE user backup@localhost; FOUND 1 /missing required privilege RELOAD/ in backup.log FOUND 1 /missing required privilege PROCESS/ in backup.log +FOUND 1 /GRANT USAGE ON/ in backup.log GRANT RELOAD, PROCESS on *.* to backup@localhost; DROP USER backup@localhost; diff --git a/mysql-test/suite/mariabackup/backup_grants.test b/mysql-test/suite/mariabackup/backup_grants.test index 1c0c3f89346..eadeedd9b5f 100644 --- a/mysql-test/suite/mariabackup/backup_grants.test +++ b/mysql-test/suite/mariabackup/backup_grants.test @@ -18,7 +18,8 @@ let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/backup.log; --source include/search_pattern_in_file.inc --let SEARCH_PATTERN= missing required privilege PROCESS --source include/search_pattern_in_file.inc - +--let SEARCH_PATTERN= GRANT USAGE ON +--source include/search_pattern_in_file.inc # backup succeeds with RELOAD privilege GRANT RELOAD, PROCESS on *.* to backup@localhost; --disable_result_log From 13d7c721a54ea777898cd0db9dce8ebc516a8af8 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 2 May 2019 19:44:36 +0100 Subject: [PATCH 2/5] MDEV-17008 prepare with datadir, on Windows, does not set ACL on tablespace files Fix is to always add Full Control for NetworkService account, for every file that copyback/moveback copies around. --- extra/mariabackup/backup_copy.cc | 68 +++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/extra/mariabackup/backup_copy.cc b/extra/mariabackup/backup_copy.cc index fa665a798ac..ee7f55e304c 100644 --- a/extra/mariabackup/backup_copy.cc +++ b/extra/mariabackup/backup_copy.cc @@ -989,6 +989,65 @@ run_data_threads(datadir_iter_t *it, os_thread_func_t func, uint n) return(ret); } +#ifdef _WIN32 +#include +#include +#include +/* + On Windows, fix permission of the file after "copyback" + We assume that after copyback, mysqld will run as service as NetworkService + user, thus well give full permission on given file to that user. +*/ + +static int fix_win_file_permissions(const char *file) +{ + struct { + TOKEN_USER tokenUser; + BYTE buffer[SECURITY_MAX_SID_SIZE]; + } tokenInfoBuffer; + HANDLE hFile = CreateFile(file, READ_CONTROL | WRITE_DAC, 0, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return -1; + ACL* pOldDACL; + SECURITY_DESCRIPTOR* pSD = NULL; + EXPLICIT_ACCESS ea = { 0 }; + BOOL isWellKnownSID = FALSE; + PSID pSid = NULL; + + GetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, + &pOldDACL, NULL, (void**)&pSD); + DWORD size = SECURITY_MAX_SID_SIZE; + pSid = (PSID)tokenInfoBuffer.buffer; + if (!CreateWellKnownSid(WinNetworkServiceSid, NULL, pSid, + &size)) + { + return 1; + } + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.ptstrName = (LPTSTR)pSid; + + ea.grfAccessMode = GRANT_ACCESS; + ea.grfAccessPermissions = GENERIC_ALL; + ea.grfInheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; + ea.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN; + ACL* pNewDACL = 0; + DWORD err = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL); + if (pNewDACL) + { + SetSecurityInfo(hFile, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, + pNewDACL, NULL); + } + if (pSD != NULL) + LocalFree((HLOCAL)pSD); + if (pNewDACL != NULL) + LocalFree((HLOCAL)pNewDACL); + CloseHandle(hFile); + return 0; +} + +#endif + /************************************************************************ Copy file for backup/restore. @@ -1037,6 +1096,10 @@ copy_file(ds_ctxt_t *datasink, /* close */ msg(thread_n," ...done"); datafile_close(&cursor); +#ifdef _WIN32 + if (xtrabackup_copy_back || xtrabackup_move_back) + ut_a(!fix_win_file_permissions(dstfile->path)); +#endif if (ds_close(dstfile)) { goto error_close; } @@ -1107,7 +1170,10 @@ move_file(ds_ctxt_t *datasink, errbuf); return(false); } - +#ifdef _WIN32 + if (xtrabackup_copy_back || xtrabackup_move_back) + ut_a(!fix_win_file_permissions(dst_file_path_abs)); +#endif msg(thread_n," ...done"); return(true); From bcc1359223c254e7649383c0993b6d27d5002c5d Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Sat, 16 Mar 2019 21:06:04 +0300 Subject: [PATCH 3/5] MDEV-17702 fix unaligned access UB in sint4korr() and similar functions Disable (hopefully temprorary) this check. Also add tests for some serialized functions. --- CMakeLists.txt | 2 +- unittest/mysys/CMakeLists.txt | 2 +- unittest/mysys/byte_order-t.c | 102 ++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 unittest/mysys/byte_order-t.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 03ab7216bad..f2397d29968 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -217,7 +217,7 @@ IF (WITH_UBSAN) IF(SECURITY_HARDENED) MESSAGE(FATAL_ERROR "WITH_UBSAN and SECURITY_HARDENED are mutually exclusive") ENDIF() - MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=undefined" DEBUG RELWITHDEBINFO) + MY_CHECK_AND_SET_COMPILER_FLAG("-fsanitize=undefined -fno-sanitize=alignment" DEBUG RELWITHDEBINFO) ENDIF() diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt index 0c61ff09af2..3be57e27943 100644 --- a/unittest/mysys/CMakeLists.txt +++ b/unittest/mysys/CMakeLists.txt @@ -14,7 +14,7 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring - aes + aes byte_order LINK_LIBRARIES mysys) MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys) diff --git a/unittest/mysys/byte_order-t.c b/unittest/mysys/byte_order-t.c new file mode 100644 index 00000000000..e276e597fbf --- /dev/null +++ b/unittest/mysys/byte_order-t.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2019, MariaDB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +/** + @file + + Unit tests for serialization and deserialization functions +*/ + +#include "tap.h" + +#include "my_byteorder.h" +#include "myisampack.h" +#include "m_string.h" + +void test_byte_order() +{ + MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) + uchar buf[CPU_LEVEL1_DCACHE_LINESIZE * 2]; + + uchar *aligned= buf; + uchar *not_aligned= buf + CPU_LEVEL1_DCACHE_LINESIZE - 1; + +#define TEST(STORE_NAME, LOAD_NAME, TYPE, VALUE, BYTES) \ + { \ + TYPE value= VALUE; \ + uchar bytes[]= BYTES; \ + STORE_NAME(aligned, value); \ + ok(!memcmp(aligned, bytes, sizeof(bytes)), "aligned\t\t" #STORE_NAME); \ + ok(LOAD_NAME(aligned) == value, "aligned\t\t" #LOAD_NAME); \ + STORE_NAME(not_aligned, value); \ + ok(!memcmp(not_aligned, bytes, sizeof(bytes)), \ + "not aligned\t" #STORE_NAME); \ + ok(LOAD_NAME(not_aligned) == value, "not aligned\t" #LOAD_NAME); \ + } + +#define ARRAY_2(A, B) {A, B} +#define ARRAY_3(A, B, C) {A, B, C} +#define ARRAY_4(A, B, C, D) {A, B, C, D} +#define ARRAY_5(A, B, C, D, E) {A, B, C, D, E} +#define ARRAY_6(A, B, C, D, E, F) {A, B, C, D, E, F} +#define ARRAY_7(A, B, C, D, E, F, G) {A, B, C, D, E, F, G} +#define ARRAY_8(A, B, C, D, E, F, G, H) {A, B, C, D, E, F, G, H} + + TEST(int2store, sint2korr, int16, 0x0201, ARRAY_2(1, 2)); + TEST(int3store, sint3korr, int32, 0xffffffff, ARRAY_3(0xff, 0xff, 0xff)); + TEST(int3store, sint3korr, int32, 0x030201, ARRAY_3(1, 2, 3)); + TEST(int4store, sint4korr, int32, 0xffffffff, + ARRAY_4(0xff, 0xff, 0xff, 0xff)); + TEST(int4store, sint4korr, int32, 0x04030201, ARRAY_4(1, 2, 3, 4)); + TEST(int8store, sint8korr, longlong, 0x0807060504030201, + ARRAY_8(1, 2, 3, 4, 5, 6, 7, 8)); + TEST(int8store, sint8korr, longlong, 0xffffffffffffffff, + ARRAY_8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff)); + + TEST(int2store, uint2korr, uint16, 0x0201, ARRAY_2(1, 2)); + TEST(int3store, uint3korr, uint32, 0x030201, ARRAY_3(1, 2, 3)); + TEST(int4store, uint4korr, uint32, 0x04030201, ARRAY_4(1, 2, 3, 4)); + TEST(int5store, uint5korr, ulonglong, 0x0504030201, ARRAY_5(1, 2, 3, 4, 5)); + TEST(int6store, uint6korr, ulonglong, 0x060504030201, + ARRAY_6(1, 2, 3, 4, 5, 6)); + TEST(int8store, uint8korr, ulonglong, 0x0807060504030201, + ARRAY_8(1, 2, 3, 4, 5, 6, 7, 8)); + + TEST(mi_int5store, mi_uint5korr, ulonglong, 0x0504030201, + ARRAY_5(5, 4, 3, 2, 1)); + TEST(mi_int6store, mi_uint6korr, ulonglong, 0x060504030201, + ARRAY_6(6, 5, 4, 3, 2, 1)); + TEST(mi_int7store, mi_uint7korr, ulonglong, 0x07060504030201, + ARRAY_7(7, 6, 5, 4, 3, 2, 1)); + TEST(mi_int8store, mi_uint8korr, ulonglong, 0x0807060504030201, + ARRAY_8(8, 7, 6, 5, 4, 3, 2, 1)); + +#undef ARRAY_8 +#undef ARRAY_7 +#undef ARRAY_6 +#undef ARRAY_5 +#undef ARRAY_4 +#undef ARRAY_3 +#undef ARRAY_2 + +#undef TEST +} + +int main(int argc, char **argv) +{ + plan(68); + test_byte_order(); + return exit_status(); +} From 3db94d2403c1f2791bddd43656d7b0d6320b453d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 3 May 2019 20:02:11 +0300 Subject: [PATCH 4/5] MDEV-19346: Remove dummy InnoDB log checkpoints log_checkpoint(), log_make_checkpoint_at(): Remove the parameter write_always. It seems that the primary purpose of this parameter was to ensure in the function recv_reset_logs() that both checkpoint header pages will be overwritten, when the function is called from the never-enabled function recv_recovery_from_archive_start(). create_log_files(): Merge recv_reset_logs() to its only caller. Debug instrumentation: Prefer to flush the redo log, instead of triggering a redo log checkpoint. page_header_set_field(): Disable a debug assertion that will always fail due to MDEV-19344, now that we no longer initiate a redo log checkpoint before an injected crash. In recv_reset_logs() there used to be two calls to log_make_checkpoint_at(). The apparent purpose of this was to ensure that both InnoDB redo log checkpoint header pages will be initialized or overwritten. The second call was removed (without any explanation) in MySQL 5.6.3: mysql/mysql-server@4ca37968da54ddc6b3b6628f41428ddba1c79bb8 In MySQL 5.6.8 WL#6494, starting with mysql/mysql-server@00a0ba8ad92569fcf08212b3b8cf046dc8a0ce10 the function recv_reset_logs() was not only invoked during InnoDB data file initialization, but also during a regular startup when the redo log is being resized. mysql/mysql-server@45e91679832219e2593c77185342f11f85232b58 in MySQL 5.7.2 removed the UNIV_LOG_ARCHIVE code, but still did not remove the parameter write_always. --- storage/innobase/buf/buf0dblwr.cc | 2 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/handler/handler0alter.cc | 1 - storage/innobase/include/log0log.h | 18 ++------ storage/innobase/include/log0recv.h | 10 ----- storage/innobase/include/page0page.ic | 2 + storage/innobase/log/log0log.cc | 50 ++++++++--------------- storage/innobase/log/log0recv.cc | 48 ---------------------- storage/innobase/row/row0import.cc | 2 +- storage/innobase/row/row0ins.cc | 3 +- storage/innobase/row/row0mysql.cc | 4 +- storage/innobase/row/row0trunc.cc | 4 +- storage/innobase/srv/srv0srv.cc | 4 +- storage/innobase/srv/srv0start.cc | 23 ++++++++++- storage/innobase/trx/trx0trx.cc | 3 +- 15 files changed, 56 insertions(+), 120 deletions(-) diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc index 194cc848234..200a65ba6ef 100644 --- a/storage/innobase/buf/buf0dblwr.cc +++ b/storage/innobase/buf/buf0dblwr.cc @@ -328,7 +328,7 @@ too_small: mtr_commit(&mtr); /* Flush the modified pages to disk and make a checkpoint */ - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); /* Remove doublewrite pages from LRU */ buf_pool_invalidate(); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index ecf85a81638..18158eae595 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -19110,7 +19110,7 @@ checkpoint_now_set( + (log_sys->append_on_checkpoint != NULL ? log_sys->append_on_checkpoint->size() : 0) < log_sys->lsn) { - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); fil_flush_file_spaces(FIL_TYPE_LOG); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 05bb8ac61cd..005c0fd5adf 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -8474,7 +8474,6 @@ ha_innobase::commit_inplace_alter_table( and the .frm files must be swapped manually by the administrator. No loss of data. */ DBUG_EXECUTE_IF("innodb_alter_commit_crash_after_commit", - log_make_checkpoint_at(LSN_MAX, TRUE); log_buffer_flush_to_disk(); DBUG_SUICIDE();); } diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index 745714e791b..817cf8e8a61 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -208,23 +208,13 @@ blocks from the buffer pool: it only checks what is lsn of the oldest modification in the pool, and writes information about the lsn in log files. Use log_make_checkpoint_at() to flush also the pool. @param[in] sync whether to wait for the write to complete -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint @return true if success, false if a checkpoint write was already running */ -bool -log_checkpoint( - bool sync, - bool write_always); +bool log_checkpoint(bool sync); /** Make a checkpoint at or after a specified LSN. @param[in] lsn the log sequence number, or LSN_MAX -for the latest LSN -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint */ -void -log_make_checkpoint_at( - lsn_t lsn, - bool write_always); +for the latest LSN */ +void log_make_checkpoint_at(lsn_t lsn); /****************************************************************//** Makes a checkpoint at the latest lsn and writes it to first page of each diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index daa8e85fbf5..7526999a1e4 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -69,16 +69,6 @@ Initiates the rollback of active transactions. */ void recv_recovery_rollback_active(void); /*===============================*/ -/******************************************************//** -Resets the logs. The contents of log files will be lost! */ -void -recv_reset_logs( -/*============*/ - lsn_t lsn); /*!< in: reset to this lsn - rounded up to be divisible by - OS_FILE_LOG_BLOCK_SIZE, after - which we add - LOG_BLOCK_HDR_SIZE */ /** Clean up after recv_sys_init() */ void recv_sys_close(); diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic index d6fded4f178..76d041347fb 100644 --- a/storage/innobase/include/page0page.ic +++ b/storage/innobase/include/page0page.ic @@ -173,7 +173,9 @@ page_header_set_field( { ut_ad(page); ut_ad(field <= PAGE_N_RECS); +#if 0 /* FIXME: MDEV-19344 hits this */ ut_ad(field != PAGE_N_RECS || val); +#endif ut_ad(field == PAGE_N_HEAP || val < srv_page_size); ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < srv_page_size); diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 3a54af8e3c2..da301a3b4f1 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -337,7 +337,7 @@ log_margin_checkpoint_age( if (!flushed_enough) { os_thread_sleep(100000); } - log_checkpoint(true, false); + log_checkpoint(true); log_mutex_enter(); } @@ -1610,13 +1610,8 @@ blocks from the buffer pool: it only checks what is lsn of the oldest modification in the pool, and writes information about the lsn in log files. Use log_make_checkpoint_at() to flush also the pool. @param[in] sync whether to wait for the write to complete -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint @return true if success, false if a checkpoint write was already running */ -bool -log_checkpoint( - bool sync, - bool write_always) +bool log_checkpoint(bool sync) { lsn_t oldest_lsn; @@ -1657,9 +1652,15 @@ log_checkpoint( flushed up to oldest_lsn. */ ut_ad(oldest_lsn >= log_sys->last_checkpoint_lsn); - if (!write_always - && oldest_lsn - <= log_sys->last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) { + if (oldest_lsn + > log_sys->last_checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT) { + /* Some log has been written since the previous checkpoint. */ + } else if (srv_shutdown_state != SRV_SHUTDOWN_NONE) { + /* MariaDB 10.3 startup expects the redo log file to be + logically empty (not even containing a MLOG_CHECKPOINT record) + after a clean shutdown. Perform an extra checkpoint at + shutdown. */ + } else { /* Do nothing, because nothing was logged (other than a MLOG_CHECKPOINT marker) since the previous checkpoint. */ log_mutex_exit(); @@ -1691,20 +1692,6 @@ log_checkpoint( log_write_up_to(flush_lsn, true); - DBUG_EXECUTE_IF( - "using_wa_checkpoint_middle", - if (write_always) { - DEBUG_SYNC_C("wa_checkpoint_middle"); - - const my_bool b = TRUE; - buf_flush_page_cleaner_disabled_debug_update( - NULL, NULL, NULL, &b); - dict_stats_disabled_debug_update( - NULL, NULL, NULL, &b); - srv_master_thread_disabled_debug_update( - NULL, NULL, NULL, &b); - }); - log_mutex_enter(); ut_ad(log_sys->flushed_to_disk_lsn >= flush_lsn); @@ -1737,13 +1724,8 @@ log_checkpoint( /** Make a checkpoint at or after a specified LSN. @param[in] lsn the log sequence number, or LSN_MAX -for the latest LSN -@param[in] write_always force a write even if no log -has been generated since the latest checkpoint */ -void -log_make_checkpoint_at( - lsn_t lsn, - bool write_always) +for the latest LSN */ +void log_make_checkpoint_at(lsn_t lsn) { /* Preflush pages synchronously */ @@ -1751,7 +1733,7 @@ log_make_checkpoint_at( /* Flush as much as we can */ } - while (!log_checkpoint(true, write_always)) { + while (!log_checkpoint(true)) { /* Force a checkpoint */ } } @@ -1834,7 +1816,7 @@ loop: } if (do_checkpoint) { - log_checkpoint(checkpoint_sync, FALSE); + log_checkpoint(checkpoint_sync); if (checkpoint_sync) { @@ -2083,7 +2065,7 @@ wait_suspend_loop: if (!srv_read_only_mode) { service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL, "ensuring dirty buffer pool are written to log"); - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); log_mutex_enter(); diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 251ee2435f5..60279e7fc90 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2849,11 +2849,6 @@ loop: if (lsn == checkpoint_lsn) { if (recv_sys->mlog_checkpoint_lsn) { - /* At recv_reset_logs() we may - write a duplicate MLOG_CHECKPOINT - for the same checkpoint LSN. Thus - recv_sys->mlog_checkpoint_lsn - can differ from the current LSN. */ ut_ad(recv_sys->mlog_checkpoint_lsn <= recv_sys->recovered_lsn); break; @@ -4016,49 +4011,6 @@ recv_recovery_rollback_active(void) } } -/******************************************************//** -Resets the logs. The contents of log files will be lost! */ -void -recv_reset_logs( -/*============*/ - lsn_t lsn) /*!< in: reset to this lsn - rounded up to be divisible by - OS_FILE_LOG_BLOCK_SIZE, after - which we add - LOG_BLOCK_HDR_SIZE */ -{ - ut_ad(log_mutex_own()); - - log_sys->lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE); - - log_sys->log.lsn = log_sys->lsn; - log_sys->log.lsn_offset = LOG_FILE_HDR_SIZE; - - log_sys->buf_next_to_write = 0; - log_sys->write_lsn = log_sys->lsn; - - log_sys->next_checkpoint_no = 0; - log_sys->last_checkpoint_lsn = 0; - - memset(log_sys->buf, 0, log_sys->buf_size); - log_block_init(log_sys->buf, log_sys->lsn); - log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE); - - log_sys->buf_free = LOG_BLOCK_HDR_SIZE; - log_sys->lsn += LOG_BLOCK_HDR_SIZE; - - MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, - (log_sys->lsn - log_sys->last_checkpoint_lsn)); - - log_mutex_exit(); - - /* Reset the checkpoint fields in logs */ - - log_make_checkpoint_at(LSN_MAX, TRUE); - - log_mutex_enter(); -} - /** Find a doublewrite copy of a page. @param[in] space_id tablespace identifier @param[in] page_no page number diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 159535fba19..94c6d12b19e 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -2090,7 +2090,7 @@ row_import_cleanup( DBUG_EXECUTE_IF("ib_import_before_checkpoint_crash", DBUG_SUICIDE();); - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); return(err); } diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 03665ccdc3c..8bfef78cd8c 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -2722,8 +2722,7 @@ err_exit: DBUG_EXECUTE_IF( "row_ins_extern_checkpoint", - log_make_checkpoint_at( - LSN_MAX, TRUE);); + log_write_up_to(mtr.commit_lsn(), true);); err = row_ins_index_entry_big_rec( entry, big_rec, offsets, &offsets_heap, index, thr_get_trx(thr)->mysql_thd); diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index e19501edea4..a06c3cbd1a8 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2882,13 +2882,13 @@ row_discard_tablespace_end( } DBUG_EXECUTE_IF("ib_discard_before_commit_crash", - log_make_checkpoint_at(LSN_MAX, TRUE); + log_write_up_to(LSN_MAX, true); DBUG_SUICIDE();); trx_commit_for_mysql(trx); DBUG_EXECUTE_IF("ib_discard_after_commit_crash", - log_make_checkpoint_at(LSN_MAX, TRUE); + log_write_up_to(LSN_MAX, true); DBUG_SUICIDE();); row_mysql_unlock_data_dictionary(trx); diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc index 847b0d0ae06..cffcc73f312 100644 --- a/storage/innobase/row/row0trunc.cc +++ b/storage/innobase/row/row0trunc.cc @@ -1996,7 +1996,7 @@ dberr_t row_truncate_table_for_mysql(dict_table_t* table, trx_t* trx) DBUG_EXECUTE_IF("ib_trunc_crash_with_intermediate_log_checkpoint", log_buffer_flush_to_disk(); os_thread_sleep(2000000); - log_checkpoint(TRUE, TRUE); + log_checkpoint(TRUE); os_thread_sleep(1000000); DBUG_SUICIDE();); @@ -2224,7 +2224,7 @@ truncate_t::fixup_tables_in_non_system_tablespace() if (err == DB_SUCCESS && s_tables.size() > 0) { - log_make_checkpoint_at(LSN_MAX, TRUE); + log_make_checkpoint_at(LSN_MAX); } for (ulint i = 0; i < s_tables.size(); ++i) { diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 58596175681..b704d495946 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2261,7 +2261,7 @@ srv_master_do_active_tasks(void) /* Make a new checkpoint */ if (cur_time % SRV_MASTER_CHECKPOINT_INTERVAL == 0) { srv_main_thread_op_info = "making checkpoint"; - log_checkpoint(TRUE, FALSE); + log_checkpoint(true); MONITOR_INC_TIME_IN_MICRO_SECS( MONITOR_SRV_CHECKPOINT_MICROSECOND, counter_time); } @@ -2349,7 +2349,7 @@ srv_master_do_idle_tasks(void) /* Make a new checkpoint */ srv_main_thread_op_info = "making checkpoint"; - log_checkpoint(TRUE, FALSE); + log_checkpoint(true); MONITOR_INC_TIME_IN_MICRO_SECS(MONITOR_SRV_CHECKPOINT_MICROSECOND, counter_time); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index d75310607b3..95d1433f09c 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -495,9 +495,30 @@ create_log_files( return(DB_ERROR); } ut_d(recv_no_log_write = false); - recv_reset_logs(lsn); + log_sys->lsn = ut_uint64_align_up(lsn, OS_FILE_LOG_BLOCK_SIZE); + + log_sys->log.lsn = log_sys->lsn; + log_sys->log.lsn_offset = LOG_FILE_HDR_SIZE; + + log_sys->buf_next_to_write = 0; + log_sys->write_lsn = log_sys->lsn; + + log_sys->next_checkpoint_no = 0; + log_sys->last_checkpoint_lsn = 0; + + memset(log_sys->buf, 0, log_sys->buf_size); + log_block_init(log_sys->buf, log_sys->lsn); + log_block_set_first_rec_group(log_sys->buf, LOG_BLOCK_HDR_SIZE); + + log_sys->buf_free = LOG_BLOCK_HDR_SIZE; + log_sys->lsn += LOG_BLOCK_HDR_SIZE; + + MONITOR_SET(MONITOR_LSN_CHECKPOINT_AGE, + (log_sys->lsn - log_sys->last_checkpoint_lsn)); log_mutex_exit(); + log_make_checkpoint_at(LSN_MAX); + return(DB_SUCCESS); } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 91e60571438..88e9313cc06 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1859,7 +1859,8 @@ trx_commit_low( DBUG_EXECUTE_IF("ib_crash_during_trx_commit_in_mem", if (trx->has_logged()) { - log_make_checkpoint_at(LSN_MAX, TRUE); + log_write_up_to(mtr->commit_lsn(), + true); DBUG_SUICIDE(); }); /*--------------*/ From ce195987c3c995470992f16ca7a985796d6b65a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Fri, 3 May 2019 16:47:07 +0300 Subject: [PATCH 5/5] MDEV-19385: Inconsistent definition of dtuple_get_nth_v_field() The accessor dtuple_get_nth_v_field() was defined differently between debug and release builds in MySQL 5.7.8 in mysql/mysql-server@c47e1751b742454de553937039bbf2bcbe3c6bc7 and a debug assertion to document or enforce the questionable assumption tuple->v_fields == &tuple->fields[tuple->n_fields] was missing. This was apparently no problem until MDEV-11369 introduced instant ADD COLUMN to MariaDB Server 10.3. With that work present, in one test case, trx_undo_report_insert_virtual() could in release builds fetch the wrong value for a virtual column. We replace many of the dtuple_t accessors with const-preserving inline functions, and fix missing or misleadingly applied const qualifiers accordingly. --- storage/innobase/data/data0data.cc | 4 +- storage/innobase/fts/fts0fts.cc | 3 +- storage/innobase/gis/gis0geo.cc | 23 ++-- storage/innobase/gis/gis0rtree.cc | 9 +- storage/innobase/gis/gis0sea.cc | 6 +- storage/innobase/handler/ha_innodb.cc | 2 +- storage/innobase/include/data0data.h | 179 +++++++++++--------------- storage/innobase/include/data0data.ic | 155 +--------------------- storage/innobase/include/gis0geo.h | 3 +- storage/innobase/include/rem0cmp.ic | 4 +- storage/innobase/include/row0mysql.h | 2 +- storage/innobase/include/row0vers.h | 6 +- storage/innobase/include/trx0rec.h | 6 +- storage/innobase/rem/rem0rec.cc | 4 +- storage/innobase/row/row0ins.cc | 4 +- storage/innobase/row/row0merge.cc | 15 +-- storage/innobase/row/row0row.cc | 16 +-- storage/innobase/row/row0sel.cc | 20 +-- storage/innobase/row/row0upd.cc | 30 ++--- storage/innobase/row/row0vers.cc | 22 ++-- storage/innobase/trx/trx0rec.cc | 13 +- 21 files changed, 168 insertions(+), 358 deletions(-) diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc index 6b63960e00f..5b3a898e4d0 100644 --- a/storage/innobase/data/data0data.cc +++ b/storage/innobase/data/data0data.cc @@ -37,7 +37,7 @@ Created 5/30/1994 Heikki Tuuri /** Dummy variable to catch access to uninitialized fields. In the debug version, dtuple_create() will make all fields of dtuple_t point to data_error. */ -byte data_error; +ut_d(byte data_error); #endif /* UNIV_DEBUG */ /** Compare two data tuples. @@ -416,7 +416,7 @@ dfield_print_also_hex( break; } - data = static_cast(dfield_get_data(dfield)); + data = static_cast(dfield_get_data(dfield)); /* fall through */ case DATA_BINARY: diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index 206aa7231c1..a5e1d5eeb4c 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -3366,12 +3366,11 @@ fts_fetch_doc_from_tuple( const dict_field_t* ifield; const dict_col_t* col; ulint pos; - dfield_t* field; ifield = dict_index_get_nth_field(index, i); col = dict_field_get_col(ifield); pos = dict_col_get_no(col); - field = dtuple_get_nth_field(tuple, pos); + const dfield_t* field = dtuple_get_nth_field(tuple, pos); if (!get_doc->index_cache->charset) { get_doc->index_cache->charset = fts_get_charset( diff --git a/storage/innobase/gis/gis0geo.cc b/storage/innobase/gis/gis0geo.cc index 436249c0026..6ea0d157a01 100644 --- a/storage/innobase/gis/gis0geo.cc +++ b/storage/innobase/gis/gis0geo.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -68,9 +69,9 @@ static int rtree_add_point_to_mbr( /*===================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ uchar byte_order, /*!< in: byte order. */ double* mbr) /*!< in/out: mbr, which @@ -108,9 +109,9 @@ static int rtree_get_point_mbr( /*================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ uchar byte_order, /*!< in: byte order. */ double* mbr) /*!< in/out: mbr, @@ -127,9 +128,9 @@ static int rtree_get_linestring_mbr( /*=====================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ uchar byte_order, /*!< in: byte order. */ double* mbr) /*!< in/out: mbr, @@ -158,9 +159,9 @@ static int rtree_get_polygon_mbr( /*==================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ uchar byte_order, /*!< in: byte order. */ double* mbr) /*!< in/out: mbr, @@ -195,9 +196,9 @@ static int rtree_get_geometry_mbr( /*===================*/ - uchar** wkb, /*!< in: pointer to wkb, + const uchar** wkb, /*!< in: pointer to wkb, where point is stored. */ - uchar* end, /*!< in: end of wkb. */ + const uchar* end, /*!< in: end of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr, /*!< in/out: mbr. */ int top) /*!< in: if it is the top, @@ -297,7 +298,7 @@ stored in "well-known binary representation" (wkb) format. int rtree_mbr_from_wkb( /*===============*/ - uchar* wkb, /*!< in: wkb */ + const uchar* wkb, /*!< in: wkb */ uint size, /*!< in: size of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr) /*!< in/out: mbr, which must diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc index a3790f5440e..501989061c1 100644 --- a/storage/innobase/gis/gis0rtree.cc +++ b/storage/innobase/gis/gis0rtree.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -64,7 +65,7 @@ rtr_page_split_initialize_nodes( page_t* page; ulint n_uniq; ulint len; - byte* source_cur; + const byte* source_cur; block = btr_cur_get_block(cursor); page = buf_block_get_frame(block); @@ -104,7 +105,7 @@ rtr_page_split_initialize_nodes( } /* Put the insert key to node list */ - source_cur = static_cast(dfield_get_data( + source_cur = static_cast(dfield_get_data( dtuple_get_nth_field(tuple, 0))); cur->coords = reserve_coords(buf_pos, SPDIMS); rec = (byte*) mem_heap_alloc( @@ -1874,11 +1875,11 @@ rtr_estimate_n_rows_in_range( ulint dtuple_f_len MY_ATTRIBUTE((unused)); rtr_mbr_t range_mbr; double range_area; - byte* range_mbr_ptr; dtuple_field = dtuple_get_nth_field(tuple, 0); dtuple_f_len = dfield_get_len(dtuple_field); - range_mbr_ptr = reinterpret_cast(dfield_get_data(dtuple_field)); + const byte* range_mbr_ptr = static_cast( + dfield_get_data(dtuple_field)); ut_ad(dtuple_f_len >= DATA_MBR_LEN); rtr_read_mbr(range_mbr_ptr, &range_mbr); diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc index cdddc346c77..995d99ad73b 100644 --- a/storage/innobase/gis/gis0sea.cc +++ b/storage/innobase/gis/gis0sea.cc @@ -1631,15 +1631,13 @@ rtr_get_mbr_from_tuple( { const dfield_t* dtuple_field; ulint dtuple_f_len; - byte* data; dtuple_field = dtuple_get_nth_field(dtuple, 0); dtuple_f_len = dfield_get_len(dtuple_field); ut_a(dtuple_f_len >= 4 * sizeof(double)); - data = static_cast(dfield_get_data(dtuple_field)); - - rtr_read_mbr(data, mbr); + rtr_read_mbr(static_cast(dfield_get_data(dtuple_field)), + mbr); } /****************************************************************//** diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 18158eae595..eb6664c427a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -21784,7 +21784,7 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage) to store the value in passed in "my_rec" */ dfield_t* innobase_get_computed_value( - const dtuple_t* row, + dtuple_t* row, const dict_v_col_t* col, const dict_index_t* index, mem_heap_t** local_heap, diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h index c181aa01a38..b9877656aaf 100644 --- a/storage/innobase/include/data0data.h +++ b/storage/innobase/include/data0data.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -31,6 +31,7 @@ Created 5/30/1994 Heikki Tuuri #include "data0type.h" #include "mem0mem.h" #include "dict0types.h" +#include "btr0types.h" #include @@ -39,29 +40,11 @@ index record which needs external storage of data fields */ struct big_rec_t; struct upd_t; -#ifdef UNIV_DEBUG -/*********************************************************************//** -Gets pointer to the type struct of SQL data field. -@return pointer to the type struct */ -UNIV_INLINE -dtype_t* -dfield_get_type( -/*============*/ - const dfield_t* field) /*!< in: SQL data field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Gets pointer to the data in a field. -@return pointer to data */ -UNIV_INLINE -void* -dfield_get_data( -/*============*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -#else /* UNIV_DEBUG */ -# define dfield_get_type(field) (&(field)->type) -# define dfield_get_data(field) ((field)->data) -#endif /* UNIV_DEBUG */ +/** Dummy variable to catch access to uninitialized fields. In the +debug version, dtuple_create() will make all fields of dtuple_t point +to data_error. */ +ut_d(extern byte data_error); + /*********************************************************************//** Sets the type struct of SQL data field. */ UNIV_INLINE @@ -72,15 +55,6 @@ dfield_set_type( const dtype_t* type); /*!< in: pointer to data type struct */ /*********************************************************************//** -Gets length of field data. -@return length of data; UNIV_SQL_NULL if SQL null data */ -UNIV_INLINE -ulint -dfield_get_len( -/*===========*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** Sets length in a field. */ UNIV_INLINE void @@ -89,32 +63,6 @@ dfield_set_len( dfield_t* field, /*!< in: field */ ulint len) /*!< in: length or UNIV_SQL_NULL */ MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** -Determines if a field is SQL NULL -@return nonzero if SQL null data */ -UNIV_INLINE -ulint -dfield_is_null( -/*===========*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Determines if a field is externally stored -@return nonzero if externally stored */ -UNIV_INLINE -ulint -dfield_is_ext( -/*==========*/ - const dfield_t* field) /*!< in: field */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Sets the "external storage" flag */ -UNIV_INLINE -void -dfield_set_ext( -/*===========*/ - dfield_t* field) /*!< in/out: field */ - MY_ATTRIBUTE((nonnull)); /** Gets spatial status for "external storage" @param[in,out] field field */ @@ -221,46 +169,7 @@ dfield_data_is_binary_equal( ulint len, /*!< in: data length or UNIV_SQL_NULL */ const byte* data) /*!< in: data */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/*********************************************************************//** -Gets number of fields in a data tuple. -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_fields( -/*================*/ - const dtuple_t* tuple) /*!< in: tuple */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); -/** Gets number of virtual fields in a data tuple. -@param[in] tuple dtuple to check -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_v_fields( - const dtuple_t* tuple); -#ifdef UNIV_DEBUG -/** Gets nth field of a tuple. -@param[in] tuple tuple -@param[in] n index of field -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_field( - const dtuple_t* tuple, - ulint n); -/** Gets nth virtual field of a tuple. -@param[in] tuple tuple -@oaran[in] n the nth field to get -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_v_field( - const dtuple_t* tuple, - ulint n); -#else /* UNIV_DEBUG */ -# define dtuple_get_nth_field(tuple, n) ((tuple)->fields + (n)) -# define dtuple_get_nth_v_field(tuple, n) ((tuple)->fields + (tuple)->n_fields + (n)) -#endif /* UNIV_DEBUG */ /*********************************************************************//** Gets info bits in a data tuple. @return info bits */ @@ -338,19 +247,12 @@ dtuple_create( /** Initialize the virtual field data in a dtuple_t @param[in,out] vrow dtuple contains the virtual fields */ -UNIV_INLINE -void -dtuple_init_v_fld( - const dtuple_t* vrow); +UNIV_INLINE void dtuple_init_v_fld(dtuple_t* vrow); /** Duplicate the virtual field data in a dtuple_t @param[in,out] vrow dtuple contains the virtual fields @param[in] heap heap memory to use */ -UNIV_INLINE -void -dtuple_dup_v_fld( - const dtuple_t* vrow, - mem_heap_t* heap); +UNIV_INLINE void dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap); /** Creates a data tuple with possible virtual columns to a memory heap. @param[in] heap memory heap where the tuple is created @@ -619,6 +521,69 @@ struct dtuple_t { #endif /* UNIV_DEBUG */ }; +inline ulint dtuple_get_n_fields(const dtuple_t* tuple) +{ return tuple->n_fields; } +inline dtype_t* dfield_get_type(dfield_t* field) { return &field->type; } +inline const dtype_t* dfield_get_type(const dfield_t* field) +{ return &field->type; } +inline void* dfield_get_data(dfield_t* field) +{ + ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error); + return field->data; +} +inline const void* dfield_get_data(const dfield_t* field) +{ + ut_ad(field->len == UNIV_SQL_NULL || field->data != &data_error); + return field->data; +} +inline ulint dfield_get_len(const dfield_t* field) { return field->len; } +inline bool dfield_is_null(const dfield_t* field) +{ return field->len == UNIV_SQL_NULL; } +/** @return whether a column is to be stored off-page */ +inline bool dfield_is_ext(const dfield_t* field) +{ + ut_ad(!field->ext || field->len >= BTR_EXTERN_FIELD_REF_SIZE); + return static_cast(field->ext); +} +/** Set the "external storage" flag */ +inline void dfield_set_ext(dfield_t* field) { field->ext = 1; } + +/** Gets number of virtual fields in a data tuple. +@param[in] tuple dtuple to check +@return number of fields */ +inline ulint +dtuple_get_n_v_fields(const dtuple_t* tuple) { return tuple->n_v_fields; } + +inline const dfield_t* dtuple_get_nth_field(const dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_fields); + return &tuple->fields[n]; +} +inline dfield_t* dtuple_get_nth_field(dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_fields); + return &tuple->fields[n]; +} + +/** Get a virtual column in a table row or an extended clustered index record. +@param[in] tuple tuple +@oaran[in] n the nth virtual field to get +@return nth virtual field */ +inline const dfield_t* dtuple_get_nth_v_field(const dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_v_fields); + return &tuple->v_fields[n]; +} +/** Get a virtual column in a table row or an extended clustered index record. +@param[in] tuple tuple +@oaran[in] n the nth virtual field to get +@return nth virtual field */ +inline dfield_t* dtuple_get_nth_v_field(dtuple_t* tuple, ulint n) +{ + ut_ad(n < tuple->n_v_fields); + return &tuple->v_fields[n]; +} + /** A slot for a field in a big rec vector */ struct big_rec_field_t { diff --git a/storage/innobase/include/data0data.ic b/storage/innobase/include/data0data.ic index f8689db54ec..448566e452f 100644 --- a/storage/innobase/include/data0data.ic +++ b/storage/innobase/include/data0data.ic @@ -24,28 +24,7 @@ SQL data field and tuple Created 5/30/1994 Heikki Tuuri *************************************************************************/ -#include "mem0mem.h" #include "ut0rnd.h" -#include "btr0types.h" - -#ifdef UNIV_DEBUG -/** Dummy variable to catch access to uninitialized fields. In the -debug version, dtuple_create() will make all fields of dtuple_t point -to data_error. */ -extern byte data_error; - -/*********************************************************************//** -Gets pointer to the type struct of SQL data field. -@return pointer to the type struct */ -UNIV_INLINE -dtype_t* -dfield_get_type( -/*============*/ - const dfield_t* field) /*!< in: SQL data field */ -{ - return((dtype_t*) &(field->type)); -} -#endif /* UNIV_DEBUG */ /*********************************************************************//** Sets the type struct of SQL data field. */ @@ -62,38 +41,6 @@ dfield_set_type( field->type = *type; } -#ifdef UNIV_DEBUG -/*********************************************************************//** -Gets pointer to the data in a field. -@return pointer to data */ -UNIV_INLINE -void* -dfield_get_data( -/*============*/ - const dfield_t* field) /*!< in: field */ -{ - ut_ad((field->len == UNIV_SQL_NULL) - || (field->data != &data_error)); - - return((void*) field->data); -} -#endif /* UNIV_DEBUG */ - -/*********************************************************************//** -Gets length of field data. -@return length of data; UNIV_SQL_NULL if SQL null data */ -UNIV_INLINE -ulint -dfield_get_len( -/*===========*/ - const dfield_t* field) /*!< in: field */ -{ - ut_ad((field->len == UNIV_SQL_NULL) - || (field->data != &data_error)); - - return(field->len); -} - /*********************************************************************//** Sets length in a field. */ UNIV_INLINE @@ -111,42 +58,6 @@ dfield_set_len( field->len = static_cast(len); } -/*********************************************************************//** -Determines if a field is SQL NULL -@return nonzero if SQL null data */ -UNIV_INLINE -ulint -dfield_is_null( -/*===========*/ - const dfield_t* field) /*!< in: field */ -{ - return(field->len == UNIV_SQL_NULL); -} - -/*********************************************************************//** -Determines if a field is externally stored -@return nonzero if externally stored */ -UNIV_INLINE -ulint -dfield_is_ext( -/*==========*/ - const dfield_t* field) /*!< in: field */ -{ - ut_ad(!field->ext || field->len >= BTR_EXTERN_FIELD_REF_SIZE); - return(field->ext); -} - -/*********************************************************************//** -Sets the "external storage" flag */ -UNIV_INLINE -void -dfield_set_ext( -/*===========*/ - dfield_t* field) /*!< in/out: field */ -{ - field->ext = 1; -} - /** Gets spatial status for "external storage" @param[in,out] field field */ UNIV_INLINE @@ -366,63 +277,6 @@ dtuple_set_n_fields_cmp( tuple->n_fields_cmp = n_fields_cmp; } -/*********************************************************************//** -Gets number of fields in a data tuple. -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_fields( -/*================*/ - const dtuple_t* tuple) /*!< in: tuple */ -{ - return(tuple->n_fields); -} - -/** Gets the number of virtual fields in a data tuple. -@param[in] tuple dtuple to check -@return number of fields */ -UNIV_INLINE -ulint -dtuple_get_n_v_fields( - const dtuple_t* tuple) -{ - ut_ad(tuple); - - return(tuple->n_v_fields); -} -#ifdef UNIV_DEBUG -/** Gets nth field of a tuple. -@param[in] tuple tuple -@param[in] n index of field -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_field( - const dtuple_t* tuple, - ulint n) -{ - ut_ad(tuple); - ut_ad(n < tuple->n_fields); - - return((dfield_t*) tuple->fields + n); -} -/** Gets nth virtual field of a tuple. -@param[in] tuple tuple -@oaran[in] n the nth field to get -@return nth field */ -UNIV_INLINE -dfield_t* -dtuple_get_nth_v_field( - const dtuple_t* tuple, - ulint n) -{ - ut_ad(tuple); - ut_ad(n < tuple->n_v_fields); - - return(static_cast(tuple->v_fields + n)); -} -#endif /* UNIV_DEBUG */ - /** Creates a data tuple from an already allocated chunk of memory. The size of the chunk must be at least DTUPLE_EST_ALLOC(n_fields). The default value for number of fields used in record comparisons @@ -487,12 +341,10 @@ dtuple_create_from_mem( /** Duplicate the virtual field data in a dtuple_t @param[in,out] vrow dtuple contains the virtual fields -@param[in] heap heap memory to use */ +@param[in,out] heap heap memory to use */ UNIV_INLINE void -dtuple_dup_v_fld( - const dtuple_t* vrow, - mem_heap_t* heap) +dtuple_dup_v_fld(dtuple_t* vrow, mem_heap_t* heap) { for (ulint i = 0; i < vrow->n_v_fields; i++) { dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); @@ -504,8 +356,7 @@ dtuple_dup_v_fld( @param[in,out] vrow dtuple contains the virtual fields */ UNIV_INLINE void -dtuple_init_v_fld( - const dtuple_t* vrow) +dtuple_init_v_fld(dtuple_t* vrow) { for (ulint i = 0; i < vrow->n_v_fields; i++) { dfield_t* dfield = dtuple_get_nth_v_field(vrow, i); diff --git a/storage/innobase/include/gis0geo.h b/storage/innobase/include/gis0geo.h index 08895af545e..9a5d426cd7c 100644 --- a/storage/innobase/include/gis0geo.h +++ b/storage/innobase/include/gis0geo.h @@ -1,5 +1,6 @@ /***************************************************************************** Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. +Copyright (c) 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -73,7 +74,7 @@ stored in "well-known binary representation" (wkb) format. int rtree_mbr_from_wkb( /*===============*/ - uchar* wkb, /*!< in: pointer to wkb. */ + const uchar* wkb, /*!< in: pointer to wkb. */ uint size, /*!< in: size of wkb. */ uint n_dims, /*!< in: dimensions. */ double* mbr); /*!< in/out: mbr. */ diff --git a/storage/innobase/include/rem0cmp.ic b/storage/innobase/include/rem0cmp.ic index 290c1455f27..9ba61ca1f94 100644 --- a/storage/innobase/include/rem0cmp.ic +++ b/storage/innobase/include/rem0cmp.ic @@ -127,10 +127,10 @@ cmp_dfield_dfield_like_prefix( if (CHARSET_INFO* cs = get_charset(cs_num, MYF(MY_WME))) { return(cs->coll->strnncoll( cs, - static_cast( + static_cast( dfield_get_data(dfield1)), dfield_get_len(dfield1), - static_cast( + static_cast( dfield_get_data(dfield2)), dfield_get_len(dfield2), 1)); diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 5dd34f5679b..29dc9c120a7 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -858,7 +858,7 @@ void innobase_free_row_for_vcol(VCOL_STORAGE *storage); @return the field filled with computed value */ dfield_t* innobase_get_computed_value( - const dtuple_t* row, + dtuple_t* row, const dict_v_col_t* col, const dict_index_t* index, mem_heap_t** local_heap, diff --git a/storage/innobase/include/row0vers.h b/storage/innobase/include/row0vers.h index ac03478e083..a6dd14f8fd8 100644 --- a/storage/innobase/include/row0vers.h +++ b/storage/innobase/include/row0vers.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -124,7 +124,7 @@ row_vers_build_for_consistent_read( if the history is missing or the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t**vrow); /*!< out: reports virtual column info if any */ + dtuple_t** vrow); /*!< out: reports virtual column info if any */ /*****************************************************************//** Constructs the last committed version of a clustered index record, @@ -149,7 +149,7 @@ row_vers_build_for_semi_consistent_read( const rec_t** old_vers,/*!< out: rec, old version, or NULL if the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t**vrow); /*!< out: holds virtual column info if any + dtuple_t** vrow); /*!< out: holds virtual column info if any is updated in the view */ #endif diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h index ea6269b5ba4..99cebc36522 100644 --- a/storage/innobase/include/trx0rec.h +++ b/storage/innobase/include/trx0rec.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -250,7 +250,7 @@ trx_undo_prev_version_build( dtuple if it is not yet created. This heap diffs from "heap" above in that it could be prebuilt->old_vers_heap for selection */ - const dtuple_t**vrow, /*!< out: virtual column info, if any */ + dtuple_t** vrow, /*!< out: virtual column info, if any */ ulint v_status); /*!< in: status determine if it is going into this function by purge thread or not. @@ -299,7 +299,7 @@ void trx_undo_read_v_cols( const dict_table_t* table, const byte* ptr, - const dtuple_t* row, + dtuple_t* row, bool in_purge); /** Read virtual column index from undo log if the undo log contains such diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index ed80696a742..8b153e28bed 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -838,9 +838,7 @@ rec_get_converted_size_comp_prefix_low( col = dict_field_get_col(field); #ifdef UNIV_DEBUG - dtype_t* type; - - type = dfield_get_type(&fields[i]); + const dtype_t* type = dfield_get_type(&fields[i]); if (dict_index_is_spatial(index)) { if (DATA_GEOMETRY_MTYPE(col->mtype) && i == 0) { ut_ad(type->prtype & DATA_GIS_MBR); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index 8bfef78cd8c..59d46d86aab 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -3327,14 +3327,14 @@ row_ins_spatial_index_entry_set_mbr_field( dfield_t* field, /*!< in/out: mbr field */ const dfield_t* row_field) /*!< in: row field */ { - uchar* dptr = NULL; ulint dlen = 0; double mbr[SPDIMS * 2]; /* This must be a GEOMETRY datatype */ ut_ad(DATA_GEOMETRY_MTYPE(field->type.mtype)); - dptr = static_cast(dfield_get_data(row_field)); + const byte* dptr = static_cast( + dfield_get_data(row_field)); dlen = dfield_get_len(row_field); /* obtain the MBR */ diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 3447ade7606..e1ef6983073 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -453,7 +453,7 @@ row_merge_buf_redundant_convert( ut_ad(field_len <= len); if (row_field->ext) { - const byte* field_data = static_cast( + const byte* field_data = static_cast( dfield_get_data(row_field)); ulint ext_len; @@ -483,7 +483,7 @@ row_merge_buf_redundant_convert( @param[in] old_table original table @param[in] new_table new table @param[in,out] psort_info parallel sort info -@param[in] row table row +@param[in,out] row table row @param[in] ext cache of externally stored column prefixes, or NULL @param[in,out] doc_id Doc ID if we are creating @@ -505,7 +505,7 @@ row_merge_buf_add( const dict_table_t* old_table, const dict_table_t* new_table, fts_psort_t* psort_info, - const dtuple_t* row, + dtuple_t* row, const row_ext_t* ext, doc_id_t* doc_id, mem_heap_t* conv_heap, @@ -642,7 +642,7 @@ row_merge_buf_add( row, index->table->fts->doc_col); *doc_id = (doc_id_t) mach_read_from_8( - static_cast( + static_cast( dfield_get_data(doc_field))); if (*doc_id == 0) { @@ -1904,7 +1904,7 @@ row_merge_read_clustered_index( const rec_t* rec; ulint* offsets; - const dtuple_t* row; + dtuple_t* row; row_ext_t* ext; page_cur_t* cur = btr_pcur_get_page_cur(&pcur); @@ -2154,9 +2154,8 @@ end_of_index: ut_ad(add_autoinc < dict_table_get_n_user_cols(new_table)); - const dfield_t* dfield; - - dfield = dtuple_get_nth_field(row, add_autoinc); + dfield_t* dfield = dtuple_get_nth_field(row, + add_autoinc); if (dfield_is_null(dfield)) { goto write_buffers; } diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index 687eab903f8..55893589f85 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -95,7 +95,7 @@ row_build_index_entry_low( const dict_col_t* col; ulint col_no = 0; dfield_t* dfield; - dfield_t* dfield2; + const dfield_t* dfield2; ulint len; if (i >= entry_len) { @@ -162,7 +162,7 @@ row_build_index_entry_low( dfield_set_data(dfield, mbr, mbr_len); if (dfield2->data) { - uchar* dptr = NULL; + const uchar* dptr = NULL; ulint dlen = 0; ulint flen = 0; double tmp_mbr[SPDIMS * 2]; @@ -170,7 +170,7 @@ row_build_index_entry_low( if (dfield_is_ext(dfield2)) { if (flag == ROW_BUILD_FOR_PURGE) { - byte* ptr = NULL; + const byte* ptr = NULL; spatial_status_t spatial_status; spatial_status = @@ -179,7 +179,7 @@ row_build_index_entry_low( switch (spatial_status) { case SPATIAL_ONLY: - ptr = static_cast( + ptr = static_cast( dfield_get_data( dfield2)); ut_ad(dfield_get_len(dfield2) @@ -187,7 +187,7 @@ row_build_index_entry_low( break; case SPATIAL_MIXED: - ptr = static_cast( + ptr = static_cast( dfield_get_data( dfield2)) + dfield_get_len( @@ -216,13 +216,13 @@ row_build_index_entry_low( flen = BTR_EXTERN_FIELD_REF_SIZE; ut_ad(dfield_get_len(dfield2) >= BTR_EXTERN_FIELD_REF_SIZE); - dptr = static_cast( + dptr = static_cast( dfield_get_data(dfield2)) + dfield_get_len(dfield2) - BTR_EXTERN_FIELD_REF_SIZE; } else { flen = dfield_get_len(dfield2); - dptr = static_cast( + dptr = static_cast( dfield_get_data(dfield2)); } @@ -240,7 +240,7 @@ row_build_index_entry_low( flen, temp_heap); } else { - dptr = static_cast( + dptr = static_cast( dfield_get_data(dfield2)); dlen = dfield_get_len(dfield2); diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 6f9e903623c..37918477c44 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -222,7 +222,6 @@ row_sel_sec_rec_is_for_clust_rec( reconstructed from base column in cluster index */ if (is_virtual) { const dict_v_col_t* v_col; - const dtuple_t* row; dfield_t* vfield; row_ext_t* ext; @@ -239,10 +238,11 @@ row_sel_sec_rec_is_for_clust_rec( v_col = reinterpret_cast(col); - row = row_build(ROW_COPY_POINTERS, - clust_index, clust_rec, - clust_offs, - NULL, NULL, NULL, &ext, heap); + dtuple_t* row = row_build( + ROW_COPY_POINTERS, + clust_index, clust_rec, + clust_offs, + NULL, NULL, NULL, &ext, heap); vfield = innobase_get_computed_value( row, v_col, clust_index, @@ -804,7 +804,7 @@ row_sel_build_committed_vers_for_mysql( record does not exist in the view: i.e., it was freshly inserted afterwards */ - const dtuple_t**vrow, /*!< out: to be filled with old virtual + dtuple_t** vrow, /*!< out: to be filled with old virtual column version if any */ mtr_t* mtr) /*!< in: mtr */ { @@ -3291,7 +3291,7 @@ row_sel_build_prev_vers_for_mysql( record does not exist in the view: i.e., it was freshly inserted afterwards */ - const dtuple_t**vrow, /*!< out: dtuple to hold old virtual + dtuple_t** vrow, /*!< out: dtuple to hold old virtual column data */ mtr_t* mtr) /*!< in: mtr */ { @@ -3335,7 +3335,7 @@ row_sel_get_clust_rec_for_mysql( rec_get_offsets(out_rec, clust_index) */ mem_heap_t** offset_heap,/*!< in/out: memory heap from which the offsets are allocated */ - const dtuple_t**vrow, /*!< out: virtual column to fill */ + dtuple_t** vrow, /*!< out: virtual column to fill */ mtr_t* mtr) /*!< in: mtr used to get access to the non-clustered record; the same mtr is used to access the clustered index */ @@ -4038,7 +4038,7 @@ void row_sel_fill_vrow( const rec_t* rec, dict_index_t* index, - const dtuple_t** vrow, + dtuple_t** vrow, mem_heap_t* heap) { ulint offsets_[REC_OFFS_NORMAL_SIZE]; @@ -4230,7 +4230,7 @@ row_search_mvcc( dict_index_t* clust_index; que_thr_t* thr; const rec_t* rec; - const dtuple_t* vrow = NULL; + dtuple_t* vrow = NULL; const rec_t* result_rec = NULL; const rec_t* clust_rec; dberr_t err = DB_SUCCESS; diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 7e4b512ca27..d16f7cfad4e 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -856,7 +856,7 @@ row_upd_index_write_log( mlog_catenate_string( mtr, - static_cast( + static_cast( dfield_get_data(new_val)), len); @@ -1052,8 +1052,6 @@ row_upd_build_difference_binary( dberr_t* error) { upd_field_t* upd_field; - dfield_t* dfield; - const byte* data; ulint len; upd_t* update; ulint n_diff; @@ -1084,10 +1082,8 @@ row_upd_build_difference_binary( } for (i = 0; i < n_fld; i++) { - - data = rec_get_nth_field(rec, offsets, i, &len); - - dfield = dtuple_get_nth_field(entry, i); + const byte* data = rec_get_nth_field(rec, offsets, i, &len); + const dfield_t* dfield = dtuple_get_nth_field(entry, i); /* NOTE: we compare the fields as binary strings! (No collation) */ @@ -1155,8 +1151,6 @@ row_upd_build_difference_binary( index->table, NULL, NULL, &ext, heap); } - dfield = dtuple_get_nth_v_field(entry, i); - dfield_t* vfield = innobase_get_computed_value( update->old_vrow, col, index, &v_heap, heap, NULL, thd, mysql_table, record, @@ -1167,6 +1161,9 @@ row_upd_build_difference_binary( return(NULL); } + const dfield_t* dfield = dtuple_get_nth_v_field( + entry, i); + if (!dfield_data_is_binary_equal( dfield, vfield->len, static_cast(vfield->data))) { @@ -1771,7 +1768,7 @@ row_upd_changes_ord_field_binary_func( double mbr2[SPDIMS * 2]; rtr_mbr_t* old_mbr; rtr_mbr_t* new_mbr; - uchar* dptr = NULL; + const uchar* dptr = NULL; ulint flen = 0; ulint dlen = 0; mem_heap_t* temp_heap = NULL; @@ -1792,7 +1789,7 @@ row_upd_changes_ord_field_binary_func( /* For off-page stored data, we need to read the whole field data. */ flen = dfield_get_len(dfield); - dptr = static_cast( + dptr = static_cast( dfield_get_data(dfield)); temp_heap = mem_heap_create(1000); @@ -1802,7 +1799,7 @@ row_upd_changes_ord_field_binary_func( flen, temp_heap); } else { - dptr = static_cast(dfield->data); + dptr = static_cast(dfield->data); dlen = dfield->len; } @@ -1822,13 +1819,13 @@ row_upd_changes_ord_field_binary_func( flen = BTR_EXTERN_FIELD_REF_SIZE; ut_ad(dfield_get_len(new_field) >= BTR_EXTERN_FIELD_REF_SIZE); - dptr = static_cast( + dptr = static_cast( dfield_get_data(new_field)) + dfield_get_len(new_field) - BTR_EXTERN_FIELD_REF_SIZE; } else { flen = dfield_get_len(new_field); - dptr = static_cast( + dptr = static_cast( dfield_get_data(new_field)); } @@ -1842,7 +1839,8 @@ row_upd_changes_ord_field_binary_func( flen, temp_heap); } else { - dptr = static_cast(upd_field->new_val.data); + dptr = static_cast( + upd_field->new_val.data); dlen = upd_field->new_val.len; } rtree_mbr_from_wkb(dptr + GEO_DATA_HEADER_SIZE, @@ -1900,7 +1898,7 @@ row_upd_changes_ord_field_binary_func( ut_a(dict_index_is_clust(index) || ind_field->prefix_len <= dfield_len); - buf = static_cast(dfield_get_data(dfield)); + buf= static_cast(dfield_get_data(dfield)); copy_dfield: ut_a(dfield_len > 0); dfield_copy(&dfield_ext, dfield); diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 30aa44dcb33..a099efc826c 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -98,7 +98,7 @@ row_vers_impl_x_locked_low( mem_heap_t* heap; dtuple_t* ientry = NULL; mem_heap_t* v_heap = NULL; - const dtuple_t* cur_vrow = NULL; + dtuple_t* cur_vrow = NULL; DBUG_ENTER("row_vers_impl_x_locked_low"); @@ -165,7 +165,7 @@ row_vers_impl_x_locked_low( ulint vers_del; trx_id_t prev_trx_id; mem_heap_t* old_heap = heap; - const dtuple_t* vrow = NULL; + dtuple_t* vrow = NULL; /* We keep the semaphore in mtr on the clust_rec page, so that no other transaction can update it and get an @@ -519,7 +519,7 @@ row_vers_build_cur_vrow_low( roll_ptr_t roll_ptr, trx_id_t trx_id, mem_heap_t* v_heap, - const dtuple_t** vrow, + dtuple_t** vrow, mtr_t* mtr) { const rec_t* version; @@ -636,7 +636,7 @@ row_vers_vc_matches_cluster( roll_ptr_t roll_ptr, trx_id_t trx_id, mem_heap_t* v_heap, - const dtuple_t**vrow, + dtuple_t** vrow, mtr_t* mtr) { const rec_t* version; @@ -801,7 +801,7 @@ func_exit: @param[in,out] vcol_info virtual column information for purge thread @return dtuple contains virtual column data */ static -const dtuple_t* +dtuple_t* row_vers_build_cur_vrow( bool in_purge, const rec_t* rec, @@ -816,7 +816,7 @@ row_vers_build_cur_vrow( mtr_t* mtr, purge_vcol_info_t* vcol_info) { - const dtuple_t* cur_vrow = NULL; + dtuple_t* cur_vrow = NULL; roll_ptr_t t_roll_ptr = row_get_rec_roll_ptr( rec, clust_index, *clust_offsets); @@ -897,9 +897,9 @@ row_vers_old_has_index_entry( dtuple_t* row; const dtuple_t* entry; ulint comp; - const dtuple_t* vrow = NULL; + dtuple_t* vrow = NULL; mem_heap_t* v_heap = NULL; - const dtuple_t* cur_vrow = NULL; + dtuple_t* cur_vrow = NULL; ut_ad(mtr_memo_contains_page_flagged(mtr, rec, MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_S_FIX)); @@ -1162,7 +1162,7 @@ row_vers_build_for_consistent_read( if the history is missing or the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t**vrow) /*!< out: virtual row */ + dtuple_t** vrow) /*!< out: virtual row */ { const rec_t* version; rec_t* prev_version; @@ -1275,7 +1275,7 @@ row_vers_build_for_semi_consistent_read( const rec_t** old_vers,/*!< out: rec, old version, or NULL if the record does not exist in the view, that is, it was freshly inserted afterwards */ - const dtuple_t** vrow) /*!< out: virtual row, old version, or NULL + dtuple_t** vrow) /*!< out: virtual row, old version, or NULL if it is not updated in the view */ { const rec_t* version; diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 5c8b2f9441f..7695e35fb7a 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -388,8 +388,6 @@ trx_undo_report_insert_virtual( for (ulint col_no = 0; col_no < dict_table_get_n_v_cols(table); col_no++) { - dfield_t* vfield = NULL; - const dict_v_col_t* col = dict_table_get_nth_v_col(table, col_no); @@ -412,7 +410,8 @@ trx_undo_report_insert_virtual( return(false); } - vfield = dtuple_get_nth_v_field(row, col->v_pos); + const dfield_t* vfield = dtuple_get_nth_v_field( + row, col->v_pos); ulint flen = vfield->len; if (flen != UNIV_SQL_NULL) { @@ -1331,8 +1330,6 @@ already_logged: for (col_no = 0; col_no < dict_table_get_n_v_cols(table); col_no++) { - dfield_t* vfield = NULL; - const dict_v_col_t* col = dict_table_get_nth_v_col(table, col_no); @@ -1362,6 +1359,8 @@ already_logged: return(0); } + const dfield_t* vfield = NULL; + if (update) { ut_ad(!row); if (update->old_vrow == NULL) { @@ -2300,7 +2299,7 @@ trx_undo_prev_version_build( dtuple if it is not yet created. This heap diffs from "heap" above in that it could be prebuilt->old_vers_heap for selection */ - const dtuple_t**vrow, /*!< out: virtual column info, if any */ + dtuple_t** vrow, /*!< out: virtual column info, if any */ ulint v_status) /*!< in: status determine if it is going into this function by purge thread or not. @@ -2503,7 +2502,7 @@ void trx_undo_read_v_cols( const dict_table_t* table, const byte* ptr, - const dtuple_t* row, + dtuple_t* row, bool in_purge) { const byte* end_ptr;