summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
Diffstat (limited to 'storage')
-rw-r--r--storage/archive/azio.c5
-rw-r--r--storage/archive/ha_archive.cc30
-rw-r--r--storage/archive/ha_archive.h11
-rw-r--r--storage/blackhole/ha_blackhole.cc2
-rw-r--r--storage/blackhole/ha_blackhole.h4
-rw-r--r--storage/cassandra/ha_cassandra.cc2
-rw-r--r--storage/cassandra/ha_cassandra.h2
-rw-r--r--storage/connect/array.cpp2
-rw-r--r--storage/connect/colblk.cpp3
-rw-r--r--storage/connect/connect.cc2
-rw-r--r--storage/connect/filamap.cpp3
-rw-r--r--storage/connect/filamdbf.cpp3
-rw-r--r--storage/connect/filamfix.cpp2
-rw-r--r--storage/connect/filamgz.cpp7
-rw-r--r--storage/connect/filamtxt.cpp3
-rw-r--r--storage/connect/filamvct.cpp5
-rw-r--r--storage/connect/filamzip.cpp2
-rw-r--r--storage/connect/filter.cpp6
-rw-r--r--storage/connect/fmdlex.c14
-rw-r--r--storage/connect/ha_connect.cc106
-rw-r--r--storage/connect/ha_connect.h6
-rw-r--r--storage/connect/inihandl.cpp3
-rw-r--r--storage/connect/json.cpp2
-rw-r--r--storage/connect/jsonudf.cpp32
-rw-r--r--storage/connect/libdoc.cpp68
-rw-r--r--storage/connect/maputil.cpp2
-rw-r--r--storage/connect/myconn.cpp2
-rw-r--r--storage/connect/mysql-test/connect/r/mysql_index.result319
-rw-r--r--storage/connect/mysql-test/connect/r/part_file.result9
-rw-r--r--storage/connect/mysql-test/connect/r/xml2_mult.result2
-rw-r--r--storage/connect/mysql-test/connect/r/xml_mult.result2
-rw-r--r--storage/connect/mysql-test/connect/t/mysql_index.test16
-rw-r--r--storage/connect/mysql-test/connect/t/part_file.test4
-rw-r--r--storage/connect/myutil.cpp4
-rw-r--r--storage/connect/plgdbutl.cpp2
-rw-r--r--storage/connect/plugutil.cpp38
-rw-r--r--storage/connect/reldef.cpp4
-rw-r--r--storage/connect/tabdos.cpp28
-rw-r--r--storage/connect/tabext.cpp6
-rw-r--r--storage/connect/tabfmt.cpp21
-rw-r--r--storage/connect/tabjson.cpp13
-rw-r--r--storage/connect/tabmul.cpp10
-rw-r--r--storage/connect/tabmysql.cpp5
-rw-r--r--storage/connect/taboccur.cpp6
-rw-r--r--storage/connect/tabpivot.cpp9
-rw-r--r--storage/connect/tabvir.cpp19
-rw-r--r--storage/connect/tabxcl.cpp3
-rw-r--r--storage/connect/tabxml.cpp26
-rw-r--r--storage/connect/user_connect.cc2
-rw-r--r--storage/connect/user_connect.h2
-rw-r--r--storage/connect/valblk.cpp2
-rw-r--r--storage/connect/value.cpp3
-rw-r--r--storage/connect/xindex.cpp7
-rw-r--r--storage/connect/zip.c16
-rw-r--r--storage/csv/ha_tina.cc34
-rw-r--r--storage/csv/ha_tina.h4
-rw-r--r--storage/example/ha_example.cc2
-rw-r--r--storage/example/ha_example.h2
-rw-r--r--storage/federated/ha_federated.cc2
-rw-r--r--storage/federated/ha_federated.h3
-rw-r--r--storage/federatedx/TODO30
-rw-r--r--storage/federatedx/federatedx_pushdown.cc304
-rw-r--r--storage/federatedx/federatedx_pushdown.h63
-rw-r--r--storage/federatedx/ha_federatedx.cc23
-rw-r--r--storage/federatedx/ha_federatedx.h13
-rw-r--r--storage/heap/ha_heap.cc2
-rw-r--r--storage/heap/ha_heap.h11
-rw-r--r--storage/innobase/CMakeLists.txt4
-rw-r--r--storage/innobase/btr/btr0btr.cc548
-rw-r--r--storage/innobase/btr/btr0bulk.cc27
-rw-r--r--storage/innobase/btr/btr0cur.cc736
-rw-r--r--storage/innobase/btr/btr0defragment.cc33
-rw-r--r--storage/innobase/btr/btr0pcur.cc38
-rw-r--r--storage/innobase/btr/btr0scrub.cc36
-rw-r--r--storage/innobase/btr/btr0sea.cc28
-rw-r--r--storage/innobase/buf/buf0buf.cc772
-rw-r--r--storage/innobase/buf/buf0checksum.cc36
-rw-r--r--storage/innobase/buf/buf0dblwr.cc186
-rw-r--r--storage/innobase/buf/buf0dump.cc12
-rw-r--r--storage/innobase/buf/buf0flu.cc271
-rw-r--r--storage/innobase/buf/buf0lru.cc72
-rw-r--r--storage/innobase/buf/buf0rea.cc116
-rw-r--r--storage/innobase/data/data0data.cc68
-rw-r--r--storage/innobase/data/data0type.cc66
-rw-r--r--storage/innobase/dict/dict0boot.cc80
-rw-r--r--storage/innobase/dict/dict0crea.cc245
-rw-r--r--storage/innobase/dict/dict0defrag_bg.cc24
-rw-r--r--storage/innobase/dict/dict0dict.cc1104
-rw-r--r--storage/innobase/dict/dict0load.cc79
-rw-r--r--storage/innobase/dict/dict0mem.cc431
-rw-r--r--storage/innobase/dict/dict0stats.cc198
-rw-r--r--storage/innobase/dict/dict0stats_bg.cc28
-rw-r--r--storage/innobase/fil/fil0crypt.cc413
-rw-r--r--storage/innobase/fil/fil0fil.cc667
-rw-r--r--storage/innobase/fil/fil0pagecompress.cc540
-rw-r--r--storage/innobase/fsp/fsp0file.cc79
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc607
-rw-r--r--storage/innobase/fsp/fsp0space.cc14
-rw-r--r--storage/innobase/fsp/fsp0sysspace.cc2
-rw-r--r--storage/innobase/fts/fts0config.cc4
-rw-r--r--storage/innobase/fts/fts0fts.cc105
-rw-r--r--storage/innobase/fts/fts0opt.cc10
-rw-r--r--storage/innobase/fts/fts0que.cc8
-rw-r--r--storage/innobase/fts/fts0sql.cc22
-rw-r--r--storage/innobase/fut/fut0lst.cc68
-rw-r--r--storage/innobase/gis/gis0rtree.cc10
-rw-r--r--storage/innobase/gis/gis0sea.cc46
-rw-r--r--storage/innobase/ha/ha0ha.cc20
-rw-r--r--storage/innobase/handler/ha_innodb.cc1256
-rw-r--r--storage/innobase/handler/ha_innodb.h257
-rw-r--r--storage/innobase/handler/handler0alter.cc3279
-rw-r--r--storage/innobase/handler/i_s.cc172
-rw-r--r--storage/innobase/ibuf/ibuf0ibuf.cc394
-rw-r--r--storage/innobase/include/btr0btr.h88
-rw-r--r--storage/innobase/include/btr0btr.ic7
-rw-r--r--storage/innobase/include/btr0bulk.h6
-rw-r--r--storage/innobase/include/btr0cur.h18
-rw-r--r--storage/innobase/include/btr0defragment.h6
-rw-r--r--storage/innobase/include/btr0sea.h2
-rw-r--r--storage/innobase/include/btr0types.h34
-rw-r--r--storage/innobase/include/buf0buddy.h5
-rw-r--r--storage/innobase/include/buf0buddy.ic10
-rw-r--r--storage/innobase/include/buf0buf.h266
-rw-r--r--storage/innobase/include/buf0buf.ic81
-rw-r--r--storage/innobase/include/buf0checksum.h15
-rw-r--r--storage/innobase/include/buf0flu.h29
-rw-r--r--storage/innobase/include/buf0flu.ic79
-rw-r--r--storage/innobase/include/buf0rea.h37
-rw-r--r--storage/innobase/include/buf0types.h17
-rw-r--r--storage/innobase/include/data0data.h27
-rw-r--r--storage/innobase/include/data0type.h115
-rw-r--r--storage/innobase/include/data0type.ic12
-rw-r--r--storage/innobase/include/db0err.h2
-rw-r--r--storage/innobase/include/dict0boot.h14
-rw-r--r--storage/innobase/include/dict0boot.ic8
-rw-r--r--storage/innobase/include/dict0crea.h29
-rw-r--r--storage/innobase/include/dict0dict.h476
-rw-r--r--storage/innobase/include/dict0dict.ic238
-rw-r--r--storage/innobase/include/dict0load.h2
-rw-r--r--storage/innobase/include/dict0mem.h612
-rw-r--r--storage/innobase/include/dict0priv.h12
-rw-r--r--storage/innobase/include/dict0priv.ic41
-rw-r--r--storage/innobase/include/dict0stats.h13
-rw-r--r--storage/innobase/include/dict0stats.ic12
-rw-r--r--storage/innobase/include/dict0stats_bg.h4
-rw-r--r--storage/innobase/include/dict0types.h1
-rw-r--r--storage/innobase/include/fil0crypt.h63
-rw-r--r--storage/innobase/include/fil0fil.h488
-rw-r--r--storage/innobase/include/fil0fil.ic42
-rw-r--r--storage/innobase/include/fil0pagecompress.h18
-rw-r--r--storage/innobase/include/fsp0file.h8
-rw-r--r--storage/innobase/include/fsp0fsp.h136
-rw-r--r--storage/innobase/include/fsp0fsp.ic74
-rw-r--r--storage/innobase/include/fsp0pagecompress.h11
-rw-r--r--storage/innobase/include/fsp0space.h2
-rw-r--r--storage/innobase/include/fsp0sysspace.h2
-rw-r--r--storage/innobase/include/fsp0types.h129
-rw-r--r--storage/innobase/include/fts0fts.h20
-rw-r--r--storage/innobase/include/fts0priv.h4
-rw-r--r--storage/innobase/include/fut0fut.h29
-rw-r--r--storage/innobase/include/fut0fut.ic68
-rw-r--r--storage/innobase/include/fut0lst.h62
-rw-r--r--storage/innobase/include/fut0lst.ic34
-rw-r--r--storage/innobase/include/gis0type.h17
-rw-r--r--storage/innobase/include/ha_prototypes.h12
-rw-r--r--storage/innobase/include/ib0mutex.h130
-rw-r--r--storage/innobase/include/ibuf0ibuf.h87
-rw-r--r--storage/innobase/include/ibuf0ibuf.ic56
-rw-r--r--storage/innobase/include/log0crypt.h19
-rw-r--r--storage/innobase/include/log0log.h96
-rw-r--r--storage/innobase/include/log0log.ic12
-rw-r--r--storage/innobase/include/log0recv.h67
-rw-r--r--storage/innobase/include/mach0data.h16
-rw-r--r--storage/innobase/include/mach0data.ic27
-rw-r--r--storage/innobase/include/mtr0log.h20
-rw-r--r--storage/innobase/include/mtr0mtr.h11
-rw-r--r--storage/innobase/include/mtr0mtr.ic20
-rw-r--r--storage/innobase/include/mtr0types.h13
-rw-r--r--storage/innobase/include/os0api.h20
-rw-r--r--storage/innobase/include/os0file.h48
-rw-r--r--storage/innobase/include/os0once.h120
-rw-r--r--storage/innobase/include/os0proc.h2
-rw-r--r--storage/innobase/include/os0thread.h2
-rw-r--r--storage/innobase/include/page0cur.ic6
-rw-r--r--storage/innobase/include/page0page.h48
-rw-r--r--storage/innobase/include/page0page.ic31
-rw-r--r--storage/innobase/include/page0size.h197
-rw-r--r--storage/innobase/include/page0types.h12
-rw-r--r--storage/innobase/include/page0zip.h48
-rw-r--r--storage/innobase/include/page0zip.ic33
-rw-r--r--storage/innobase/include/que0que.h6
-rw-r--r--storage/innobase/include/read0types.h34
-rw-r--r--storage/innobase/include/rem0rec.h173
-rw-r--r--storage/innobase/include/rem0rec.ic32
-rw-r--r--storage/innobase/include/row0ext.h9
-rw-r--r--storage/innobase/include/row0ftsort.h26
-rw-r--r--storage/innobase/include/row0log.h2
-rw-r--r--storage/innobase/include/row0mysql.h15
-rw-r--r--storage/innobase/include/row0row.h19
-rw-r--r--storage/innobase/include/row0row.ic8
-rw-r--r--storage/innobase/include/row0trunc.h416
-rw-r--r--storage/innobase/include/row0types.h8
-rw-r--r--storage/innobase/include/row0undo.h15
-rw-r--r--storage/innobase/include/row0upd.h34
-rw-r--r--storage/innobase/include/row0upd.ic8
-rw-r--r--storage/innobase/include/srv0mon.h2
-rw-r--r--storage/innobase/include/srv0srv.h28
-rw-r--r--storage/innobase/include/sync0arr.ic3
-rw-r--r--storage/innobase/include/sync0policy.h522
-rw-r--r--storage/innobase/include/sync0policy.ic101
-rw-r--r--storage/innobase/include/sync0rw.h8
-rw-r--r--storage/innobase/include/sync0rw.ic87
-rw-r--r--storage/innobase/include/sync0types.h77
-rw-r--r--storage/innobase/include/trx0purge.h247
-rw-r--r--storage/innobase/include/trx0roll.h10
-rw-r--r--storage/innobase/include/trx0rseg.ic5
-rw-r--r--storage/innobase/include/trx0sys.h93
-rw-r--r--storage/innobase/include/trx0trx.h31
-rw-r--r--storage/innobase/include/trx0undo.h62
-rw-r--r--storage/innobase/include/trx0undo.ic39
-rw-r--r--storage/innobase/include/univ.i1
-rw-r--r--storage/innobase/include/ut0counter.h136
-rw-r--r--storage/innobase/include/ut0crc32.h6
-rw-r--r--storage/innobase/include/ut0mutex.h2
-rw-r--r--storage/innobase/include/ut0rnd.h9
-rw-r--r--storage/innobase/include/ut0ut.h13
-rw-r--r--storage/innobase/innodb.cmake6
-rw-r--r--storage/innobase/lock/lock0lock.cc106
-rw-r--r--storage/innobase/lock/lock0wait.cc4
-rw-r--r--storage/innobase/log/log0crypt.cc170
-rw-r--r--storage/innobase/log/log0log.cc73
-rw-r--r--storage/innobase/log/log0recv.cc1073
-rw-r--r--storage/innobase/mtr/mtr0log.cc126
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc11
-rw-r--r--storage/innobase/os/os0event.cc2
-rw-r--r--storage/innobase/os/os0file.cc517
-rw-r--r--storage/innobase/os/os0proc.cc21
-rw-r--r--storage/innobase/os/os0thread.cc8
-rw-r--r--storage/innobase/page/page0cur.cc31
-rw-r--r--storage/innobase/page/page0page.cc61
-rw-r--r--storage/innobase/page/page0zip.cc173
-rw-r--r--storage/innobase/pars/pars0pars.cc2
-rw-r--r--storage/innobase/pars/pars0sym.cc2
-rw-r--r--storage/innobase/que/que0que.cc14
-rw-r--r--storage/innobase/read/read0read.cc10
-rw-r--r--storage/innobase/rem/rem0cmp.cc2
-rw-r--r--storage/innobase/rem/rem0rec.cc540
-rw-r--r--storage/innobase/row/row0ext.cc32
-rw-r--r--storage/innobase/row/row0ftsort.cc32
-rw-r--r--storage/innobase/row/row0import.cc295
-rw-r--r--storage/innobase/row/row0ins.cc157
-rw-r--r--storage/innobase/row/row0log.cc104
-rw-r--r--storage/innobase/row/row0merge.cc49
-rw-r--r--storage/innobase/row/row0mysql.cc64
-rw-r--r--storage/innobase/row/row0purge.cc56
-rw-r--r--storage/innobase/row/row0quiesce.cc22
-rw-r--r--storage/innobase/row/row0row.cc397
-rw-r--r--storage/innobase/row/row0sel.cc203
-rw-r--r--storage/innobase/row/row0trunc.cc1742
-rw-r--r--storage/innobase/row/row0uins.cc238
-rw-r--r--storage/innobase/row/row0umod.cc196
-rw-r--r--storage/innobase/row/row0undo.cc196
-rw-r--r--storage/innobase/row/row0upd.cc213
-rw-r--r--storage/innobase/srv/srv0conc.cc34
-rw-r--r--storage/innobase/srv/srv0mon.cc20
-rw-r--r--storage/innobase/srv/srv0srv.cc144
-rw-r--r--storage/innobase/srv/srv0start.cc230
-rw-r--r--storage/innobase/sync/sync0arr.cc34
-rw-r--r--storage/innobase/sync/sync0rw.cc82
-rw-r--r--storage/innobase/trx/trx0purge.cc824
-rw-r--r--storage/innobase/trx/trx0rec.cc320
-rw-r--r--storage/innobase/trx/trx0roll.cc191
-rw-r--r--storage/innobase/trx/trx0rseg.cc56
-rw-r--r--storage/innobase/trx/trx0sys.cc9
-rw-r--r--storage/innobase/trx/trx0trx.cc86
-rw-r--r--storage/innobase/trx/trx0undo.cc78
-rw-r--r--storage/innobase/ut/ut0crc32.cc82
-rw-r--r--storage/innobase/ut/ut0new.cc1
-rw-r--r--storage/innobase/ut/ut0rnd.cc4
-rw-r--r--storage/innobase/ut/ut0ut.cc2
-rw-r--r--storage/maria/CMakeLists.txt10
-rw-r--r--storage/maria/ha_maria.cc152
-rw-r--r--storage/maria/ha_maria.h2
-rw-r--r--storage/maria/ma_backup.c281
-rw-r--r--storage/maria/ma_blockrec.c3
-rw-r--r--storage/maria/ma_check.c40
-rw-r--r--storage/maria/ma_checkpoint.h4
-rw-r--r--storage/maria/ma_control_file.c122
-rw-r--r--storage/maria/ma_control_file.h1
-rw-r--r--storage/maria/ma_create.c22
-rw-r--r--storage/maria/ma_crypt.c8
-rw-r--r--storage/maria/ma_extra.c5
-rw-r--r--storage/maria/ma_info.c2
-rw-r--r--storage/maria/ma_init.c2
-rw-r--r--storage/maria/ma_locking.c9
-rw-r--r--storage/maria/ma_loghandler.c27
-rw-r--r--storage/maria/ma_loghandler.h3
-rw-r--r--storage/maria/ma_open.c35
-rw-r--r--storage/maria/ma_pagecrc.c10
-rw-r--r--storage/maria/ma_recovery.c17
-rw-r--r--storage/maria/ma_sort.c2
-rw-r--r--storage/maria/ma_state.c27
-rw-r--r--storage/maria/ma_test2.c5
-rw-r--r--storage/maria/ma_trnman.h36
-rw-r--r--storage/maria/ma_write.c2
-rw-r--r--storage/maria/maria_chk.c2
-rw-r--r--storage/maria/maria_def.h7
-rw-r--r--storage/maria/maria_pack.c116
-rw-r--r--storage/maria/maria_read_log.c30
-rwxr-xr-xstorage/maria/maria_rename.sh17
-rw-r--r--storage/maria/test_ma_backup.c449
-rw-r--r--storage/maria/trnman.c3
-rw-r--r--storage/maria/unittest/lockman-t.c1
-rw-r--r--storage/maria/unittest/lockman1-t.c1
-rw-r--r--storage/maria/unittest/lockman2-t.c1
-rwxr-xr-xstorage/maria/unittest/ma_test_all-t7
-rw-r--r--storage/maria/unittest/ma_test_recovery.expected192
-rw-r--r--storage/maria/unittest/trnman-t.c1
-rw-r--r--storage/mroonga/CMakeLists.txt7
-rw-r--r--storage/mroonga/ha_mroonga.cpp40
-rw-r--r--storage/mroonga/ha_mroonga.hpp14
-rw-r--r--storage/mroonga/lib/mrn_condition_converter.cpp29
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_between.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater_equal.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less_equal.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_not_equal.result2
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_between.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater_equal.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_not_equal.result2
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/r/variable_max_n_records_for_estimate_not_found_in_limit.result1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_between.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater_equal.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less_equal.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_between.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater.test2
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater_equal.test1
-rw-r--r--storage/mroonga/mysql-test/mroonga/storage/t/variable_max_n_records_for_estimate_not_found_in_limit.test1
-rw-r--r--storage/mroonga/vendor/groonga/lib/ii.c48
-rw-r--r--storage/mroonga/vendor/groonga/vendor/plugins/CMakeLists.txt3
-rw-r--r--storage/myisam/TODO7
-rw-r--r--storage/myisam/ha_myisam.cc101
-rw-r--r--storage/myisam/ha_myisam.h4
-rw-r--r--storage/myisam/mi_check.c40
-rw-r--r--storage/myisam/mi_extra.c15
-rw-r--r--storage/myisam/mi_info.c2
-rw-r--r--storage/myisam/mi_key.c13
-rw-r--r--storage/myisam/mi_locking.c6
-rw-r--r--storage/myisam/mi_range.c75
-rw-r--r--storage/myisam/mi_rkey.c4
-rw-r--r--storage/myisam/mi_rnext.c4
-rw-r--r--storage/myisam/mi_rnext_same.c4
-rw-r--r--storage/myisam/mi_rprev.c4
-rw-r--r--storage/myisam/mi_write.c2
-rw-r--r--storage/myisam/myisamdef.h14
-rw-r--r--storage/myisam/myisamlog.c3
-rw-r--r--storage/myisam/myisampack.c2
-rw-r--r--storage/myisam/sort.c2
-rw-r--r--storage/myisammrg/ha_myisammrg.cc2
-rw-r--r--storage/myisammrg/ha_myisammrg.h2
-rw-r--r--storage/myisammrg/myrg_write.c2
-rw-r--r--storage/oqgraph/CMakeLists.txt27
-rw-r--r--storage/oqgraph/ha_oqgraph.cc4
-rw-r--r--storage/oqgraph/ha_oqgraph.h2
-rw-r--r--storage/oqgraph/oqgraph_thunk.cc12
-rw-r--r--storage/perfschema/ha_perfschema.cc3
-rw-r--r--storage/perfschema/ha_perfschema.h2
-rw-r--r--storage/perfschema/pfs_engine_table.cc2
-rw-r--r--storage/perfschema/pfs_engine_table.h4
-rw-r--r--storage/perfschema/pfs_server.h2
-rw-r--r--storage/perfschema/table_setup_actors.cc2
-rw-r--r--storage/perfschema/table_setup_actors.h2
-rw-r--r--storage/perfschema/table_setup_objects.cc2
-rw-r--r--storage/perfschema/table_setup_objects.h2
-rw-r--r--storage/perfschema/unittest/pfs_server_stubs.cc2
-rw-r--r--storage/rocksdb/CMakeLists.txt25
-rw-r--r--storage/rocksdb/build_rocksdb.cmake2
-rw-r--r--storage/rocksdb/ha_rocksdb.cc14
-rw-r--r--storage/rocksdb/ha_rocksdb.h3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/include/use_direct_io_option.inc1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result14
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key_with_sk.result9
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result6
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/autoinc_secondary.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bloomfilter3.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load_errors.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/cardinality.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/compression_zstd.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/drop_table2.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/drop_table3.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result480
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result8
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/issue884.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/max_open_files.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/misc.result6
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result60
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/partition.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_options.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/rocksdb_checksums.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/rocksdb_parts.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result3
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/select.result6
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/show_table_status.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/skip_validate_tmp_table.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/statistics.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/truncate_table3.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/type_char_indexes.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/type_date_time_indexes.result2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result8
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result5
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/use_direct_reads_writes.result4
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/r/xa.result1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/t/cardinality.test2
-rw-r--r--storage/rocksdb/mysql-test/rocksdb/t/disabled.def1
-rw-r--r--storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result18
-rw-r--r--storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test85
-rw-r--r--storage/rocksdb/rdb_datadic.cc3
-rw-r--r--storage/sequence/mysql-test/sequence/simple.result4
-rw-r--r--storage/sequence/mysql-test/sequence/simple.test2
-rw-r--r--storage/sphinx/ha_sphinx.cc10
-rw-r--r--storage/sphinx/ha_sphinx.h2
-rw-r--r--storage/spider/ha_spider.cc169
-rw-r--r--storage/spider/ha_spider.h33
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc2
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/cp932_column_deinit.inc13
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/cp932_column_init.inc29
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_deinit.inc13
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_init.inc24
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_deinit.inc4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_init.inc14
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_deinit.inc4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_init.inc16
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_deinit.inc14
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_init.inc54
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/mdev_19866_deinit.inc14
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/mdev_19866_init.inc52
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc27
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc26
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/same_server_link_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/same_server_link_init.inc15
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_init.inc25
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_deinit.inc10
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_init.inc10
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc12
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc13
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/sql_mode_deinit.inc13
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/sql_mode_init.inc40
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_deinit.inc1
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_init.inc3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_deinit.inc1
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_init.inc3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/wait_timeout_deinit.inc18
-rw-r--r--storage/spider/mysql-test/spider/bugfix/include/wait_timeout_init.inc56
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result6
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/cp932_column.result84
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mariadb.result85
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mysql.result85
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/group_by_order_by_limit.result117
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result111
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result179
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result99
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/same_server_link.result42
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result75
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result22
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result2
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result38
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result83
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result83
-rw-r--r--storage/spider/mysql-test/spider/bugfix/r/wait_timeout.result130
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/cp932_column.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/cp932_column.test80
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column.inc98
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.cnf4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.test5
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.cnf4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.test5
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.cnf4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.test97
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/mdev_19866.cnf4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/mdev_19866.test97
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test98
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test78
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/same_server_link.cnf2
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/same_server_link.test55
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.test74
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.cnf6
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.test9
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf2
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test46
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc65
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.test5
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.cnf3
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.test5
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/wait_timeout.cnf4
-rw-r--r--storage/spider/mysql-test/spider/bugfix/t/wait_timeout.test109
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_deinit.inc16
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_deinit.inc1
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_init.inc2
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_init.inc53
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_deinit.inc1
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_init.inc2
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_deinit.inc1
-rw-r--r--storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_init.inc2
-rw-r--r--storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_deinit.inc10
-rw-r--r--storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_init.inc10
-rw-r--r--storage/spider/mysql-test/spider/feature/my.cnf2
-rw-r--r--storage/spider/mysql-test/spider/feature/my_1_1.cnf44
-rw-r--r--storage/spider/mysql-test/spider/feature/my_2_1.cnf56
-rw-r--r--storage/spider/mysql-test/spider/feature/my_2_2.cnf38
-rw-r--r--storage/spider/mysql-test/spider/feature/my_2_3.cnf8
-rw-r--r--storage/spider/mysql-test/spider/feature/my_3_1.cnf11
-rw-r--r--storage/spider/mysql-test/spider/feature/my_3_2.cnf9
-rw-r--r--storage/spider/mysql-test/spider/feature/my_3_3.cnf9
-rw-r--r--storage/spider/mysql-test/spider/feature/my_4_1.cnf9
-rw-r--r--storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_extended.result130
-rw-r--r--storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_no_opt.result128
-rw-r--r--storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_quick.result128
-rw-r--r--storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result22
-rw-r--r--storage/spider/mysql-test/spider/feature/suite.opt1
-rw-r--r--storage/spider/mysql-test/spider/feature/suite.pm12
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel.inc107
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.cnf4
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.test5
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.cnf4
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.test5
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.cnf4
-rw-r--r--storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.test5
-rw-r--r--storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.cnf4
-rw-r--r--storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.test9
-rw-r--r--storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc2
-rw-r--r--storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc2
-rw-r--r--storage/spider/mysql-test/spider/include/deinit_spider.inc99
-rw-r--r--storage/spider/mysql-test/spider/include/init_spider.inc541
-rw-r--r--storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result6
-rw-r--r--storage/spider/mysql-test/spider/r/direct_join.result2
-rw-r--r--storage/spider/mysql-test/spider/r/partition_fulltext.result6
-rw-r--r--storage/spider/mysql-test/spider/r/show_system_tables.result18
-rw-r--r--storage/spider/mysql-test/spider/r/slave_trx_isolation.result2
-rw-r--r--storage/spider/mysql-test/spider/r/timestamp.result20
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_deinit.inc12
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_init.inc36
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_deinit.inc12
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_init.inc36
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_deinit.inc3
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_init.inc4
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_deinit.inc3
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_init.inc4
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/load_data_deinit.inc11
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/include/load_data_init.inc25
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/my.cnf3
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/my_1_1.cnf44
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/my_2_1.cnf56
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result94
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_pkey.result94
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi0.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi1.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi0.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi1.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi0.result84
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi1.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi0.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi1.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi0.result104
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi1.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi0.result104
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi1.result75
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/suite.opt1
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/suite.pm12
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_key.test82
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_pkey.test82
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data.inc76
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_deinit.inc14
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_init.inc54
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_deinit.inc3
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_init.inc4
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_deinit.inc3
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_init.inc4
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_deinit.inc14
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_init.inc52
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/my.cnf4
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/my_1_1.cnf44
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/my_2_1.cnf56
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/my_2_2.cnf38
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/group_by_order_by_limit_ok.result117
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi0.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi1.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi0.result114
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi1.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi0.result103
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi1.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi0.result114
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi1.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi0.result123
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi1.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi0.result123
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi1.result95
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/suite.opt1
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/suite.pm12
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/group_by_order_by_limit_ok.test97
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part.inc100
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi0.test8
-rw-r--r--storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi1.test8
-rw-r--r--storage/spider/mysql-test/spider/t/connect_child2_1.inc1
-rw-r--r--storage/spider/mysql-test/spider/t/connect_child2_2.inc1
-rw-r--r--storage/spider/mysql-test/spider/t/test_deinit.inc2
-rw-r--r--storage/spider/scripts/install_spider.sql543
-rw-r--r--storage/spider/spd_conn.cc58
-rw-r--r--storage/spider/spd_conn.h24
-rw-r--r--storage/spider/spd_db_conn.cc478
-rw-r--r--storage/spider/spd_db_conn.h32
-rw-r--r--storage/spider/spd_db_handlersocket.cc143
-rw-r--r--storage/spider/spd_db_handlersocket.h44
-rw-r--r--storage/spider/spd_db_include.cc27
-rw-r--r--storage/spider/spd_db_include.h67
-rw-r--r--storage/spider/spd_db_mysql.cc1838
-rw-r--r--storage/spider/spd_db_mysql.h89
-rw-r--r--storage/spider/spd_db_oracle.cc204
-rw-r--r--storage/spider/spd_db_oracle.h44
-rw-r--r--storage/spider/spd_environ.h3
-rw-r--r--storage/spider/spd_err.h3
-rw-r--r--storage/spider/spd_group_by_handler.cc62
-rw-r--r--storage/spider/spd_include.h39
-rw-r--r--storage/spider/spd_init_query.h782
-rw-r--r--storage/spider/spd_malloc.cc19
-rw-r--r--storage/spider/spd_malloc.h5
-rw-r--r--storage/spider/spd_param.cc73
-rw-r--r--storage/spider/spd_param.h12
-rw-r--r--storage/spider/spd_sys_table.cc462
-rw-r--r--storage/spider/spd_sys_table.h85
-rw-r--r--storage/spider/spd_table.cc395
-rw-r--r--storage/spider/spd_table.h15
-rw-r--r--storage/spider/spd_trx.cc55
-rw-r--r--storage/spider/spd_trx.h17
-rw-r--r--storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake1
-rw-r--r--storage/tokudb/PerconaFT/portability/toku_crash.cc2
-rw-r--r--storage/tokudb/ha_tokudb.cc36
-rw-r--r--storage/tokudb/ha_tokudb.h10
-rw-r--r--storage/tokudb/ha_tokudb_alter_56.cc18
-rw-r--r--storage/tokudb/ha_tokudb_update.cc6
-rw-r--r--storage/tokudb/man/tokuft_logprint.12
-rw-r--r--storage/tokudb/man/tokuftdump.12
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result12
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result4
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result40
-rw-r--r--storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/include/cluster_key.inc73
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_add_drop.result5
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_add_index.result6
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_drop_index.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_no_keys.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_pk.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_pk_2.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result5
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_sk.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_sk_2.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_2968-2.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_create_table.result8
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_delete.result128
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_filter_key.result13
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_key.result165
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_query_plan.result8
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_tokudb_bug_993_2.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/cluster_update.result115
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/compressions.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/dir_per_db_rename_to_nonexisting_schema.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/tokudb_mrr.result12
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/type_bit.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/type_blob.result11
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/type_datetime.result10
-rw-r--r--storage/tokudb/mysql-test/tokudb/r/type_varchar.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_add_drop.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_add_index.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_drop_index.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_drop_index_2.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_drop_pk.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_pk_2.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_pk_sk.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_sk.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/card_sk_2.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_create_table.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_delete.test50
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_filter_key.test8
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_query_plan.test8
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/cluster_update.test43
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/tokudb_mrr.test8
-rw-r--r--storage/tokudb/mysql-test/tokudb/t/type_blob.test5
-rw-r--r--storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_with_lock_sps.result12
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/disabled.def1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/5733_innodb.result8
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/5733_tokudb.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/PS-3773.result2
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/bulk_fetch.result8
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result6
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result7
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/frm_store.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/frm_store2.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/frm_store3.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/r/index_read.result6
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/bulk_fetch.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash.test3
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1_pick.test3
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2_pick.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/db757_part_alter_analyze.test3
-rw-r--r--storage/tokudb/mysql-test/tokudb_bugs/t/index_read.test4
-rw-r--r--storage/tokudb/mysql-test/tokudb_mariadb/r/clustering.result17
-rw-r--r--storage/tokudb/mysql-test/tokudb_mariadb/t/clustering.test5
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_2_tokudb.result56
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_tokudb.result32
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_2_tokudb.result80
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_1_tokudb.result40
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_2_tokudb.result40
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_1_tokudb.result40
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_2_tokudb.result40
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_alter4_tokudb.result216
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_basic_tokudb.result64
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result11
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result1
-rw-r--r--storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result18
-rw-r--r--storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test85
-rw-r--r--storage/tokudb/tokudb_dir_cmd.cc4
-rw-r--r--storage/tokudb/tokudb_sysvars.cc2
784 files changed, 30103 insertions, 19336 deletions
diff --git a/storage/archive/azio.c b/storage/archive/azio.c
index 0f66b999c94..3529d875f72 100644
--- a/storage/archive/azio.c
+++ b/storage/archive/azio.c
@@ -866,7 +866,10 @@ int azclose (azio_stream *s)
if (s->mode == 'w')
{
if (do_flush(s, Z_FINISH) != Z_OK)
- return destroy(s);
+ {
+ destroy(s);
+ return Z_ERRNO;
+ }
putLong(s->file, s->crc);
putLong(s->file, (uLong)(s->in & 0xffffffff));
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc
index c25a1c00c87..fa49b081ad1 100644
--- a/storage/archive/ha_archive.cc
+++ b/storage/archive/ha_archive.cc
@@ -371,7 +371,7 @@ int Archive_share::write_v1_metafile()
@return Length of packed row
*/
-unsigned int ha_archive::pack_row_v1(uchar *record)
+unsigned int ha_archive::pack_row_v1(const uchar *record)
{
uint *blob, *end;
uchar *pos;
@@ -802,7 +802,7 @@ int ha_archive::create(const char *name, TABLE *table_arg,
#endif /* HAVE_READLINK */
{
if (create_info->data_file_name)
- my_error(WARN_OPTION_IGNORED, MYF(ME_JUST_WARNING), "DATA DIRECTORY");
+ my_error(WARN_OPTION_IGNORED, MYF(ME_WARNING), "DATA DIRECTORY");
fn_format(name_buff, name, "", ARZ,
MY_REPLACE_EXT | MY_UNPACK_FILENAME);
@@ -811,7 +811,7 @@ int ha_archive::create(const char *name, TABLE *table_arg,
/* Archive engine never uses INDEX DIRECTORY. */
if (create_info->index_file_name)
- my_error(WARN_OPTION_IGNORED, MYF(ME_JUST_WARNING), "INDEX DIRECTORY");
+ my_error(WARN_OPTION_IGNORED, MYF(ME_WARNING), "INDEX DIRECTORY");
/*
There is a chance that the file was "discovered". In this case
@@ -868,7 +868,7 @@ error:
/*
This is where the actual row is written out.
*/
-int ha_archive::real_write_row(uchar *buf, azio_stream *writer)
+int ha_archive::real_write_row(const uchar *buf, azio_stream *writer)
{
my_off_t written;
unsigned int r_pack_length;
@@ -917,7 +917,7 @@ uint32 ha_archive::max_row_length(const uchar *record)
}
-unsigned int ha_archive::pack_row(uchar *record, azio_stream *writer)
+unsigned int ha_archive::pack_row(const uchar *record, azio_stream *writer)
{
uchar *ptr;
my_ptrdiff_t const rec_offset= record - table->record[0];
@@ -959,7 +959,7 @@ unsigned int ha_archive::pack_row(uchar *record, azio_stream *writer)
for implementing start_bulk_insert() is that we could skip
setting dirty to true each time.
*/
-int ha_archive::write_row(uchar *buf)
+int ha_archive::write_row(const uchar *buf)
{
int rc;
uchar *read_buf= NULL;
@@ -980,7 +980,7 @@ int ha_archive::write_row(uchar *buf)
if (table->next_number_field && record == table->record[0])
{
- KEY *mkey= &table->s->key_info[0]; // We only support one key right now
+ KEY *mkey= &table->key_info[0]; // We only support one key right now
update_auto_increment();
temp_auto= table->next_number_field->val_int();
@@ -1098,7 +1098,7 @@ int ha_archive::index_read_idx(uchar *buf, uint index, const uchar *key,
{
int rc;
bool found= 0;
- KEY *mkey= &table->s->key_info[index];
+ KEY *mkey= &table->key_info[index];
current_k_offset= mkey->key_part->offset;
current_key= key;
current_key_len= key_len;
@@ -1753,6 +1753,20 @@ void ha_archive::flush_and_clear_pending_writes()
}
+int ha_archive::extra(enum ha_extra_function operation)
+{
+ switch (operation) {
+ case HA_EXTRA_FLUSH:
+ mysql_mutex_lock(&share->mutex);
+ share->close_archive_writer();
+ mysql_mutex_unlock(&share->mutex);
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
/*
This method tells us that a bulk insert operation is about to occur. We set
a flag which will keep write_row from saying that its data is dirty. This in
diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h
index a4911fe9e32..b9fcf10f96f 100644
--- a/storage/archive/ha_archive.h
+++ b/storage/archive/ha_archive.h
@@ -95,7 +95,7 @@ class ha_archive: public handler
void destroy_record_buffer(archive_record_buffer *r);
int frm_copy(azio_stream *src, azio_stream *dst);
int frm_compare(azio_stream *src);
- unsigned int pack_row_v1(uchar *record);
+ unsigned int pack_row_v1(const uchar *record);
public:
ha_archive(handlerton *hton, TABLE_SHARE *table_arg);
@@ -108,7 +108,7 @@ public:
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_STATS_RECORDS_IS_EXACT | HA_CAN_EXPORT |
- HA_HAS_RECORDS | HA_CAN_REPAIR |
+ HA_HAS_RECORDS | HA_CAN_REPAIR | HA_SLOW_RND_POS |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
@@ -131,8 +131,8 @@ public:
int index_next(uchar * buf);
int open(const char *name, int mode, uint test_if_locked);
int close(void);
- int write_row(uchar * buf);
- int real_write_row(uchar *buf, azio_stream *writer);
+ int write_row(const uchar * buf);
+ int real_write_row(const uchar *buf, azio_stream *writer);
int truncate();
int rnd_init(bool scan=1);
int rnd_next(uchar *buf);
@@ -148,6 +148,7 @@ public:
int read_data_header(azio_stream *file_to_read);
void position(const uchar *record);
int info(uint);
+ int extra(enum ha_extra_function operation);
void update_create_info(HA_CREATE_INFO *create_info);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
@@ -167,7 +168,7 @@ public:
uint32 max_row_length(const uchar *buf);
bool fix_rec_buff(unsigned int length);
int unpack_row(azio_stream *file_to_read, uchar *record);
- unsigned int pack_row(uchar *record, azio_stream *writer);
+ unsigned int pack_row(const uchar *record, azio_stream *writer);
bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes);
int external_lock(THD *thd, int lock_type);
private:
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 3f770c7005e..1b64db142e0 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -117,7 +117,7 @@ const char *ha_blackhole::index_type(uint key_number)
HA_KEY_ALG_RTREE) ? "RTREE" : "BTREE");
}
-int ha_blackhole::write_row(uchar * buf)
+int ha_blackhole::write_row(const uchar * buf)
{
DBUG_ENTER("ha_blackhole::write_row");
DBUG_RETURN(table->next_number_field ? update_auto_increment() : 0);
diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h
index ea026c5837c..6ee30877b64 100644
--- a/storage/blackhole/ha_blackhole.h
+++ b/storage/blackhole/ha_blackhole.h
@@ -55,7 +55,7 @@ public:
{
return(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE |
- HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
+ HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY | HA_CAN_ONLINE_BACKUPS |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_CAN_INSERT_DELAYED);
}
ulong index_flags(uint inx, uint part, bool all_parts) const
@@ -96,7 +96,7 @@ public:
THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
private:
- virtual int write_row(uchar *buf);
+ virtual int write_row(const uchar *buf);
virtual int update_row(const uchar *old_data, const uchar *new_data);
virtual int delete_row(const uchar *buf);
};
diff --git a/storage/cassandra/ha_cassandra.cc b/storage/cassandra/ha_cassandra.cc
index 4f9e207235f..f081dca71c3 100644
--- a/storage/cassandra/ha_cassandra.cc
+++ b/storage/cassandra/ha_cassandra.cc
@@ -1931,7 +1931,7 @@ void ha_cassandra::free_dynamic_row(DYNAMIC_COLUMN_VALUE **vals,
*names= 0;
}
-int ha_cassandra::write_row(uchar *buf)
+int ha_cassandra::write_row(const uchar *buf)
{
my_bitmap_map *old_map;
int ires;
diff --git a/storage/cassandra/ha_cassandra.h b/storage/cassandra/ha_cassandra.h
index 9a44abc985f..a36d58fa4da 100644
--- a/storage/cassandra/ha_cassandra.h
+++ b/storage/cassandra/ha_cassandra.h
@@ -239,7 +239,7 @@ public:
int open(const char *name, int mode, uint test_if_locked);
int close(void);
- int write_row(uchar *buf);
+ int write_row(const uchar *buf);
int update_row(const uchar *old_data, const uchar *new_data);
int delete_row(const uchar *buf);
diff --git a/storage/connect/array.cpp b/storage/connect/array.cpp
index 84a686cc145..3c736941b6f 100644
--- a/storage/connect/array.cpp
+++ b/storage/connect/array.cpp
@@ -599,10 +599,12 @@ int ARRAY::Convert(PGLOBAL g, int k, PVAL vp)
/* Converting STRING to DATE can be done according to date format. */
/*********************************************************************/
if (Type == TYPE_DATE && ovblp->GetType() == TYPE_STRING && vp)
+ {
if (((DTVAL*)Value)->SetFormat(g, vp))
return TYPE_ERROR;
else
b = true; // Sort the new array on date internal values
+ }
/*********************************************************************/
/* Do the actual conversion. */
diff --git a/storage/connect/colblk.cpp b/storage/connect/colblk.cpp
index a9cf43f3d96..242e68b5905 100644
--- a/storage/connect/colblk.cpp
+++ b/storage/connect/colblk.cpp
@@ -80,6 +80,7 @@ COLBLK::COLBLK(PCOL col1, PTDB tdbp)
htrc(" copying COLBLK %s from %p to %p\n", Name, col1, this);
if (tdbp)
+ {
// Attach the new column to the table block
if (!tdbp->GetColumns())
tdbp->SetColumns(this);
@@ -88,7 +89,7 @@ COLBLK::COLBLK(PCOL col1, PTDB tdbp)
colp->Next = this;
} // endelse
-
+ }
} // end of COLBLK copy constructor
/***********************************************************************/
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index dfc619cf4af..60c10527fe9 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -646,6 +646,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
// return 0;
if (tdbp->GetKindex())
+ {
if (((XXBASE*)tdbp->GetKindex())->GetID() == id) {
tdbp->GetKindex()->Reset(); // Same index
return (tdbp->GetKindex()->IsMul()) ? 2 : 1;
@@ -653,6 +654,7 @@ int CntIndexInit(PGLOBAL g, PTDB ptdb, int id, bool sorted)
tdbp->GetKindex()->Close();
tdbp->SetKindex(NULL);
} // endif colp
+ }
for (xdp= dfp->GetIndx(); xdp; xdp= xdp->GetNext())
if (xdp->GetID() == id)
diff --git a/storage/connect/filamap.cpp b/storage/connect/filamap.cpp
index 6e71e1bf2cd..53150f9d8ae 100644
--- a/storage/connect/filamap.cpp
+++ b/storage/connect/filamap.cpp
@@ -349,7 +349,8 @@ int MAPFAM::ReadBuffer(PGLOBAL g)
if ((rc = GetNext(g)) != RC_OK)
return rc;
- case RC_NF:
+ /* falls through */
+ case RC_NF:
// Skip this record
if ((rc = SkipRecord(g, false)) != RC_OK)
return rc;
diff --git a/storage/connect/filamdbf.cpp b/storage/connect/filamdbf.cpp
index c8bab2b53a4..43b3e461cd1 100644
--- a/storage/connect/filamdbf.cpp
+++ b/storage/connect/filamdbf.cpp
@@ -841,6 +841,7 @@ int DBFFAM::DeleteRecords(PGLOBAL g, int irc)
if (irc == RC_OK) {
// T_Stream is the temporary stream or the table file stream itself
if (!T_Stream)
+ {
if (UseTemp) {
if (OpenTempFile(g))
return RC_FX;
@@ -850,7 +851,7 @@ int DBFFAM::DeleteRecords(PGLOBAL g, int irc)
} else
T_Stream = Stream;
-
+ }
*Tdbp->GetLine() = '*';
Modif++; // Modified line in Delete mode
} // endif irc
diff --git a/storage/connect/filamfix.cpp b/storage/connect/filamfix.cpp
index 0a98ec5b54a..433dd71cd0c 100644
--- a/storage/connect/filamfix.cpp
+++ b/storage/connect/filamfix.cpp
@@ -135,7 +135,7 @@ bool FIXFAM::AllocateBuffer(PGLOBAL g)
// The buffer must be prepared depending on column types
int n = 0;
bool b = false;
- PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
+ PDOSDEF defp __attribute__((unused))= (PDOSDEF)Tdbp->GetDef();
// PCOLDEF cdp;
PBINCOL colp;
diff --git a/storage/connect/filamgz.cpp b/storage/connect/filamgz.cpp
index 880db54c91d..6c960ab86de 100644
--- a/storage/connect/filamgz.cpp
+++ b/storage/connect/filamgz.cpp
@@ -647,7 +647,7 @@ int ZBKFAM::WriteBuffer(PGLOBAL g)
int ZBKFAM::DeleteRecords(PGLOBAL g, int irc)
{
if (irc == RC_EF) {
- LPCSTR name = Tdbp->GetName();
+ LPCSTR name __attribute__((unused)) = Tdbp->GetName();
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
defp->SetBlock(0);
@@ -673,7 +673,7 @@ void ZBKFAM::CloseTableFile(PGLOBAL g, bool)
int rc = RC_OK;
if (Tdbp->GetMode() == MODE_INSERT) {
- LPCSTR name = Tdbp->GetName();
+ LPCSTR name __attribute__((unused))= Tdbp->GetName();
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
if (CurNum && !Closing) {
@@ -1021,6 +1021,7 @@ bool ZLBFAM::AllocateBuffer(PGLOBAL g)
#else
sprintf(g->Message, MSG(READ_ERROR), To_File, _strerror(NULL));
#endif
+ /* falls through */
case RC_NF:
return TRUE;
} // endswitch
@@ -1355,7 +1356,7 @@ void ZLBFAM::CloseTableFile(PGLOBAL g, bool)
int rc = RC_OK;
if (Tdbp->GetMode() == MODE_INSERT) {
- LPCSTR name = Tdbp->GetName();
+ LPCSTR name __attribute__((unused))= Tdbp->GetName();
PDOSDEF defp = (PDOSDEF)Tdbp->GetDef();
// Closing is True if last Write was in error
diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp
index ca48fc765a1..67ab120c499 100644
--- a/storage/connect/filamtxt.cpp
+++ b/storage/connect/filamtxt.cpp
@@ -1547,13 +1547,14 @@ int BLKFAM::WriteBuffer(PGLOBAL g)
// T_Stream is the temporary stream or the table file stream itself
if (!T_Stream)
+ {
if (UseTemp /*&& Tdbp->GetMode() == MODE_UPDATE*/) {
if (OpenTempFile(g))
return RC_FX;
} else
T_Stream = Stream;
-
+ }
if (UseTemp) {
/*****************************************************************/
/* We are using a temporary file. Before writing the updated */
diff --git a/storage/connect/filamvct.cpp b/storage/connect/filamvct.cpp
index 6d0779b150a..49283f8c0c7 100644
--- a/storage/connect/filamvct.cpp
+++ b/storage/connect/filamvct.cpp
@@ -302,6 +302,7 @@ int VCTFAM::Cardinality(PGLOBAL g)
return 1;
if (Block < 0)
+ {
if (Split) {
// Separate column files and no pre setting of Block and Last
// This allows to see a table modified externally, but Block
@@ -347,7 +348,7 @@ int VCTFAM::Cardinality(PGLOBAL g)
return -1; // Error
} // endif split
-
+ }
return (Block) ? ((Block - 1) * Nrec + Last) : 0;
} // end of Cardinality
@@ -1163,7 +1164,7 @@ bool VCTFAM::ResetTableSize(PGLOBAL g, int block, int last)
if (!Header) {
// Update catalog values for Block and Last
PVCTDEF defp = (PVCTDEF)Tdbp->GetDef();
- LPCSTR name = Tdbp->GetName();
+ LPCSTR name __attribute__((unused))= Tdbp->GetName();
defp->SetBlock(Block);
defp->SetLast(Last);
diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp
index f7866b9dae1..fd1cf0ceff9 100644
--- a/storage/connect/filamzip.cpp
+++ b/storage/connect/filamzip.cpp
@@ -91,7 +91,6 @@ static bool ZipFile(PGLOBAL g, ZIPUTIL *zutp, PCSZ fn, PCSZ entry, char *buf)
static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf)
{
char filename[_MAX_PATH];
- int rc;
/*********************************************************************/
/* pat is a multiple file name with wildcard characters */
@@ -102,6 +101,7 @@ static bool ZipFiles(PGLOBAL g, ZIPUTIL *zutp, PCSZ pat, char *buf)
char drive[_MAX_DRIVE], direc[_MAX_DIR];
WIN32_FIND_DATA FileData;
HANDLE hSearch;
+ int rc;
_splitpath(filename, drive, direc, NULL, NULL);
diff --git a/storage/connect/filter.cpp b/storage/connect/filter.cpp
index 7082b082c67..d776b403917 100644
--- a/storage/connect/filter.cpp
+++ b/storage/connect/filter.cpp
@@ -1220,15 +1220,19 @@ bool FILTER::Eval(PGLOBAL g)
int i; // n = 0;
//PSUBQ subp = NULL;
PARRAY ap = NULL;
- PDBUSER dup = PlgGetUser(g);
+ PDBUSER dup __attribute__((unused)) = PlgGetUser(g);
if (Opc <= OP_XX)
+ {
for (i = 0; i < 2; i++)
+ {
// Evaluate the object and eventually convert it.
if (Arg(i)->Eval(g))
return TRUE;
else if (Test[i].Conv)
Val(i)->SetValue_pval(Arg(i)->GetValue());
+ }
+ }
if (trace(1))
htrc(" Filter: op=%d type=%d %d B_T=%d %d val=%p %p\n",
diff --git a/storage/connect/fmdlex.c b/storage/connect/fmdlex.c
index 729b1b883c1..28b71b95e4d 100644
--- a/storage/connect/fmdlex.c
+++ b/storage/connect/fmdlex.c
@@ -240,12 +240,11 @@ YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+#ifdef NOT_USED
static int yy_start_stack_ptr = 0;
static int yy_start_stack_depth = 0;
static int *yy_start_stack = 0;
-static void yy_push_state YY_PROTO(( int new_state ));
-static void yy_pop_state YY_PROTO(( void ));
-static int yy_top_state YY_PROTO(( void ));
+#endif
static void *yy_flex_alloc YY_PROTO(( unsigned int ));
static void *yy_flex_realloc YY_PROTO(( void *, unsigned int ));
@@ -267,11 +266,13 @@ extern char *yytext;
static void yy_flex_strncpy YY_PROTO(( char *, const char *, int ));
#endif
+#ifdef NOT_USED
#ifdef __cplusplus
static int yyinput YY_PROTO(( void ));
#else
static int input YY_PROTO(( void ));
#endif
+#endif
static yy_state_type yy_get_previous_state YY_PROTO(( void ));
static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
@@ -1060,6 +1061,8 @@ register char *yy_bp;
}
+#ifdef NOT_USED
+
#ifdef __cplusplus
static int yyinput()
#else
@@ -1126,7 +1129,7 @@ static int input()
return c;
}
-
+#endif /* NOT_USED */
#ifdef YY_USE_PROTOS
void yyrestart( FILE *input_file )
@@ -1266,6 +1269,7 @@ FILE *file;
}
+#ifdef NOT_USED
#ifdef YY_USE_PROTOS
static void yy_push_state( int new_state )
#else
@@ -1297,7 +1301,6 @@ int new_state;
BEGIN(new_state);
}
-
static void yy_pop_state()
{
if ( --yy_start_stack_ptr < 0 )
@@ -1311,6 +1314,7 @@ static int yy_top_state()
{
return yy_start_stack[yy_start_stack_ptr - 1];
}
+#endif /* NOT_USED */
#ifdef YY_USE_PROTOS
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index df6edae7218..8b9a1ae5c8d 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -790,7 +790,7 @@ static int connect_init_func(void *p)
@brief
Plugin clean up
*/
-static int connect_done_func(void *)
+int connect_done_func(void *)
{
int error= 0;
PCONNECT pc, pn;
@@ -1703,10 +1703,7 @@ bool ha_connect::GetIndexOption(KEY *kp, PCSZ opname)
/****************************************************************************/
bool ha_connect::IsUnique(uint n)
{
- TABLE_SHARE *s= (table) ? table->s : NULL;
- KEY kp= s->key_info[n];
-
- return (kp.flags & 1) != 0;
+ return (table->key_info[n].flags & HA_NOSAME) != 0;
} // end of IsUnique
/****************************************************************************/
@@ -1976,7 +1973,7 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
k1= k2= 0;
n1= n2= 1; // 1 is space for final null character
- for (field= table->field; fp= *field; field++) {
+ for (field= table->field; (fp= *field); field++) {
if (bitmap_is_set(map, fp->field_index)) {
n1+= (fp->field_name.length + 1);
k1++;
@@ -1992,7 +1989,7 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
if (k1) {
p= c1= (char*)PlugSubAlloc(g, NULL, n1);
- for (field= table->field; fp= *field; field++)
+ for (field= table->field; (fp= *field); field++)
if (bitmap_is_set(map, fp->field_index)) {
strcpy(p, fp->field_name.str);
p+= (fp->field_name.length + 1);
@@ -2004,7 +2001,7 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
if (k2) {
p= c2= (char*)PlugSubAlloc(g, NULL, n2);
- for (field= table->field; fp= *field; field++)
+ for (field= table->field; (fp= *field); field++)
if (bitmap_is_set(ump, fp->field_index)) {
strcpy(p, fp->field_name.str);
@@ -2031,11 +2028,13 @@ int ha_connect::OpenTable(PGLOBAL g, bool del)
istable= true;
// strmake(tname, table_name, sizeof(tname)-1);
+#ifdef NOT_USED_VARIABLE
// We may be in a create index query
if (xmod == MODE_ANY && *tdbp->GetName() != '#') {
// The current indexes
PIXDEF oldpix= GetIndexInfo();
} // endif xmod
+#endif
} else
htrc("OpenTable: %s\n", g->Message);
@@ -2062,7 +2061,7 @@ bool ha_connect::CheckColumnList(PGLOBAL g)
MY_BITMAP *map= table->read_set;
try {
- for (field= table->field; fp= *field; field++)
+ for (field= table->field; (fp= *field); field++)
if (bitmap_is_set(map, fp->field_index)) {
if (!(colp= tdbp->ColDB(g, (PSZ)fp->field_name.str, 0))) {
sprintf(g->Message, "Column %s not found in %s",
@@ -2135,9 +2134,8 @@ int ha_connect::MakeRecord(char *buf)
DBUG_ENTER("ha_connect::MakeRecord");
if (trace(2))
- htrc("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n",
+ htrc("Maps: read=%08X write=%08X defr=%08X defw=%08X\n",
*table->read_set->bitmap, *table->write_set->bitmap,
- (table->vcol_set) ? *table->vcol_set->bitmap : 0,
*table->def_read_set.bitmap, *table->def_write_set.bitmap);
// Avoid asserts in field::store() for columns that are not updated
@@ -2777,37 +2775,40 @@ PFIL ha_connect::CondFilter(PGLOBAL g, Item *cond)
if (!i && (ismul))
return NULL;
- switch (args[i]->real_type()) {
- case COND::STRING_ITEM:
- res= pval->val_str(&tmp);
- pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length());
- pp->Type= (pp->Value) ? TYPE_STRING : TYPE_ERROR;
- break;
- case COND::INT_ITEM:
- pp->Type= TYPE_INT;
- pp->Value= PlugSubAlloc(g, NULL, sizeof(int));
- *((int*)pp->Value)= (int)pval->val_int();
- break;
- case COND::DATE_ITEM:
- pp->Type= TYPE_DATE;
- pp->Value= PlugSubAlloc(g, NULL, sizeof(int));
- *((int*)pp->Value)= (int)pval->val_int_from_date();
- break;
- case COND::REAL_ITEM:
- pp->Type= TYPE_DOUBLE;
- pp->Value= PlugSubAlloc(g, NULL, sizeof(double));
- *((double*)pp->Value)= pval->val_real();
- break;
- case COND::DECIMAL_ITEM:
- pp->Type= TYPE_DOUBLE;
- pp->Value= PlugSubAlloc(g, NULL, sizeof(double));
- *((double*)pp->Value)= pval->val_real_from_decimal();
- break;
+ switch (args[i]->real_type()) {
+ case COND::CONST_ITEM:
+ switch (args[i]->cmp_type()) {
+ case STRING_RESULT:
+ res= pval->val_str(&tmp);
+ pp->Value= PlugSubAllocStr(g, NULL, res->ptr(), res->length());
+ pp->Type= (pp->Value) ? TYPE_STRING : TYPE_ERROR;
+ break;
+ case INT_RESULT:
+ pp->Type= TYPE_INT;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(int));
+ *((int*)pp->Value)= (int)pval->val_int();
+ break;
+ case TIME_RESULT:
+ pp->Type= TYPE_DATE;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(int));
+ *((int*)pp->Value)= (int) Temporal_hybrid(pval).to_longlong();
+ break;
+ case REAL_RESULT:
+ case DECIMAL_RESULT:
+ pp->Type= TYPE_DOUBLE;
+ pp->Value= PlugSubAlloc(g, NULL, sizeof(double));
+ *((double*)pp->Value)= pval->val_real();
+ break;
+ case ROW_RESULT:
+ DBUG_ASSERT(0);
+ return NULL;
+ }
+ break;
case COND::CACHE_ITEM: // Possible ???
case COND::NULL_ITEM: // TODO: handle this
default:
return NULL;
- } // endswitch type
+ } // endswitch type
if (trace(1))
htrc("Value type=%hd\n", pp->Type);
@@ -3061,12 +3062,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
Item::Type type= args[i]->real_type();
switch (type) {
- case COND::STRING_ITEM:
- case COND::INT_ITEM:
- case COND::REAL_ITEM:
+ case COND::CONST_ITEM:
case COND::NULL_ITEM:
- case COND::DECIMAL_ITEM:
- case COND::DATE_ITEM:
case COND::CACHE_ITEM:
break;
default:
@@ -3102,14 +3099,14 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
strcat(s, "'}");
break;
} // endif ODBC
-
- // fall through
+ // fall through
case MYSQL_TYPE_DATE:
if (tty == TYPE_AM_ODBC) {
strcat(s, "{d '");
strcat(strncat(s, res->ptr(), res->length()), "'}");
break;
} // endif ODBC
+ // fall through
case MYSQL_TYPE_TIME:
if (tty == TYPE_AM_ODBC) {
@@ -3117,6 +3114,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, const Item *cond)
strcat(strncat(s, res->ptr(), res->length()), "'}");
break;
} // endif ODBC
+ // fall through
case MYSQL_TYPE_VARCHAR:
if (tty == TYPE_AM_ODBC && i) {
@@ -3606,7 +3604,7 @@ int ha_connect::close(void)
item_sum.cc, item_sum.cc, sql_acl.cc, sql_insert.cc,
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc and sql_update.cc
*/
-int ha_connect::write_row(uchar *buf)
+int ha_connect::write_row(const uchar *buf)
{
int rc= 0;
PGLOBAL& g= xp->g;
@@ -4305,8 +4303,6 @@ int ha_connect::info(uint flag)
// tdbp must be available to get updated info
if (xp->CheckQuery(valid_query_id) || !tdbp) {
- PDBUSER dup= PlgGetUser(g);
- PCATLG cat= (dup) ? dup->Catalog : NULL;
if (xmod == MODE_ANY || xmod == MODE_ALTER) {
// Pure info, not a query
@@ -4591,12 +4587,14 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
// break;
case SQLCOM_DELETE_MULTI:
*cras= true;
+ // fall through
case SQLCOM_DELETE:
case SQLCOM_TRUNCATE:
newmode= MODE_DELETE;
break;
case SQLCOM_UPDATE_MULTI:
*cras= true;
+ // fall through
case SQLCOM_UPDATE:
newmode= MODE_UPDATE;
break;
@@ -4606,6 +4604,7 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
break;
case SQLCOM_FLUSH:
locked= 0;
+ // fall through
case SQLCOM_DROP_TABLE:
case SQLCOM_RENAME_TABLE:
newmode= MODE_ANY;
@@ -5527,7 +5526,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
PCSZ nsp= NULL, cls= NULL;
#endif // __WIN__
//int hdr, mxe;
- int port= 0, mxr= 0, rc= 0, mul= 0, lrecl= 0;
+ int port= 0, mxr __attribute__((unused)) = 0, rc= 0, mul= 0;
//PCSZ tabtyp= NULL;
#if defined(ODBC_SUPPORT)
POPARM sop= NULL;
@@ -5550,8 +5549,6 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
if (!g)
return HA_ERR_INTERNAL_ERROR;
- PDBUSER dup= PlgGetUser(g);
- PCATLG cat= (dup) ? dup->Catalog : NULL;
PTOS topt= table_s->option_struct;
char buf[1024];
String sql(buf, sizeof(buf), system_charset_info);
@@ -5794,6 +5791,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
#endif // __WIN__
case TAB_PIVOT:
supfnc= FNC_NO;
+ // fall through
case TAB_PRX:
case TAB_TBL:
case TAB_XCL:
@@ -6032,7 +6030,7 @@ static int connect_assisted_discovery(handlerton *, THD* thd,
} // endfor crp
} else {
- char *schem= NULL;
+ char *schem __attribute__((unused)) = NULL;
char *tn= NULL;
// Not a catalog table
@@ -7061,7 +7059,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
ALTER_DROP_PK_INDEX;
alter_table_operations inplace_offline_operations=
- ALTER_COLUMN_EQUAL_PACK_LENGTH |
+ ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
ALTER_COLUMN_NAME |
ALTER_COLUMN_DEFAULT |
ALTER_CHANGE_CREATE_OPTION |
@@ -7160,7 +7158,7 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
#if 0
uint table_changes= (ha_alter_info->handler_flags &
- ALTER_COLUMN_EQUAL_PACK_LENGTH) ?
+ ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) ?
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
if (table->file->check_if_incompatible_data(create_info, table_changes)
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 3e4474d140e..06de375ef58 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -388,7 +388,7 @@ virtual int check(THD* thd, HA_CHECK_OPT* check_opt);
We implement this in ha_connect.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
- int write_row(uchar *buf);
+ int write_row(const uchar *buf);
/** @brief
We implement this in ha_connect.cc. It's not an obligatory method;
@@ -549,3 +549,7 @@ public:
uint int_table_flags; // Inherited from MyISAM
bool enable_activate_all_index; // Inherited from MyISAM
}; // end of ha_connect class definition
+
+#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
+bool MongoEnabled(void);
+#endif // JAVA_SUPPORT || CMGO_SUPPORT
diff --git a/storage/connect/inihandl.cpp b/storage/connect/inihandl.cpp
index 8e79aeac7ef..95cb3a1227d 100644
--- a/storage/connect/inihandl.cpp
+++ b/storage/connect/inihandl.cpp
@@ -1340,6 +1340,7 @@ BOOL WritePrivateProfileSection(LPCSTR section,
* Note that when the buffer is big enough then the return value may be any
* value between 1 and len-1 (or len in Win95), including len-2.
*/
+#ifdef NOT_USED
static DWORD
GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename)
{
@@ -1356,7 +1357,7 @@ GetPrivateProfileSectionNames(LPSTR buffer, DWORD size, LPCSTR filename)
LeaveCriticalSection(&PROFILE_CritSect);
return ret;
} // end of GetPrivateProfileSectionNames
-
+#endif
/************************************************************************
* Program to test the above
diff --git a/storage/connect/json.cpp b/storage/connect/json.cpp
index 98a4659cea8..5d7d08285cf 100644
--- a/storage/connect/json.cpp
+++ b/storage/connect/json.cpp
@@ -154,7 +154,7 @@ PJSON ParseJson(PGLOBAL g, char *s, int len, int *ptyp, bool *comma)
b = false;
break;
} // endif b
-
+ /* falls through */
default:
if (jsp)
goto tryit;
diff --git a/storage/connect/jsonudf.cpp b/storage/connect/jsonudf.cpp
index d5bd1215e77..940e7e678fd 100644
--- a/storage/connect/jsonudf.cpp
+++ b/storage/connect/jsonudf.cpp
@@ -247,7 +247,7 @@ my_bool JSNX::ParseJpath(PGLOBAL g)
{
char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL;
int i;
- my_bool a, mul = false;
+ my_bool a;
if (Parsed)
return false; // Already done
@@ -379,6 +379,7 @@ void JSNX::SetJsonValue(PGLOBAL g, PVAL vp, PJVAL val, int n)
case TYPE_NULL:
vp->SetNull(true);
+ /* falls through */
default:
vp->Reset();
} // endswitch Type
@@ -424,7 +425,6 @@ PVAL JSNX::GetColumnValue(PGLOBAL g, PJSON row, int i)
/*********************************************************************************/
PJVAL JSNX::GetRowValue(PGLOBAL g, PJSON row, int i, my_bool b)
{
- my_bool expd = false;
PJAR arp;
PJVAL val = NULL;
@@ -763,7 +763,7 @@ my_bool JSNX::WriteValue(PGLOBAL g, PJVAL jvalp)
PSZ JSNX::Locate(PGLOBAL g, PJSON jsp, PJVAL jvp, int k)
{
PSZ str = NULL;
- my_bool b = false, err = true;
+ my_bool err = true;
g->Message[0] = 0;
@@ -885,7 +885,7 @@ my_bool JSNX::LocateValue(PJVAL jvp)
PSZ JSNX::LocateAll(PGLOBAL g, PJSON jsp, PJVAL jvp, int mx)
{
PSZ str = NULL;
- my_bool b = false, err = true;
+ my_bool err = true;
PJPN jnp;
if (!jsp) {
@@ -1352,7 +1352,7 @@ static PBSON MakeBinResult(PGLOBAL g, UDF_ARGS *args, PJSON top, ulong len, int
bsnp->Pretty = pretty;
- if (bsnp->Filename = (char*)args->args[0]) {
+ if ((bsnp->Filename = (char*)args->args[0])) {
bsnp->Filename = MakePSZ(g, args, 0);
strncpy(bsnp->Msg, bsnp->Filename, BMX);
} else
@@ -1773,7 +1773,7 @@ static char *GetJsonFile(PGLOBAL g, char *fn)
#endif
if (h == -1) {
- sprintf(g->Message, "Error %d opening %s", errno, fn);
+ sprintf(g->Message, "Error %d opening %-.1024s", errno, fn);
return NULL;
} // endif h
@@ -1785,7 +1785,7 @@ static char *GetJsonFile(PGLOBAL g, char *fn)
if ((str = (char*)PlgDBSubAlloc(g, NULL, len + 1))) {
if ((n = read(h, str, len)) < 0) {
- sprintf(g->Message, "Error %d reading %d bytes from %s", errno, len, fn);
+ sprintf(g->Message, "Error %d reading %d bytes from %-.1024s", errno, len, fn);
return NULL;
} // endif n
@@ -3480,7 +3480,7 @@ char *jsonget_string(UDF_INIT *initid, UDF_ARGS *args, char *result,
} catch (int n) {
if (trace(1))
- htrc("Exception %d: %s\n", n, g->Message);
+ htrc("Exception %d: %-.256s\n", n, g->Message);
PUSH_WARNING(g->Message);
str = NULL;
@@ -3755,12 +3755,13 @@ my_bool jsonlocate_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
strcpy(message, "Third argument is not an integer (rank)");
return true;
} else if (args->arg_count > 3)
+ {
if (args->arg_type[3] != INT_RESULT) {
strcpy(message, "Fourth argument is not an integer (memory)");
return true;
} else
more += (ulong)*(longlong*)args->args[2];
-
+ }
CalcLen(args, false, reslen, memlen);
// TODO: calculate this
@@ -3838,7 +3839,7 @@ char *jsonlocate(UDF_INIT *initid, UDF_ARGS *args, char *result,
} catch (int n) {
if (trace(1))
- htrc("Exception %d: %s\n", n, g->Message);
+ htrc("Exception %d: %-.256s\n", n, g->Message);
PUSH_WARNING(g->Message);
*error = 1;
@@ -3882,12 +3883,13 @@ my_bool json_locate_all_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
strcpy(message, "Third argument is not an integer (Depth)");
return true;
} else if (args->arg_count > 3)
+ {
if (args->arg_type[3] != INT_RESULT) {
strcpy(message, "Fourth argument is not an integer (memory)");
return true;
} else
more += (ulong)*(longlong*)args->args[2];
-
+ }
CalcLen(args, false, reslen, memlen);
// TODO: calculate this
@@ -3963,7 +3965,7 @@ char *json_locate_all(UDF_INIT *initid, UDF_ARGS *args, char *result,
} catch (int n) {
if (trace(1))
- htrc("Exception %d: %s\n", n, g->Message);
+ htrc("Exception %d: %-.256s\n", n, g->Message);
PUSH_WARNING(g->Message);
*error = 1;
@@ -4243,7 +4245,7 @@ char *handle_item(UDF_INIT *initid, UDF_ARGS *args, char *result,
} catch (int n) {
if (trace(1))
- htrc("Exception %d: %s\n", n, g->Message);
+ htrc("Exception %d: %-.256s\n", n, g->Message);
PUSH_WARNING(g->Message);
str = NULL;
@@ -5178,7 +5180,7 @@ char *jbin_object_delete(UDF_INIT *initid, UDF_ARGS *args, char *result,
PCSZ key;
PJOB jobp;
PJVAL jvp = MakeValue(g, args, 0, &top);
- PJSON jsp = jvp->GetJson();
+ PJSON jsp __attribute__((unused)) = jvp->GetJson();
if (CheckPath(g, args, top, jvp, 2))
PUSH_WARNING(g->Message);
@@ -5889,7 +5891,7 @@ long long countin(UDF_INIT *initid, UDF_ARGS *args, char *result,
memcpy(str2, args->args[1], lg);
str2[lg] = 0;
- while (s = strstr(s, str2)) {
+ while ((s = strstr(s, str2))) {
n++;
s += lg;
} // endwhile
diff --git a/storage/connect/libdoc.cpp b/storage/connect/libdoc.cpp
index 58b0267bd6d..69bbe980eba 100644
--- a/storage/connect/libdoc.cpp
+++ b/storage/connect/libdoc.cpp
@@ -211,7 +211,7 @@ static xmlStrdupFunc Strdup;
void xmlMyFree(void *mem)
{
if (trace(1)) {
- htrc("%.4d Freeing at %p %s\n", ++m, mem, s);
+ htrc("%.4d Freeing at %p %-.256s\n", ++m, mem, s);
*s = 0;
} // endif trace
Free(mem);
@@ -221,7 +221,7 @@ void *xmlMyMalloc(size_t size)
{
void *p = Malloc(size);
if (trace(1)) {
- htrc("%.4d Allocating %.5d at %p %s\n", ++m, size, p, s);
+ htrc("%.4d Allocating %.5d at %p %-.256s\n", ++m, size, p, s);
*s = 0;
} // endif trace
return p;
@@ -231,7 +231,7 @@ void *xmlMyMallocAtomic(size_t size)
{
void *p = MallocA(size);
if (trace(1)) {
- htrc("%.4d Atom alloc %.5d at %p %s\n", ++m, size, p, s);
+ htrc("%.4d Atom alloc %.5d at %p %-.256s\n", ++m, size, p, s);
*s = 0;
} // endif trace
return p;
@@ -241,7 +241,7 @@ void *xmlMyRealloc(void *mem, size_t size)
{
void *p = Realloc(mem, size);
if (trace(1)) {
- htrc("%.4d ReAlloc %.5d to %p from %p %s\n", ++m, size, p, mem, s);
+ htrc("%.4d ReAlloc %.5d to %p from %p %-.256s\n", ++m, size, p, mem, s);
*s = 0;
} // endif trace
return p;
@@ -251,7 +251,7 @@ char *xmlMyStrdup(const char *str)
{
char *p = Strdup(str);
if (trace(1)) {
- htrc("%.4d Duplicating to %p from %p %s %s\n", ++m, p, str, str, s);
+ htrc("%.4d Duplicating to %p from %p %-.256s %-.256s\n", ++m, p, str, str, s);
*s = 0;
} // endif trace
return p;
@@ -378,7 +378,7 @@ bool LIBXMLDOC::Initialize(PGLOBAL g, PCSZ entry, bool zipped)
if (zipped && InitZip(g, entry))
return true;
- int n = xmlKeepBlanksDefault(1);
+ int n __attribute__((unused))= xmlKeepBlanksDefault(1);
return MakeNSlist(g);
} // end of Initialize
@@ -448,7 +448,7 @@ bool LIBXMLDOC::NewDoc(PGLOBAL g, PCSZ ver)
void LIBXMLDOC::AddComment(PGLOBAL g, char *txtp)
{
if (trace(1))
- htrc("AddComment: %s\n", txtp);
+ htrc("AddComment: %-.256s\n", txtp);
xmlNodePtr cp = xmlNewDocComment(Docp, BAD_CAST txtp);
xmlAddChild((xmlNodePtr)Docp, cp);
@@ -476,7 +476,7 @@ PXNODE LIBXMLDOC::GetRoot(PGLOBAL g)
PXNODE LIBXMLDOC::NewRoot(PGLOBAL g, char *name)
{
if (trace(1))
- htrc("NewRoot: %s\n", name);
+ htrc("NewRoot: %-.256s\n", name);
xmlNodePtr root = xmlNewDocNode(Docp, NULL, BAD_CAST name, NULL);
@@ -494,7 +494,7 @@ PXNODE LIBXMLDOC::NewRoot(PGLOBAL g, char *name)
PXNODE LIBXMLDOC::NewPnode(PGLOBAL g, char *name)
{
if (trace(1))
- htrc("NewNode: %s\n", name);
+ htrc("NewNode: %-.256s\n", name);
xmlNodePtr nop;
@@ -535,7 +535,7 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
FILE *of;
if (trace(1))
- htrc("DumpDoc: %s\n", ofn);
+ htrc("DumpDoc: %-.256s\n", ofn);
if (!(of= global_fopen(g, MSGID_CANNOT_OPEN, ofn, "w")))
return -1;
@@ -554,8 +554,8 @@ int LIBXMLDOC::DumpDoc(PGLOBAL g, char *ofn)
xmlNodePtr Rootp;
// Save the modified document
- fprintf(of, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", Encoding);
- fprintf(of, "<!-- Created by CONNECT %s -->\n", version);
+ fprintf(of, "<?xml version=\"1.0\" encoding=\"%-.256s\"?>\n", Encoding);
+ fprintf(of, "<!-- Created by CONNECT %-.256s -->\n", version);
if (!(Rootp = xmlDocGetRootElement(Docp)))
return 1;
@@ -631,7 +631,7 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
xmlNodeSetPtr nl;
if (trace(1))
- htrc("GetNodeList: %s np=%p\n", xp, np);
+ htrc("GetNodeList: %-.256s np=%p\n", xp, np);
if (!Ctxp) {
// Init Xpath
@@ -648,7 +648,7 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
strcpy(g->Message, MSG(XPATH_CNTX_ERR));
if (trace(1))
- htrc("Context error: %s\n", g->Message);
+ htrc("Context error: %-.256s\n", g->Message);
return NULL;
} // endif xpathCtx
@@ -656,7 +656,7 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
// Register namespaces from list (if any)
for (PNS nsp = Namespaces; nsp; nsp = nsp->Next) {
if (trace(1))
- htrc("Calling xmlXPathRegisterNs Prefix=%s Uri=%s\n",
+ htrc("Calling xmlXPathRegisterNs Prefix=%-.256s Uri=%-.512s\n",
nsp->Prefix, nsp->Uri);
if (xmlXPathRegisterNs(Ctxp, BAD_CAST nsp->Prefix,
@@ -664,7 +664,7 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
sprintf(g->Message, MSG(REGISTER_ERR), nsp->Prefix, nsp->Uri);
if (trace(1))
- htrc("Ns error: %s\n", g->Message);
+ htrc("Ns error: %-.256s\n", g->Message);
return NULL;
} // endif Registering
@@ -699,14 +699,14 @@ xmlNodeSetPtr LIBXMLDOC::GetNodeList(PGLOBAL g, xmlNodePtr np, char *xp)
Ctxp->node = np;
if (trace(1))
- htrc("Calling xmlXPathEval %s Ctxp=%p\n", xp, Ctxp);
+ htrc("Calling xmlXPathEval %-.256s Ctxp=%p\n", xp, Ctxp);
// Evaluate table xpath
if (!(Xop = xmlXPathEval(BAD_CAST xp, Ctxp))) {
sprintf(g->Message, MSG(XPATH_EVAL_ERR), xp);
if (trace(1))
- htrc("Path error: %s\n", g->Message);
+ htrc("Path error: %-.256s\n", g->Message);
return NULL;
} else
@@ -882,14 +882,14 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len)
} // endif p1
} else {
- sprintf(g->Message, "Truncated %s content", Nodep->name);
+ sprintf(g->Message, "Truncated %-.256s content", Nodep->name);
rc = RC_INFO;
} // endif len
*p2 = 0;
if (trace(1))
- htrc("GetText buf='%s' len=%d\n", buf, len);
+ htrc("GetText buf='%-.256s' len=%d\n", buf, len);
xmlFree(Content);
Content = NULL;
@@ -897,7 +897,7 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len)
*buf = '\0';
if (trace(1))
- htrc("GetContent: %s\n", buf);
+ htrc("GetContent: %-.256s\n", buf);
return rc;
} // end of GetContent
@@ -908,12 +908,12 @@ RCODE XML2NODE::GetContent(PGLOBAL g, char *buf, int len)
bool XML2NODE::SetContent(PGLOBAL g, char *txtp, int len)
{
if (trace(1))
- htrc("SetContent: %s\n", txtp);
+ htrc("SetContent: %-.256s\n", txtp);
xmlChar *buf = xmlEncodeEntitiesReentrant(Docp, BAD_CAST txtp);
if (trace(1))
- htrc("SetContent: %s -> %s\n", txtp, buf);
+ htrc("SetContent: %-.256s -> %-.256s\n", txtp, buf);
xmlNodeSetContent(Nodep, buf);
xmlFree(buf);
@@ -942,7 +942,7 @@ PXNODE XML2NODE::Clone(PGLOBAL g, PXNODE np)
PXLIST XML2NODE::GetChildElements(PGLOBAL g, char *xp, PXLIST lp)
{
if (trace(1))
- htrc("GetChildElements: %s\n", xp);
+ htrc("GetChildElements: %-.256s\n", xp);
return SelectNodes(g, (xp) ? xp : (char*)"*", lp);
} // end of GetChildElements
@@ -953,7 +953,7 @@ PXLIST XML2NODE::GetChildElements(PGLOBAL g, char *xp, PXLIST lp)
PXLIST XML2NODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
{
if (trace(1))
- htrc("SelectNodes: %s\n", xp);
+ htrc("SelectNodes: %-.256s\n", xp);
xmlNodeSetPtr nl = ((PXDOC2)Doc)->GetNodeList(g, Nodep, xp);
@@ -971,7 +971,7 @@ PXLIST XML2NODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
PXNODE XML2NODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
{
if (trace(1))
- htrc("SelectSingleNode: %s\n", xp);
+ htrc("SelectSingleNode: %-.256s\n", xp);
xmlNodeSetPtr nl = ((PXDOC2)Doc)->GetNodeList(g, Nodep, xp);
@@ -995,7 +995,7 @@ PXATTR XML2NODE::GetAttribute(PGLOBAL g, char *name, PXATTR ap)
xmlAttrPtr atp;
if (trace(1))
- htrc("GetAttribute: %s\n", SVP(name));
+ htrc("GetAttribute: %-.256s\n", SVP(name));
if (name)
atp = xmlHasProp(Nodep, BAD_CAST name);
@@ -1024,7 +1024,7 @@ PXNODE XML2NODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np)
char *p, *pn, *pf = NULL, *nmp = PlugDup(g, name);
if (trace(1))
- htrc("AddChildNode: %s\n", name);
+ htrc("AddChildNode: %-.256s\n", name);
// Is a prefix specified
if ((pn = strchr(nmp, ':'))) {
@@ -1075,7 +1075,7 @@ PXNODE XML2NODE::AddChildNode(PGLOBAL g, PCSZ name, PXNODE np)
PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
{
if (trace(1))
- htrc("AddProperty: %s\n", name);
+ htrc("AddProperty: %-.256s\n", name);
xmlAttrPtr atp = xmlNewProp(Nodep, BAD_CAST name, NULL);
@@ -1098,7 +1098,7 @@ PXATTR XML2NODE::AddProperty(PGLOBAL g, char *name, PXATTR ap)
void XML2NODE::AddText(PGLOBAL g, PCSZ txtp)
{
if (trace(1))
- htrc("AddText: %s\n", txtp);
+ htrc("AddText: %-.256s\n", txtp);
// This is to avoid a blank line when inserting a new line
xmlNodePtr np = xmlGetLastChild(Nodep);
@@ -1158,7 +1158,7 @@ void XML2NODE::DeleteChild(PGLOBAL g, PXNODE dnp)
err:
if (trace(1))
- htrc("DeleteChild: errmsg=%s\n", xerr->message);
+ htrc("DeleteChild: errmsg=%-.256s\n", xerr->message);
xmlResetError(xerr);
} // end of DeleteChild
@@ -1260,7 +1260,7 @@ RCODE XML2ATTR::GetText(PGLOBAL g, char *buf, int len)
if (strlen((char*)txt) >= (unsigned)len) {
memcpy(buf, txt, len - 1);
buf[len - 1] = 0;
- sprintf(g->Message, "Truncated %s content", Atrp->name);
+ sprintf(g->Message, "Truncated %-.256s content", Atrp->name);
rc = RC_INFO;
} else
strcpy(buf, (const char*)txt);
@@ -1270,7 +1270,7 @@ RCODE XML2ATTR::GetText(PGLOBAL g, char *buf, int len)
*buf = '\0';
if (trace(1))
- htrc("GetText: %s\n", buf);
+ htrc("GetText: %-.256s\n", buf);
return rc;
} // end of GetText
@@ -1281,7 +1281,7 @@ RCODE XML2ATTR::GetText(PGLOBAL g, char *buf, int len)
bool XML2ATTR::SetText(PGLOBAL g, char *txtp, int len)
{
if (trace(1))
- htrc("SetText: %s %d\n", txtp, len);
+ htrc("SetText: %-.256s %d\n", txtp, len);
xmlSetProp(Parent, Atrp->name, BAD_CAST txtp);
return false;
diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp
index 87263b3adf6..9dcc564a86b 100644
--- a/storage/connect/maputil.cpp
+++ b/storage/connect/maputil.cpp
@@ -190,7 +190,7 @@ bool CloseMemMap(void *memory, size_t dwSize)
{
if (memory) {
// All this must be redesigned
- int rc = msync((char*)memory, dwSize, MS_SYNC);
+ int rc __attribute__((unused))= msync((char*)memory, dwSize, MS_SYNC);
return (munmap((char*)memory, dwSize) < 0) ? true : false;
} else
return false;
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 4303a9e191b..e07270aff8a 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -140,7 +140,7 @@ PQRYRES MyColumns(PGLOBAL g, THD *thd, const char *host, const char *db,
PCSZ fmt;
char *fld, *colname, *chset, v, buf[128], uns[16], zero[16];
int i, n, nf = 0, ncol = sizeof(buftyp) / sizeof(int);
- int len, type, prec, rc, k = 0;
+ int len, type, prec, rc;
bool b;
PQRYRES qrp;
PCOLRES crp;
diff --git a/storage/connect/mysql-test/connect/r/mysql_index.result b/storage/connect/mysql-test/connect/r/mysql_index.result
index dd1864529ca..e81caf671a4 100644
--- a/storage/connect/mysql-test/connect/r/mysql_index.result
+++ b/storage/connect/mysql-test/connect/r/mysql_index.result
@@ -45,10 +45,9 @@ id msg
SELECT * FROM t2 WHERE id IN (2,4) AND msg = 'Two';
id msg
2 Two
-SELECT * FROM t2 WHERE id > 3;
+SELECT * FROM t2 WHERE id > 4;
id msg
5 Cinq
-4 Four
6 Six
SELECT * FROM t2 WHERE id >= 3;
id msg
@@ -60,10 +59,9 @@ SELECT * FROM t2 WHERE id < 3;
id msg
1 Un
2 Two
-SELECT * FROM t2 WHERE id < 3 OR id > 4;
+SELECT * FROM t2 WHERE id < 2 OR id > 4;
id msg
1 Un
-2 Two
5 Cinq
6 Six
SELECT * FROM t2 WHERE id <= 3;
@@ -173,6 +171,9 @@ matricule nom prenom
5765 FOCH ROBERT
4080 FOCH SERGE
3368 MOGADOR ALAIN
+explain SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 range NP NP 18 NULL 4 Using where
SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR';
matricule nom prenom
1977 FOCH BERNADETTE
@@ -184,252 +185,252 @@ matricule nom prenom
3368 MOGADOR ALAIN
SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX';
matricule nom prenom
-4552 ABBADIE MONIQUE
+1122 ACACIAS SERGE
+115 ACHILLE JACQUES
+1340 ABBE MICHELE
+1644 ACARDIE BEATE
+2728 ABOUT CATHERINE MARIE
+2945 ABBEVILLE PASCAL
307 ABBAYE ANNICK
+3395 ADAM JEAN CLAUDE
+398 ABREUVOIR JEAN LUC
+4038 ADAM JANICK
+4552 ABBADIE MONIQUE
+6124 ABELIAS DELIA
+6314 ABERDEN EVELYNE
+6399 ABEILLES RENE
6627 ABBAYE GERALD
7961 ABBE KATIA
-1340 ABBE MICHELE
-9270 ABBE SOPHIE
-2945 ABBEVILLE PASCAL
8596 ABEBERRY PATRICK
-6399 ABEILLES RENE
8673 ABEL JEAN PIERRE
-6124 ABELIAS DELIA
-6314 ABERDEN EVELYNE
895 ABORD CHANTAL
-2728 ABOUT CATHERINE MARIE
-398 ABREUVOIR JEAN LUC
-1122 ACACIAS SERGE
-1644 ACARDIE BEATE
-115 ACHILLE JACQUES
-4038 ADAM JANICK
-3395 ADAM JEAN CLAUDE
+9270 ABBE SOPHIE
SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL';
matricule nom prenom
-4552 ABBADIE MONIQUE
+1340 ABBE MICHELE
+2945 ABBEVILLE PASCAL
307 ABBAYE ANNICK
+4552 ABBADIE MONIQUE
+6399 ABEILLES RENE
6627 ABBAYE GERALD
7961 ABBE KATIA
-1340 ABBE MICHELE
-9270 ABBE SOPHIE
-2945 ABBEVILLE PASCAL
8596 ABEBERRY PATRICK
-6399 ABEILLES RENE
8673 ABEL JEAN PIERRE
+9270 ABBE SOPHIE
SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON';
matricule nom prenom
-9742 YZENGREMER MICHEL
-8738 ZILINA JEAN LOUIS
-5357 ZOLA BERNARD
-5441 ZOLA BRIGITTE
1325 ZOLA CHRISTINE
-4859 ZORI CATHERINE
4102 ZOUAVES ALAIN
-SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
-matricule nom prenom
-5389 YVON CAROLE
-9742 YZENGREMER MICHEL
-8738 ZILINA JEAN LOUIS
+4859 ZORI CATHERINE
5357 ZOLA BERNARD
5441 ZOLA BRIGITTE
+8738 ZILINA JEAN LOUIS
+9742 YZENGREMER MICHEL
+SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
+matricule nom prenom
1325 ZOLA CHRISTINE
-4859 ZORI CATHERINE
4102 ZOUAVES ALAIN
+4859 ZORI CATHERINE
+5357 ZOLA BERNARD
+5389 YVON CAROLE
+5441 ZOLA BRIGITTE
+8738 ZILINA JEAN LOUIS
+9742 YZENGREMER MICHEL
SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON';
matricule nom prenom
-4552 ABBADIE MONIQUE
+1325 ZOLA CHRISTINE
+1340 ABBE MICHELE
+2945 ABBEVILLE PASCAL
307 ABBAYE ANNICK
+4102 ZOUAVES ALAIN
+4552 ABBADIE MONIQUE
+4859 ZORI CATHERINE
+5357 ZOLA BERNARD
+5441 ZOLA BRIGITTE
+6399 ABEILLES RENE
6627 ABBAYE GERALD
7961 ABBE KATIA
-1340 ABBE MICHELE
-9270 ABBE SOPHIE
-2945 ABBEVILLE PASCAL
8596 ABEBERRY PATRICK
-6399 ABEILLES RENE
8673 ABEL JEAN PIERRE
-9742 YZENGREMER MICHEL
8738 ZILINA JEAN LOUIS
-5357 ZOLA BERNARD
-5441 ZOLA BRIGITTE
-1325 ZOLA CHRISTINE
-4859 ZORI CATHERINE
-4102 ZOUAVES ALAIN
+9270 ABBE SOPHIE
+9742 YZENGREMER MICHEL
SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS';
matricule nom prenom
-9096 HELENA PHILIPPE
+1291 HERMITAGE XAVIER
+2085 HEOL GUY PAUL
+2579 HERANDIERE PIERRE
+2673 HENNER LILIANE
3309 HELENE ISABELLE
-8365 HELIOTROPES LISE
+403 HERMITTE PHILIPPE
+4050 HERBILLON FRANCOIS
+4254 HENIN SERGE
4666 HELLEN PIERRE
5781 HELSINKI DANIELLE
-7626 HENIN PHILIPPE
-4254 HENIN SERGE
-2673 HENNER LILIANE
-9716 HENRI JACQUES
-2085 HEOL GUY PAUL
-2579 HERANDIERE PIERRE
+6185 HERMITTE FRANCOIS
7093 HERAULTS DANIEL
-4050 HERBILLON FRANCOIS
+7626 HENIN PHILIPPE
+8365 HELIOTROPES LISE
+9096 HELENA PHILIPPE
9231 HERBILLON MADELEINE
-1291 HERMITAGE XAVIER
-6185 HERMITTE FRANCOIS
-403 HERMITTE PHILIPPE
+9716 HENRI JACQUES
9749 HEROLD ISABELLE
SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS';
matricule nom prenom
-6199 HELEN MARTIAL
-9096 HELENA PHILIPPE
+1291 HERMITAGE XAVIER
+2085 HEOL GUY PAUL
+2579 HERANDIERE PIERRE
+2673 HENNER LILIANE
3309 HELENE ISABELLE
-8365 HELIOTROPES LISE
+403 HERMITTE PHILIPPE
+4050 HERBILLON FRANCOIS
+4254 HENIN SERGE
4666 HELLEN PIERRE
5781 HELSINKI DANIELLE
-7626 HENIN PHILIPPE
-4254 HENIN SERGE
-2673 HENNER LILIANE
-9716 HENRI JACQUES
-2085 HEOL GUY PAUL
-2579 HERANDIERE PIERRE
+6185 HERMITTE FRANCOIS
+6199 HELEN MARTIAL
7093 HERAULTS DANIEL
-4050 HERBILLON FRANCOIS
+7626 HENIN PHILIPPE
+8365 HELIOTROPES LISE
+8445 HEROS SYLVIE
+9096 HELENA PHILIPPE
9231 HERBILLON MADELEINE
-1291 HERMITAGE XAVIER
-6185 HERMITTE FRANCOIS
-403 HERMITTE PHILIPPE
+9716 HENRI JACQUES
9749 HEROLD ISABELLE
-8445 HEROS SYLVIE
SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE';
matricule nom prenom
-9096 HELENA PHILIPPE
-7626 HENIN PHILIPPE
403 HERMITTE PHILIPPE
+7626 HENIN PHILIPPE
+9096 HELENA PHILIPPE
SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10;
matricule nom prenom
+1340 ABBE MICHELE
+2945 ABBEVILLE PASCAL
+307 ABBAYE ANNICK
4552 ABBADIE MONIQUE
+6399 ABEILLES RENE
6627 ABBAYE GERALD
-307 ABBAYE ANNICK
7961 ABBE KATIA
-1340 ABBE MICHELE
-9270 ABBE SOPHIE
-2945 ABBEVILLE PASCAL
8596 ABEBERRY PATRICK
-6399 ABEILLES RENE
8673 ABEL JEAN PIERRE
+9270 ABBE SOPHIE
SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom;
nom prenom nom
-FOCH SERGE ACACIAS
-FOCH ROBERT AGRIANT
-FOCH JOCELYNE ALEXIS
+FOCH BERNADETTE BERTIN
+FOCH BERNADETTE BOISSY
+FOCH BERNADETTE HUNTZIGER
+FOCH BERNADETTE LATECOERE
+FOCH BERNADETTE LEGER
+FOCH BERNADETTE MONTJUSTIN
+FOCH BERNADETTE ONZE
+FOCH BERNADETTE PALMAROLE
+FOCH BERNADETTE PLOUHARNEL
FOCH DENIS AMBOISE
-FOCH SERGE ANDALUCIA
-FOCH ROBERT ANNECY
-FOCH SERGE ARCACHON
-FOCH JOCELYNE AUGUSTE
-FOCH JOCELYNE BASSE
-FOCH SERGE BEACH
-FOCH FRANCK BEARN
-FOCH SERGE BELLES
FOCH DENIS BERARD
FOCH DENIS BERIN
-FOCH BERNADETTE BERTIN
FOCH DENIS BILLEHOU
FOCH DENIS BOILEAU
-FOCH BERNADETTE BOISSY
-FOCH ROBERT BONVIN
-FOCH SERGE BOUTON
-FOCH SERGE BREUIL
-FOCH SERGE CARREFOUR
-FOCH JOCELYNE CARRERE
-FOCH JOCELYNE CHAPELLE
-FOCH SERGE CHATEAU
-FOCH ROBERT CHENIER
-FOCH SERGE COLLETTE
FOCH DENIS CONNE
-FOCH SERGE COOLE
FOCH DENIS COULOUBRIER
FOCH DENIS COUTURIER
-FOCH ROBERT CURAT
-FOCH ROBERT DAUDET
-FOCH SERGE ECLUSE
-FOCH SERGE EGUILLON
FOCH DENIS EPINETTES
FOCH DENIS FIGOURNAS
-FOCH JOCELYNE FLEMING
-FOCH JOCELYNE GAMBADES
-FOCH ROBERT GIOTERAIE
-FOCH SERGE GOAS
-FOCH ROBERT GRAFFIANE
-FOCH SERGE GREFFIER
-FOCH ROBERT GUILLOTIERE
-FOCH SERGE HENIN
-FOCH BERNADETTE HUNTZIGER
-FOCH FRANCK ILLIERS
FOCH DENIS ISTANBUL
FOCH DENIS ITALIE
-FOCH SERGE JARDIN
+FOCH DENIS LACATE
+FOCH DENIS MAROLLES
+FOCH DENIS MONTELIER
+FOCH DENIS MONTILS
+FOCH DENIS POINTE
+FOCH DENIS PORTO
+FOCH DENIS REINOTS
+FOCH DENIS REMPART
+FOCH DENIS ROUSSIER
+FOCH DENIS TORTE
+FOCH DENIS TOULON
+FOCH DENIS VALMANTE
+FOCH FRANCK BEARN
+FOCH FRANCK ILLIERS
FOCH FRANCK JEANPIERRE
-FOCH JOCELYNE KENNEDY
FOCH FRANCK LABBE
-FOCH DENIS LACATE
FOCH FRANCK LACOMBE
-FOCH ROBERT LAMOTHE
-FOCH BERNADETTE LATECOERE
-FOCH BERNADETTE LEGER
-FOCH SERGE LEONIE
FOCH FRANCK LEROY
-FOCH SERGE LOZERE
-FOCH DENIS MAROLLES
-FOCH ROBERT MARRONIERS
-FOCH SERGE MARSAT
-FOCH SERGE MONTAGNE
FOCH FRANCK MONTALEIGNE
-FOCH DENIS MONTELIER
-FOCH DENIS MONTILS
-FOCH BERNADETTE MONTJUSTIN
-FOCH SERGE MORIZET
-FOCH ROBERT NIMES
-FOCH ROBERT NORD
-FOCH SERGE NOVEMBRE
-FOCH BERNADETTE ONZE
-FOCH SERGE ORANGERIE
FOCH FRANCK ORVEAU
-FOCH BERNADETTE PALMAROLE
+FOCH FRANCK PURPAN
+FOCH FRANCK ROCQUENCOURT
+FOCH FRANCK RUSSIE
+FOCH JOCELYNE ALEXIS
+FOCH JOCELYNE AUGUSTE
+FOCH JOCELYNE BASSE
+FOCH JOCELYNE CARRERE
+FOCH JOCELYNE CHAPELLE
+FOCH JOCELYNE FLEMING
+FOCH JOCELYNE GAMBADES
+FOCH JOCELYNE KENNEDY
FOCH JOCELYNE PEYBERT
+FOCH JOCELYNE PIED
+FOCH JOCELYNE PONTAROUX
+FOCH ROBERT AGRIANT
+FOCH ROBERT ANNECY
+FOCH ROBERT BONVIN
+FOCH ROBERT CHENIER
+FOCH ROBERT CURAT
+FOCH ROBERT DAUDET
+FOCH ROBERT GIOTERAIE
+FOCH ROBERT GRAFFIANE
+FOCH ROBERT GUILLOTIERE
+FOCH ROBERT LAMOTHE
+FOCH ROBERT MARRONIERS
+FOCH ROBERT NIMES
+FOCH ROBERT NORD
FOCH ROBERT PEYNIBLOU
FOCH ROBERT PIECE
-FOCH JOCELYNE PIED
FOCH ROBERT PLAGNE
-FOCH SERGE PLAISANCE
-FOCH BERNADETTE PLOUHARNEL
-FOCH DENIS POINTE
FOCH ROBERT POMMERY
-FOCH JOCELYNE PONTAROUX
-FOCH DENIS PORTO
FOCH ROBERT PRESIDENT
FOCH ROBERT PUJADE
-FOCH FRANCK PURPAN
FOCH ROBERT QUILICHINI
-FOCH DENIS REINOTS
-FOCH DENIS REMPART
-FOCH SERGE RESISTANCE
-FOCH SERGE RESTANQUES
FOCH ROBERT RIOU
-FOCH FRANCK ROCQUENCOURT
FOCH ROBERT ROLL
FOCH ROBERT ROSSA
-FOCH SERGE ROSSAYS
-FOCH DENIS ROUSSIER
-FOCH FRANCK RUSSIE
FOCH ROBERT SABLONS
-FOCH SERGE SARTRE
-FOCH SERGE SAVIGNAC
-FOCH SERGE SEGUR
FOCH ROBERT STRASBOURG
FOCH ROBERT TIRE
-FOCH DENIS TORTE
-FOCH DENIS TOULON
FOCH ROBERT TUBY
-FOCH DENIS VALMANTE
-FOCH SERGE VANOEL
FOCH ROBERT VIARMES
+FOCH SERGE ACACIAS
+FOCH SERGE ANDALUCIA
+FOCH SERGE ARCACHON
+FOCH SERGE BEACH
+FOCH SERGE BELLES
+FOCH SERGE BOUTON
+FOCH SERGE BREUIL
+FOCH SERGE CARREFOUR
+FOCH SERGE CHATEAU
+FOCH SERGE COLLETTE
+FOCH SERGE COOLE
+FOCH SERGE ECLUSE
+FOCH SERGE EGUILLON
+FOCH SERGE GOAS
+FOCH SERGE GREFFIER
+FOCH SERGE HENIN
+FOCH SERGE JARDIN
+FOCH SERGE LEONIE
+FOCH SERGE LOZERE
+FOCH SERGE MARSAT
+FOCH SERGE MONTAGNE
+FOCH SERGE MORIZET
+FOCH SERGE NOVEMBRE
+FOCH SERGE ORANGERIE
+FOCH SERGE PLAISANCE
+FOCH SERGE RESISTANCE
+FOCH SERGE RESTANQUES
+FOCH SERGE ROSSAYS
+FOCH SERGE SARTRE
+FOCH SERGE SAVIGNAC
+FOCH SERGE SEGUR
+FOCH SERGE VANOEL
FOCH SERGE WILSON
DROP TABLE t2;
DROP TABLE t1;
diff --git a/storage/connect/mysql-test/connect/r/part_file.result b/storage/connect/mysql-test/connect/r/part_file.result
index c679ed95062..3dabd946b50 100644
--- a/storage/connect/mysql-test/connect/r/part_file.result
+++ b/storage/connect/mysql-test/connect/r/part_file.result
@@ -145,14 +145,11 @@ id select_type table partitions type possible_keys key key_len ref rows Extra
SELECT * FROM t1 WHERE id = 10;
rwid rnum prtn tbn fid id msg
1 1 2 t1 part2 10 ten
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 10;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 40;
id select_type table partitions type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 2,3 range PRIMARY PRIMARY 4 NULL 7 Using where
-SELECT * FROM t1 WHERE id >= 10;
+1 SIMPLE t1 2,3 range PRIMARY PRIMARY 4 NULL 4 Using where
+SELECT * FROM t1 WHERE id >= 40;
rwid rnum prtn tbn fid id msg
-1 1 2 t1 part2 10 ten
-3 3 2 t1 part2 20 twenty
-4 4 2 t1 part2 35 thirty five
2 2 2 t1 part2 40 forty
1 1 3 t1 part3 60 sixty
3 3 3 t1 part3 72 seventy two
diff --git a/storage/connect/mysql-test/connect/r/xml2_mult.result b/storage/connect/mysql-test/connect/r/xml2_mult.result
index 87d1118edd5..07c86d961e1 100644
--- a/storage/connect/mysql-test/connect/r/xml2_mult.result
+++ b/storage/connect/mysql-test/connect/r/xml2_mult.result
@@ -74,6 +74,8 @@ Warnings:
Warning 1105 Truncated author content
# increase author size
ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
+Warnings:
+Warning 1105 This is an outward table, table data were not modified.
SELECT * FROM bookstore;
category title lang author year price
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
diff --git a/storage/connect/mysql-test/connect/r/xml_mult.result b/storage/connect/mysql-test/connect/r/xml_mult.result
index 9922b40060c..c786a80819c 100644
--- a/storage/connect/mysql-test/connect/r/xml_mult.result
+++ b/storage/connect/mysql-test/connect/r/xml_mult.result
@@ -72,6 +72,8 @@ Warnings:
Warning 1105 Truncated author content
# increase author size
ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
+Warnings:
+Warning 1105 This is an outward table, table data were not modified.
SELECT * FROM bookstore;
category title lang author year price
COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
diff --git a/storage/connect/mysql-test/connect/t/mysql_index.test b/storage/connect/mysql-test/connect/t/mysql_index.test
index 81fdcad9330..ebc4965e8e1 100644
--- a/storage/connect/mysql-test/connect/t/mysql_index.test
+++ b/storage/connect/mysql-test/connect/t/mysql_index.test
@@ -49,10 +49,10 @@ SELECT * FROM t2;
SELECT * FROM t2 WHERE id = 3;
SELECT * FROM t2 WHERE id IN (2,4);
SELECT * FROM t2 WHERE id IN (2,4) AND msg = 'Two';
-SELECT * FROM t2 WHERE id > 3;
+SELECT * FROM t2 WHERE id > 4;
SELECT * FROM t2 WHERE id >= 3;
SELECT * FROM t2 WHERE id < 3;
-SELECT * FROM t2 WHERE id < 3 OR id > 4;
+SELECT * FROM t2 WHERE id < 2 OR id > 4;
SELECT * FROM t2 WHERE id <= 3;
SELECT * FROM t2 WHERE id BETWEEN 3 AND 5;
SELECT * FROM t2 WHERE id > 2 AND id < 6;
@@ -111,16 +111,28 @@ CREATE TABLE t2
) ENGINE=CONNECT TABLE_TYPE=MYSQL CONNECTIOn='mysql://root@localhost/test/t1';
SELECT * FROM t2 limit 10;
SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
+--sorted_result
+explain SELECT matricule, nom, prenom FROM t2 WHERE nom IN ('FOCH','MOGADOR');
SELECT matricule, nom, prenom FROM t2 WHERE nom = 'FOCH' OR nom = 'MOGADOR';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom < 'ADDAX';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom > 'YVON';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom >= 'YVON';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom <= 'ABEL' OR nom > 'YVON';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom > 'HELEN' AND nom < 'HEROS';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 WHERE nom BETWEEN 'HELEN' AND 'HEROS' AND prenom = 'PHILIPPE';
+--sorted_result
SELECT matricule, nom, prenom FROM t2 ORDER BY nom LIMIT 10;
+--sorted_result
SELECT a.nom, a.prenom, b.nom FROM t1 a STRAIGHT_JOIN t2 b ON a.prenom = b.prenom WHERE a.nom = 'FOCH' AND a.nom != b.nom;
DROP TABLE t2;
diff --git a/storage/connect/mysql-test/connect/t/part_file.test b/storage/connect/mysql-test/connect/t/part_file.test
index 8ee43a917ec..2e5127f03e5 100644
--- a/storage/connect/mysql-test/connect/t/part_file.test
+++ b/storage/connect/mysql-test/connect/t/part_file.test
@@ -82,8 +82,8 @@ SELECT * FROM t1;
SELECT * FROM t1 order by id;
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id = 10;
SELECT * FROM t1 WHERE id = 10;
-EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 10;
-SELECT * FROM t1 WHERE id >= 10;
+EXPLAIN PARTITIONS SELECT * FROM t1 WHERE id >= 40;
+SELECT * FROM t1 WHERE id >= 40;
SELECT count(*) FROM t1 WHERE id < 10;
SELECT case when id < 10 then 1 when id < 50 then 2 else 3 end as pn, count(*) FROM t1 group by pn;
SELECT prtn, count(*) FROM t1 group by prtn;
diff --git a/storage/connect/myutil.cpp b/storage/connect/myutil.cpp
index 338a79d9455..89b18f86323 100644
--- a/storage/connect/myutil.cpp
+++ b/storage/connect/myutil.cpp
@@ -66,6 +66,7 @@ int MYSQLtoPLG(char *typname, char *var)
break;
case TPC_SKIP:
*var = 'K';
+ /* falls through */
default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
@@ -237,13 +238,14 @@ int MYSQLtoPLG(int mytype, char *var)
break;
case TPC_SKIP:
*var = 'K'; // Skip
+ /* falls through */
default: // TPC_NO
type = TYPE_ERROR;
} // endswitch xconv
return type;
} // endif var
-
+ /* falls through */
default:
type = TYPE_ERROR;
} // endswitch mytype
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index e296553d8e2..d51d52a2678 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -430,6 +430,7 @@ char *ExtractFromPath(PGLOBAL g, char *pBuff, char *FileName, OPVAL op)
/* Because this function is only used for catalog name checking, */
/* it must be case insensitive. */
/***********************************************************************/
+#ifdef NOT_USED
static bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat)
{
if (pat && strlen(pat)) {
@@ -443,6 +444,7 @@ static bool PlugCheckPattern(PGLOBAL g, LPCSTR string, LPCSTR pat)
return true;
} // end of PlugCheckPattern
+#endif
/***********************************************************************/
/* PlugEvalLike: evaluates a LIKE clause. */
diff --git a/storage/connect/plugutil.cpp b/storage/connect/plugutil.cpp
index e74937b942a..3899379ade2 100644
--- a/storage/connect/plugutil.cpp
+++ b/storage/connect/plugutil.cpp
@@ -147,7 +147,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
PGLOBAL g;
if (trace(2))
- htrc("PlugInit: Language='%s'\n",
+ htrc("PlugInit: Language='%-.256s'\n",
((!Language) ? "Null" : (char*)Language));
try {
@@ -216,15 +216,15 @@ LPSTR PlugRemoveType(LPSTR pBuff, LPCSTR FileName)
_splitpath(FileName, drive, direc, fname, ftype);
if (trace(2)) {
- htrc("after _splitpath: FileName=%s\n", FileName);
- htrc("drive=%s dir=%s fname=%s ext=%s\n",
+ htrc("after _splitpath: FileName=%-.256s\n", FileName);
+ htrc("drive=%-.256s dir=%-.256s fname=%-.256s ext=%-.256s\n",
SVP(drive), direc, fname, ftype);
} // endif trace
_makepath(pBuff, drive, direc, fname, "");
if (trace(2))
- htrc("buff='%s'\n", pBuff);
+ htrc("buff='%-.256s'\n", pBuff);
return pBuff;
} // end of PlugRemoveType
@@ -257,7 +257,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
#endif
if (trace(2))
- htrc("prefix=%s fn=%s path=%s\n", prefix, FileName, defpath);
+ htrc("prefix=%-.256s fn=%-.256s path=%-.256s\n", prefix, FileName, defpath);
if (!strncmp(FileName, "//", 2) || !strncmp(FileName, "\\\\", 2)) {
strcpy(pBuff, FileName); // Remote file
@@ -274,7 +274,7 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
if (*FileName == '~') {
if (_fullpath(pBuff, FileName, _MAX_PATH)) {
if (trace(2))
- htrc("pbuff='%s'\n", pBuff);
+ htrc("pbuff='%-.256s'\n", pBuff);
return pBuff;
} else
@@ -309,12 +309,12 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
_splitpath(tmpdir, defdrv, defdir, NULL, NULL);
if (trace(2)) {
- htrc("after _splitpath: FileName=%s\n", FileName);
+ htrc("after _splitpath: FileName=%-.256s\n", FileName);
#if defined(__WIN__)
- htrc("drive=%s dir=%s fname=%s ext=%s\n", drive, direc, fname, ftype);
- htrc("defdrv=%s defdir=%s\n", defdrv, defdir);
+ htrc("drive=%-.256s dir=%-.256s fname=%-.256s ext=%-.256s\n", drive, direc, fname, ftype);
+ htrc("defdrv=%-.256s defdir=%-.256s\n", defdrv, defdir);
#else
- htrc("dir=%s fname=%s ext=%s\n", direc, fname, ftype);
+ htrc("dir=%-.256s fname=%-.256s ext=%-.256s\n", direc, fname, ftype);
#endif
} // endif trace
@@ -336,11 +336,11 @@ LPCSTR PlugSetPath(LPSTR pBuff, LPCSTR prefix, LPCSTR FileName, LPCSTR defpath)
_makepath(newname, drive, direc, fname, ftype);
if (trace(2))
- htrc("newname='%s'\n", newname);
+ htrc("newname='%-.256s'\n", newname);
if (_fullpath(pBuff, newname, _MAX_PATH)) {
if (trace(2))
- htrc("pbuff='%s'\n", pBuff);
+ htrc("pbuff='%-.256s'\n", pBuff);
return pBuff;
} else
@@ -365,22 +365,22 @@ char *PlugReadMessage(PGLOBAL g, int mid, char *m)
PlugSetPath(msgfile, NULL, buff, msg_path);
if (!(mfile = fopen(msgfile, "rt"))) {
- sprintf(stmsg, "Fail to open message file %s", msgfile);
+ sprintf(stmsg, "Fail to open message file %-.256s", msgfile);
goto err;
} // endif mfile
for (;;)
if (!fgets(buff, 256, mfile)) {
- sprintf(stmsg, "Cannot get message %d %s", mid, SVP(m));
+ sprintf(stmsg, "Cannot get message %d %-.256s", mid, SVP(m));
goto fin;
} else
if (atoi(buff) == mid)
break;
- if (sscanf(buff, " %*d %s \"%[^\"]", msgid, stmsg) < 2) {
+ if (sscanf(buff, " %*d %-.256s \"%[^\"]", msgid, stmsg) < 2) {
// Old message file
if (!sscanf(buff, " %*d \"%[^\"]", stmsg)) {
- sprintf(stmsg, "Bad message file for %d %s", mid, SVP(m));
+ sprintf(stmsg, "Bad message file for %d %-.256s", mid, SVP(m));
goto fin;
} else
m = NULL;
@@ -485,7 +485,7 @@ bool AllocSarea(PGLOBAL g, uint size)
if (g->Sarea)
htrc("Work area of %u allocated at %p\n", size, g->Sarea);
else
- htrc("SareaAlloc: %s\n", g->Message);
+ htrc("SareaAlloc: %-.256s\n", g->Message);
} // endif trace
@@ -567,11 +567,11 @@ void *PlugSubAlloc(PGLOBAL g, void *memp, size_t size)
PCSZ pname = "Work";
sprintf(g->Message,
- "Not enough memory in %s area for request of %u (used=%d free=%d)",
+ "Not enough memory in %-.256s area for request of %u (used=%d free=%d)",
pname, (uint)size, pph->To_Free, pph->FreeBlk);
if (trace(1))
- htrc("PlugSubAlloc: %s\n", g->Message);
+ htrc("PlugSubAlloc: %-.256s\n", g->Message);
DoThrow(1234);
} /* endif size OS32 code */
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
index 2d3c6a6aacd..5b97377db97 100644
--- a/storage/connect/reldef.cpp
+++ b/storage/connect/reldef.cpp
@@ -350,8 +350,6 @@ RECFM TABDEF::GetTableFormat(const char* type)
bool TABDEF::Define(PGLOBAL g, PCATLG cat,
LPCSTR name, LPCSTR schema, LPCSTR am)
{
- int poff = 0;
-
Hc = ((MYCAT*)cat)->GetHandler();
Name = (PSZ)name;
Schema = (PSZ)Hc->GetDBName(schema);
@@ -430,6 +428,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
case RECFM_CSV:
case RECFM_FMT:
nlg+= nof;
+ /* falls through */
case RECFM_DIR:
case RECFM_XML:
poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1);
@@ -472,6 +471,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g)
switch (trf ) {
case RECFM_VCT:
cdp->SetOffset(0); // Not to have shift
+ /* falls through */
case RECFM_BIN:
// BIN/VEC are packed by default
if (nof) {
diff --git a/storage/connect/tabdos.cpp b/storage/connect/tabdos.cpp
index 8efe2aad702..3d8e89f3f3c 100644
--- a/storage/connect/tabdos.cpp
+++ b/storage/connect/tabdos.cpp
@@ -569,8 +569,6 @@ int TDBDOS::ResetTableOpt(PGLOBAL g, bool dop, bool dox)
MaxSize = -1; // Size must be recalculated
Cardinal = -1; // as well as Cardinality
- PTXF xp = Txfp;
-
To_Filter = NULL; // Disable filtering
//To_BlkIdx = NULL; // and index filtering
To_BlkFil = NULL; // and block filtering
@@ -642,7 +640,7 @@ int TDBDOS::MakeBlockValues(PGLOBAL g)
PDOSDEF defp = (PDOSDEF)To_Def;
PDOSCOL colp = NULL;
PDBUSER dup = PlgGetUser(g);
- PCATLG cat = defp->GetCat();
+ PCATLG cat __attribute__((unused))= defp->GetCat();
//void *memp = cat->GetDescp();
if ((nrec = defp->GetElemt()) < 2) {
@@ -1005,14 +1003,14 @@ bool TDBDOS::GetBlockValues(PGLOBAL g)
{
char filename[_MAX_PATH];
int i, lg, n[NZ];
- int nrec, block = 0, last = 0, allocblk = 0;
+ int nrec, block = 0, last = 0;
int len;
bool newblk = false;
size_t ndv, nbm, nbk, blk;
FILE *opfile;
PCOLDEF cdp;
PDOSDEF defp = (PDOSDEF)To_Def;
- PCATLG cat = defp->GetCat();
+ PCATLG cat __attribute__((unused))= defp->GetCat();
PDBUSER dup = PlgGetUser(g);
#if 0
@@ -1294,7 +1292,7 @@ PBF TDBDOS::InitBlockFilter(PGLOBAL g, PFIL filp)
} // endif blk
- int i, op = filp->GetOpc(), opm = filp->GetOpm(), n = 0;
+ int i, op = filp->GetOpc(), opm = filp->GetOpm();
bool cnv[2];
PCOL colp;
PXOB arg[2] = {NULL,NULL};
@@ -1337,13 +1335,14 @@ PBF TDBDOS::InitBlockFilter(PGLOBAL g, PFIL filp)
bfp = new(g) BLKSPCIN(g, this, op, opm, arg, Txfp->Nrec);
} else if (blk && Txfp->Nrec > 1 && colp->IsClustered())
+ {
// Clustered column and constant array
if (colp->GetClustered() == 2)
bfp = new(g) BLKFILIN2(g, this, op, opm, arg);
else
bfp = new(g) BLKFILIN(g, this, op, opm, arg);
-
- } // endif this
+ }
+ } // endif this
#if 0
} else if (filp->GetArgType(0) == TYPE_SCALF &&
@@ -1419,12 +1418,10 @@ PBF TDBDOS::CheckBlockFilari(PGLOBAL g, PXOB *arg, int op, bool *cnv)
//bool conv = false, xdb2 = false, ok = false, b[2];
//PXOB *xarg1, *xarg2 = NULL, xp[2];
int i, n = 0, type[2] = {0,0};
- bool conv = false, xdb2 = false, ok = false;
- PXOB *xarg2 = NULL, xp[2];
+ bool conv = false, xdb2 = false;
+ PXOB xp[2];
PCOL colp;
-//LSTVAL *vlp = NULL;
-//SFROW *sfr[2];
- PBF *fp = NULL, bfp = NULL;
+ PBF bfp = NULL;
for (i = 0; i < 2; i++) {
switch (arg[i]->GetType()) {
@@ -1655,7 +1652,7 @@ int TDBDOS::TestBlock(PGLOBAL g)
int TDBDOS::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
{
int k, n, rc = RC_OK;
- bool fixed, doit, sep, b = (pxdf != NULL);
+ bool fixed, doit, sep;
PCOL *keycols, colp;
PIXDEF xdp, sxp = NULL;
PKPDEF kdp;
@@ -2831,6 +2828,7 @@ bool DOSCOL::SetBitMap(PGLOBAL g)
bool DOSCOL::CheckSorted(PGLOBAL g)
{
if (Sorted)
+ {
if (OldVal) {
// Verify whether this column is sorted all right
if (OldVal->CompareValue(Value) > 0) {
@@ -2843,7 +2841,7 @@ bool DOSCOL::CheckSorted(PGLOBAL g)
} else
OldVal = AllocateValue(g, Value);
-
+ }
return false;
} // end of CheckSorted
diff --git a/storage/connect/tabext.cpp b/storage/connect/tabext.cpp
index e9c7b2490d8..aaf14f123c6 100644
--- a/storage/connect/tabext.cpp
+++ b/storage/connect/tabext.cpp
@@ -342,7 +342,6 @@ bool TDBEXT::MakeSQL(PGLOBAL g, bool cnt)
char *catp = NULL, buf[NAM_LEN * 3];
int len;
bool first = true;
- PTABLE tablep = To_Table;
PCOL colp;
if (Srcdef)
@@ -455,6 +454,7 @@ void TDBEXT::RemoveConst(PGLOBAL g, char *stmt)
int n, nc;
while ((p = strstr(stmt, "NAME_CONST")))
+ {
if ((n = sscanf(p, "%*[^,],%1024[^)])%n", val, &nc))) {
if (trace(33))
htrc("p=%s\nn=%d val=%s nc=%d\n", p, n, val, nc);
@@ -478,8 +478,8 @@ void TDBEXT::RemoveConst(PGLOBAL g, char *stmt)
} else
break;
-
- return;
+ }
+ return;
} // end of RemoveConst
/***********************************************************************/
diff --git a/storage/connect/tabfmt.cpp b/storage/connect/tabfmt.cpp
index b395c49c95d..eed67525f78 100644
--- a/storage/connect/tabfmt.cpp
+++ b/storage/connect/tabfmt.cpp
@@ -312,12 +312,13 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info)
} else if (*p == q) {
if (phase == 0) {
if (blank)
+ {
if (++nerr > mxr) {
sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
goto err;
} else
goto skip;
-
+ }
n = 0;
phase = digit = 1;
} else if (phase == 1) {
@@ -342,12 +343,13 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info)
} else {
if (phase == 2)
+ {
if (++nerr > mxr) {
sprintf(g->Message, MSG(MISPLACED_QUOTE), num_read);
goto err;
} else
goto skip;
-
+ }
// isdigit cannot be used here because of debug assert
if (!strchr("0123456789", *p)) {
if (!digit && *p == dechar)
@@ -363,12 +365,13 @@ PQRYRES CSVColumns(PGLOBAL g, PCSZ dp, PTOS topt, bool info)
} // endif's *p
if (phase == 1)
+ {
if (++nerr > mxr) {
sprintf(g->Message, MSG(UNBALANCE_QUOTE), num_read);
goto err;
} else
goto skip;
-
+ }
if (n) {
len[i] = MY_MAX(len[i], n);
type = (digit || n == 0 || (dec && n == 1)) ? TYPE_STRING
@@ -742,6 +745,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
PCSVCOL colp;
if (!Fields) // May have been set in TABFMT::OpenDB
+ {
if (Mode != MODE_UPDATE && Mode != MODE_INSERT) {
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
if (!colp->IsSpecial() && !colp->IsVirtual())
@@ -754,7 +758,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
for (cdp = tdp->GetCols(); cdp; cdp = cdp->GetNext())
if (!cdp->IsSpecial() && !cdp->IsVirtual())
Fields++;
-
+ }
Offset = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);
Fldlen = (int*)PlugSubAlloc(g, NULL, sizeof(int) * Fields);
@@ -775,6 +779,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
} // endfor i
if (Field)
+ {
// Prepare writing fields
if (Mode != MODE_UPDATE) {
for (colp = (PCSVCOL)Columns; colp; colp = (PCSVCOL)colp->Next)
@@ -797,7 +802,7 @@ bool TDBCSV::OpenDB(PGLOBAL g)
Fldlen[i] = len;
Fldtyp[i] = IsTypeNum(cdp->GetType());
} // endif cdp
-
+ }
} // endif Use
if (Header) {
@@ -1047,6 +1052,7 @@ bool TDBCSV::PrepareWriting(PGLOBAL g)
strcat(To_Line, sep);
if (Field[i])
+ {
if (!strlen(Field[i])) {
// Generally null fields are not quoted
if (Quoted > 2)
@@ -1075,7 +1081,7 @@ bool TDBCSV::PrepareWriting(PGLOBAL g)
else
strcat(To_Line, Field[i]);
-
+ }
} // endfor i
#if defined(_DEBUG)
@@ -1135,6 +1141,7 @@ int TDBCSV::CheckWrite(PGLOBAL g)
n += (Quoted > 2 ? 2 : 0);
else if (strchr(Field[i], Sep) || (Qot && *Field[i] == Qot)
|| Quoted > 1 || (Quoted == 1 && !Fldtyp[i]))
+ {
if (!Qot) {
sprintf(g->Message, MSG(SEP_IN_FIELD), i + 1);
return -1;
@@ -1147,7 +1154,7 @@ int TDBCSV::CheckWrite(PGLOBAL g)
n += 2; // Outside quotes
} // endif
-
+ }
if ((nlen += n) > maxlen) {
strcpy(g->Message, MSG(LINE_TOO_LONG));
return -1;
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 7e8d6c8d9f0..a8e96e2fe8d 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -255,11 +255,13 @@ int JSONDISC::GetColumns(PGLOBAL g, PCSZ db, PCSZ dsn, PTOS topt)
jsp = (tjsp->GetDoc()) ? tjsp->GetDoc()->GetValue(0) : NULL;
} else {
if (!(tdp->Lrecl = GetIntegerTableOption(g, topt, "Lrecl", 0)))
+ {
if (!mgo) {
sprintf(g->Message, "LRECL must be specified for pretty=%d", tdp->Pretty);
return 0;
} else
tdp->Lrecl = 8192; // Should be enough
+ }
tdp->Ending = GetIntegerTableOption(g, topt, "Ending", CRLF);
@@ -1328,7 +1330,7 @@ bool JSONCOL::ParseJpath(PGLOBAL g)
{
char *p, *p1 = NULL, *p2 = NULL, *pbuf = NULL;
int i;
- bool a, mul = false;
+ bool a;
if (Parsed)
return false; // Already done
@@ -1427,6 +1429,7 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
return NULL;
for (p1 = p2 = mgopath; *p1; p1++)
+ {
if (i) { // Inside []
if (isdigit(*p1)) {
if (!proj)
@@ -1464,12 +1467,12 @@ PSZ JSONCOL::GetJpath(PGLOBAL g, bool proj)
p2--; // Suppress last :*
break;
} // endif p2
-
+ /* falls through */
default:
*p2++ = *p1;
break;
} // endswitch p1;
-
+ }
*p2 = 0;
return mgopath;
} else
@@ -1558,7 +1561,6 @@ void JSONCOL::ReadColumn(PGLOBAL g)
PVAL JSONCOL::GetColumnValue(PGLOBAL g, PJSON row, int i)
{
int n = Nod - 1;
- bool expd = false;
PJAR arp;
PJVAL val = NULL;
@@ -2119,13 +2121,14 @@ int TDBJSON::Cardinality(PGLOBAL g)
if (!g)
return (Xcol || Multiple) ? 0 : 1;
else if (Cardinal < 0)
+ {
if (!Multiple) {
if (MakeDocument(g) == RC_OK)
Cardinal = Doc->size();
} else
return 10;
-
+ }
return Cardinal;
} // end of Cardinality
diff --git a/storage/connect/tabmul.cpp b/storage/connect/tabmul.cpp
index 649fc6706c6..7997a999b56 100644
--- a/storage/connect/tabmul.cpp
+++ b/storage/connect/tabmul.cpp
@@ -671,8 +671,8 @@ TDBDIR::TDBDIR(PSZ fpat) : TDBASE((PTABDEF)NULL)
/***********************************************************************/
char* TDBDIR::Path(PGLOBAL g)
{
- PCATLG cat = PlgGetCatalog(g);
- PTABDEF defp = (PTABDEF)To_Def;
+ PCATLG cat __attribute__((unused))= PlgGetCatalog(g);
+ PTABDEF defp = (PTABDEF)To_Def;
#if defined(__WIN__)
if (!*Drive) {
@@ -708,8 +708,9 @@ PCOL TDBDIR::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
int TDBDIR::GetMaxSize(PGLOBAL g)
{
if (MaxSize < 0) {
- int rc, n = -1;
+ int n = -1;
#if defined(__WIN__)
+ int rc;
// Start searching files in the target directory.
hSearch = FindFirstFile(Path(g), &FileData);
@@ -1041,12 +1042,13 @@ int TDBSDR::GetMaxSize(PGLOBAL g)
/***********************************************************************/
int TDBSDR::FindInDir(PGLOBAL g)
{
- int rc, n = 0;
+ int n = 0;
size_t m = strlen(Direc);
// Start searching files in the target directory.
#if defined(__WIN__)
HANDLE h;
+ int rc;
#if defined(PATHMATCHSPEC)
if (!*Drive)
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index 7e165fb5a80..440fdb583f1 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -1264,7 +1264,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PCSZ am)
: COLBLK(NULL, tdbp, i)
{
- const char *chset = get_charset_name(fld->charsetnr);
+//const char *chset = get_charset_name(fld->charsetnr);
//char v = (!strcmp(chset, "binary")) ? 'B' : 0;
char v = 0;
@@ -1405,6 +1405,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
/* If physical fetching of the line was deferred, do it now. */
/*********************************************************************/
if (!tdbp->Fetched)
+ {
if ((rc = tdbp->Myc.Fetch(g, tdbp->N)) != RC_OK) {
if (rc == RC_EF)
sprintf(g->Message, MSG(INV_DEF_READ), rc);
@@ -1412,7 +1413,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
throw 11;
} else
tdbp->Fetched = true;
-
+ }
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
if (trace(2))
htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
diff --git a/storage/connect/taboccur.cpp b/storage/connect/taboccur.cpp
index 07272d1b298..20d4c0cb032 100644
--- a/storage/connect/taboccur.cpp
+++ b/storage/connect/taboccur.cpp
@@ -202,7 +202,7 @@ bool OcrSrcCols(PGLOBAL g, PQRYRES qrp, const char *col,
/**********************************************************************/
/* Replace the columns of the colist by the rank and occur columns. */
/**********************************************************************/
- for (i = 0, pcrp = &qrp->Colresp; crp = *pcrp; ) {
+ for (i = 0, pcrp = &qrp->Colresp; (crp = *pcrp); ) {
for (k = 0, pn = colist; k < m; k++, pn += (strlen(pn) + 1))
if (!stricmp(pn, crp->Name))
break;
@@ -450,8 +450,8 @@ bool TDBOCCUR::OpenDB(PGLOBAL g)
N = M = 0;
RowFlag = 0;
- if (Xcolp)
- Xcolp->Xreset();
+ if (Xcolp)
+ Xcolp->Xreset();
return Tdbp->OpenDB(g);
} // endif use
diff --git a/storage/connect/tabpivot.cpp b/storage/connect/tabpivot.cpp
index 9121a0453e5..b8e61f259e4 100644
--- a/storage/connect/tabpivot.cpp
+++ b/storage/connect/tabpivot.cpp
@@ -187,7 +187,7 @@ PQRYRES PIVAID::MakePivotColumns(PGLOBAL g)
} // endif picol
// Prepare the column list
- for (pcrp = &Qryp->Colresp; crp = *pcrp; )
+ for (pcrp = &Qryp->Colresp; (crp = *pcrp); )
if (SkipColumn(crp, skc)) {
// Ignore this column
*pcrp = crp->Next;
@@ -340,7 +340,7 @@ int PIVAID::Qcompare(int *i1, int *i2)
bool PIVOTDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
{
char *p1, *p2;
- PHC hc = ((MYCAT*)Cat)->GetHandler();
+ PHC hc __attribute__((unused))= ((MYCAT*)Cat)->GetHandler();
if (PRXDEF::DefineAM(g, am, poff))
return TRUE;
@@ -748,7 +748,9 @@ int TDBPIVOT::ReadDB(PGLOBAL g)
colp->ReadColumn(g);
for (colp = Columns; colp; colp = colp->GetNext())
+ {
if (colp->GetAmType() == TYPE_AM_SRC)
+ {
if (FileStatus) {
if (((PSRCCOL)colp)->CompareLast()) {
newrow = (RowFlag) ? TRUE : FALSE;
@@ -757,7 +759,8 @@ int TDBPIVOT::ReadDB(PGLOBAL g)
} else
((PSRCCOL)colp)->SetColumn();
-
+ }
+ }
FileStatus = 1;
} // endif RowFlag
diff --git a/storage/connect/tabvir.cpp b/storage/connect/tabvir.cpp
index c78a8f531f6..76d52e198e3 100644
--- a/storage/connect/tabvir.cpp
+++ b/storage/connect/tabvir.cpp
@@ -168,16 +168,17 @@ int TDBVIR::TestFilter(PFIL filp, bool nop)
} // endswitch op
if (!nop) switch (op) {
- case OP_LT: l1--;
- case OP_LE: limit = l1; break;
- default: ok = false;
- } // endswitch op
-
+ case OP_LT: l1--;
+ /* falls through */
+ case OP_LE: limit = l1; break;
+ default: ok = false;
+ } // endswitch op
else switch (op) {
- case OP_GE: l1--;
- case OP_GT: limit = l1; break;
- default: ok = false;
- } // endswitch op
+ case OP_GE: l1--;
+ /* falls through */
+ case OP_GT: limit = l1; break;
+ default: ok = false;
+ } // endswitch op
limit = MY_MIN(MY_MAX(0, limit), Size);
diff --git a/storage/connect/tabxcl.cpp b/storage/connect/tabxcl.cpp
index 93a24accc3c..4634f6a4ded 100644
--- a/storage/connect/tabxcl.cpp
+++ b/storage/connect/tabxcl.cpp
@@ -274,7 +274,8 @@ void XCLCOL::ReadColumn(PGLOBAL g)
PSZ p;
// Trim left
- for (p = Cp; *p == ' '; p++) ;
+ for (p = Cp; *p == ' '; p++)
+ ;
if ((Cp = strchr(Cp, Sep)))
// Separator is found
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 717090e9c5a..a46aa8635aa 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -218,8 +218,10 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
while (true) {
if (!vp->atp &&
- !(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, tdp->Usedom ? node : NULL)
- : NULL))
+ !(node = (vp->nl) ? vp->nl->GetItem(g, vp->k++, tdp->Usedom ?
+ node : NULL)
+ : NULL))
+ {
if (j) {
vp = lvlp[--j];
@@ -234,7 +236,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
continue;
} else
break;
-
+ }
xcol->Name[vp->n] = 0;
fmt[vp->m] = 0;
@@ -248,6 +250,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
switch (vp->atp->GetText(g, buf, sizeof(buf))) {
case RC_INFO:
PushWarning(g, txmp);
+ /* falls through */
case RC_OK:
strncat(fmt, "@", XLEN(fmt));
break;
@@ -308,6 +311,7 @@ PQRYRES XMLColumns(PGLOBAL g, char *db, char *tab, PTOS topt, bool info)
switch (node->GetContent(g, buf, sizeof(buf))) {
case RC_INFO:
PushWarning(g, txmp);
+ /* falls through */
case RC_OK:
xcol->Cbn = !strlen(buf);
break;
@@ -1271,6 +1275,7 @@ int TDBXML::ReadDB(PGLOBAL g)
bool TDBXML::CheckRow(PGLOBAL g, bool b)
{
if (NewRow && Mode == MODE_INSERT)
+ {
if (Rowname) {
TabNode->AddText(g, "\n\t");
RowNode = TabNode->AddChildNode(g, Rowname, RowNode);
@@ -1278,6 +1283,7 @@ bool TDBXML::CheckRow(PGLOBAL g, bool b)
strcpy(g->Message, MSG(NO_ROW_NODE));
return true;
} // endif Rowname
+ }
if (Colname && (NewRow || b))
Clist = RowNode->SelectNodes(g, Colname, Clist);
@@ -1525,11 +1531,13 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
// Analyze the Xpath for this column
for (i = 0, p = pbuf; (p2 = strchr(p, '/')); i++, p = p2 + 1) {
if (Tdbp->Mulnode && !strncmp(p, Tdbp->Mulnode, p2 - p))
+ {
if (!Tdbp->Xpand && mode) {
strcpy(g->Message, MSG(CONCAT_SUBNODE));
return true;
} else
Inod = i; // Index of multiple node
+ }
if (mode) {
// For Update or Insert the Xpath must be explicit
@@ -1776,10 +1784,12 @@ void XMLCOL::WriteColumn(PGLOBAL g)
break;
if (ColNode)
+ {
if (Type)
ValNode = ColNode->SelectSingleNode(g, Xname, Vxnp);
else
AttNode = ColNode->GetAttribute(g, Xname, Vxap);
+ }
if (TopNode || ValNode || AttNode)
break; // We found the good column
@@ -1793,6 +1803,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
/*********************************************************************/
if (ColNode == NULL) {
if (TopNode == NULL)
+ {
if (Tdbp->Clist) {
Tdbp->RowNode->AddText(g, "\n\t\t");
ColNode = Tdbp->RowNode->AddChildNode(g, Tdbp->Colname);
@@ -1800,7 +1811,7 @@ void XMLCOL::WriteColumn(PGLOBAL g)
TopNode = ColNode;
} else
TopNode = Tdbp->RowNode;
-
+ }
for (; k < Nod && TopNode; k++) {
if (!done) {
TopNode->AddText(g, "\n\t\t");
@@ -2015,6 +2026,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
} // endfor k
if (ColNode)
+ {
if (Inod == Nod) {
/***************************************************************/
/* The node value can be multiple. */
@@ -2032,11 +2044,13 @@ void XMULCOL::WriteColumn(PGLOBAL g)
ValNode = Nlx->GetItem(g, Tdbp->Nsub, Vxnp);
} else // Inod != Nod
+ {
if (Type)
ValNode = ColNode->SelectSingleNode(g, Xname, Vxnp);
else
AttNode = ColNode->GetAttribute(g, Xname, Vxap);
-
+ }
+ }
if (TopNode || ValNode || AttNode)
break; // We found the good column
else if (Tdbp->Clist)
@@ -2049,6 +2063,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
/*********************************************************************/
if (ColNode == NULL) {
if (TopNode == NULL)
+ {
if (Tdbp->Clist) {
Tdbp->RowNode->AddText(g, "\n\t\t");
ColNode = Tdbp->RowNode->AddChildNode(g, Tdbp->Colname);
@@ -2056,6 +2071,7 @@ void XMULCOL::WriteColumn(PGLOBAL g)
TopNode = ColNode;
} else
TopNode = Tdbp->RowNode;
+ }
for (; k < Nod && TopNode; k++) {
if (!done) {
diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc
index c25443ef7ef..55597c426eb 100644
--- a/storage/connect/user_connect.cc
+++ b/storage/connect/user_connect.cc
@@ -112,7 +112,7 @@ bool user_connect::user_init()
if (g)
printf("%s\n", g->Message);
- int rc= PlugExit(g);
+ int rc __attribute__((unused))= PlugExit(g);
g= NULL;
if (dup)
diff --git a/storage/connect/user_connect.h b/storage/connect/user_connect.h
index 2670c5bcebc..53064e620f2 100644
--- a/storage/connect/user_connect.h
+++ b/storage/connect/user_connect.h
@@ -35,7 +35,7 @@
//typedef struct _global *PGLOBAL;
typedef class user_connect *PCONNECT;
typedef class ha_connect *PHC;
-static int connect_done_func(void *);
+int connect_done_func(void *);
/*****************************************************************************/
/* The CONNECT users. There should be one by connected users. */
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index b7c8c704e65..2ae9382609d 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -1131,7 +1131,7 @@ void STRBLK::SetValues(PVBLK pv, int k, int n)
CheckType(pv)
PSZ *sp = ((STRBLK*)pv)->Strp;
- for (register int i = k; i < n; i++)
+ for (int i = k; i < n; i++)
Strp[i] = (!pv->IsNull(i)) ? sp[i] : NULL;
} // end of SetValues
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index df75722d0e8..2fad67f453b 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -2605,12 +2605,13 @@ bool DTVAL::MakeDate(PGLOBAL g, int *val, int nval)
// Pass g to have an error return or NULL to set invalid dates to 0
if (MakeTime(&datm))
+ {
if (g) {
strcpy(g->Message, MSG(BAD_DATETIME));
rc = true;
} else
Tval = 0;
-
+ }
return rc;
} // end of MakeDate
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index 95f038d494c..8dcaa186bc9 100644
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -559,12 +559,14 @@ bool XINDEX::Make(PGLOBAL g, PIXDEF sxp)
// Check whether the unique index is unique indeed
if (!Mul)
+ {
if (Ndif < Num_K) {
strcpy(g->Message, MSG(INDEX_NOT_UNIQ));
brc = true;
goto err;
} else
PlgDBfree(Offset); // Not used anymore
+ }
// Restore kcp list
To_LastCol->Next = addcolp;
@@ -1209,7 +1211,7 @@ bool XINDEX::MapInit(PGLOBAL g)
PCOL colp;
PXCOL prev = NULL, kcp = NULL;
PDOSDEF defp = (PDOSDEF)Tdbp->To_Def;
- PDBUSER dup = PlgGetUser(g);
+ PDBUSER dup __attribute__((unused))= PlgGetUser(g);
/*********************************************************************/
/* Get the estimated table size. */
@@ -2043,11 +2045,12 @@ int XINDXS::Range(PGLOBAL g, int limit, bool incl)
k = FastFind();
if (k < Num_K || Op != OP_EQ)
+ {
if (limit)
n = (Mul) ? k : kp->Val_K;
else
n = (Mul) ? Pof[kp->Val_K + 1] - k : 1;
-
+ }
} else {
strcpy(g->Message, MSG(RANGE_NO_JOIN));
n = -1; // Logical error
diff --git a/storage/connect/zip.c b/storage/connect/zip.c
index 4bbe31ab7dd..52d63e108e7 100644
--- a/storage/connect/zip.c
+++ b/storage/connect/zip.c
@@ -28,6 +28,7 @@
#include <time.h>
#include "zlib.h"
#include "zip.h"
+#include "my_attribute.h"
#ifdef STDC
# include <stddef.h>
@@ -518,16 +519,16 @@ local ZPOS64_T zip64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_f
if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
break;
- for (i=(int)uReadSize-3; (i--)>0;)
+ for (i=(int)uReadSize-3; (i--)>0;) {
if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
{
uPosFound = uReadPos+i;
break;
}
-
- if (uPosFound!=0)
- break;
+ }
+ if (uPosFound!=0)
+ break;
}
TRYFREE(buf);
return uPosFound;
@@ -1057,7 +1058,7 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
const void* extrafield_global, uInt size_extrafield_global,
const char* comment, int method, int level, int raw,
int windowBits,int memLevel, int strategy,
- const char* password, uLong crcForCrypting,
+ const char* password, uLong crcForCrypting __attribute__((unused)),
uLong versionMadeBy, uLong flagBase, int zip64)
{
zip64_internal* zi;
@@ -1066,11 +1067,10 @@ extern int ZEXPORT zipOpenNewFileInZip4_64 (zipFile file, const char* filename,
uInt i;
int err = ZIP_OK;
-# ifdef NOCRYPT
- (crcForCrypting);
+#ifdef NOCRYPT
if (password != NULL)
return ZIP_PARAMERROR;
-# endif
+#endif
if (file == NULL)
return ZIP_PARAMERROR;
diff --git a/storage/csv/ha_tina.cc b/storage/csv/ha_tina.cc
index 3a9bbc2766f..badb515c2b2 100644
--- a/storage/csv/ha_tina.cc
+++ b/storage/csv/ha_tina.cc
@@ -1004,7 +1004,7 @@ int ha_tina::close(void)
of the file and appends the data. In an error case it really should
just truncate to the original position (this is not done yet).
*/
-int ha_tina::write_row(uchar * buf)
+int ha_tina::write_row(const uchar * buf)
{
int size;
DBUG_ENTER("ha_tina::write_row");
@@ -1311,12 +1311,28 @@ int ha_tina::info(uint flag)
int ha_tina::extra(enum ha_extra_function operation)
{
DBUG_ENTER("ha_tina::extra");
- if (operation == HA_EXTRA_MARK_AS_LOG_TABLE)
- {
- mysql_mutex_lock(&share->mutex);
- share->is_log_table= TRUE;
- mysql_mutex_unlock(&share->mutex);
- }
+ switch (operation) {
+ case HA_EXTRA_MARK_AS_LOG_TABLE:
+ {
+ mysql_mutex_lock(&share->mutex);
+ share->is_log_table= TRUE;
+ mysql_mutex_unlock(&share->mutex);
+ }
+ break;
+ case HA_EXTRA_FLUSH:
+ mysql_mutex_lock(&share->mutex);
+ if (share->tina_write_opened)
+ {
+ (void)write_meta_file(share->meta_file, share->rows_recorded,
+ share->crashed ? TRUE :FALSE);
+ mysql_file_close(share->tina_write_filedes, MYF(0));
+ share->tina_write_opened= FALSE;
+ }
+ mysql_mutex_unlock(&share->mutex);
+ break;
+ default:
+ break;
+ }
DBUG_RETURN(0);
}
@@ -1385,7 +1401,7 @@ int ha_tina::rnd_end()
if (mysql_file_write(update_temp_file,
(uchar*) (file_buff->ptr() +
(write_begin - file_buff->start())),
- (size_t)write_length, MYF_RW))
+ (size_t)write_length, MYF(MY_WME+MY_NABP)))
goto error;
temp_file_length+= write_length;
}
@@ -1571,7 +1587,7 @@ int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
write_end= MY_MIN(file_buff->end(), current_position);
if ((write_end - write_begin) &&
(mysql_file_write(repair_file, (uchar*)file_buff->ptr(),
- (size_t) (write_end - write_begin), MYF_RW)))
+ (size_t) (write_end - write_begin), MYF(MY_WME+MY_NABP))))
DBUG_RETURN(-1);
write_begin= write_end;
diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h
index da3a1b9ffe8..aae535c271e 100644
--- a/storage/csv/ha_tina.h
+++ b/storage/csv/ha_tina.h
@@ -107,7 +107,7 @@ public:
{
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_CAN_EXPORT |
- HA_CAN_REPAIR);
+ HA_CAN_REPAIR | HA_SLOW_RND_POS);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
{
@@ -136,7 +136,7 @@ public:
int open(const char *name, int mode, uint open_options);
int close(void);
- int write_row(uchar * buf);
+ int write_row(const uchar * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int rnd_init(bool scan=1);
diff --git a/storage/example/ha_example.cc b/storage/example/ha_example.cc
index ab402c636d1..e873837694b 100644
--- a/storage/example/ha_example.cc
+++ b/storage/example/ha_example.cc
@@ -398,7 +398,7 @@ int ha_example::close(void)
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc and sql_update.cc
*/
-int ha_example::write_row(uchar *buf)
+int ha_example::write_row(const uchar *buf)
{
DBUG_ENTER("ha_example::write_row");
/*
diff --git a/storage/example/ha_example.h b/storage/example/ha_example.h
index 52fb4ff3c1b..0a08e871461 100644
--- a/storage/example/ha_example.h
+++ b/storage/example/ha_example.h
@@ -180,7 +180,7 @@ public:
We implement this in ha_example.cc. It's not an obligatory method;
skip it and and MySQL will treat it as not implemented.
*/
- int write_row(uchar *buf);
+ int write_row(const uchar *buf);
/** @brief
We implement this in ha_example.cc. It's not an obligatory method;
diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc
index 79e70ce5123..ec34cf16858 100644
--- a/storage/federated/ha_federated.cc
+++ b/storage/federated/ha_federated.cc
@@ -1825,7 +1825,7 @@ bool ha_federated::append_stmt_insert(String *query)
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
*/
-int ha_federated::write_row(uchar *buf)
+int ha_federated::write_row(const uchar *buf)
{
char values_buffer[FEDERATED_QUERY_BUFFER_SIZE];
char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h
index 0b34d66baa9..3beb2ca9570 100644
--- a/storage/federated/ha_federated.h
+++ b/storage/federated/ha_federated.h
@@ -146,6 +146,7 @@ public:
HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ |
HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY |
+ HA_CAN_ONLINE_BACKUPS |
HA_CAN_REPAIR);
}
/*
@@ -208,7 +209,7 @@ public:
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();
- int write_row(uchar *buf);
+ int write_row(const uchar *buf);
int update_row(const uchar *old_data, const uchar *new_data);
int delete_row(const uchar *buf);
int index_init(uint keynr, bool sorted);
diff --git a/storage/federatedx/TODO b/storage/federatedx/TODO
deleted file mode 100644
index 71330742f4e..00000000000
--- a/storage/federatedx/TODO
+++ /dev/null
@@ -1,30 +0,0 @@
-Features
-
-* Add Pushdown conditions
-* Add other network driver interfaces
-* Handle large result sets
-* Auto-discovery of tables on foreign data sources
-
-Bugs (http://bugs.mysql.com)
-
-20026 2006-05-23 FEDERATED lacks support for auto_increment_increment and auto_increment_offset
-20724 2006-06-27 FEDERATED does not honour SET INSERT_ID
-28269 2007-05-06 Any FEDERATED engine fails to quote reserved words for field names
-25509 2007-01-10 Federated: Failure with non-ASCII characters
-26697 2007-02-27 Every query to a federated table results in a full scan of MyISAM table.
-21360 2006-07-31 Microsoft Windows (Windows/Linux) mysqldump error on federated tables
-34189 2008-01-31 Any ALTER TABLE t1 ENGINE=FEDERATED CONNECTION='connectionString' on MyISAM fails
-31757 2007-10-22 Any Federated tables break replication Antony Curtis
-33953 2008-01-21 Any mysqld dies on search federated table using nullable index with < or <= operator
-34015 2008-01-23 Linux Problems with float fields using federated tables
-21583 2006-08-11 Linux (Linux) Federated table returns broken strings.
-33702 2008-01-05 Accessing a federated table with a non existing server returns random error code
-25512 2007-01-10 Federated: CREATE failures
-32426 2007-11-16 Any FEDERATED query returns corrupt results for ORDER BY on a TEXT field
-25510 2007-01-10 Federated: double trigger activation
-33250 2007-12-14 SELECT * FROM really_big_federated_table eats lots of virtual memory (OOM)
-14874 2005-11-11 Error 2013: Lost connection to MySQL server with Federated table
-25508 2007-01-10 Federated: Failure to Remove Partitioning
-27180 2007-03-15 #1030 - Got error 1 from storage engine with big tables
-33947 2008-01-20 Any Join on Federated tables with Unique index and IS NOT NULL crashes server
-30051 (fixed) CREATE TABLE does not connect and check existence of remote table
diff --git a/storage/federatedx/federatedx_pushdown.cc b/storage/federatedx/federatedx_pushdown.cc
new file mode 100644
index 00000000000..15b0b0d3d4e
--- /dev/null
+++ b/storage/federatedx/federatedx_pushdown.cc
@@ -0,0 +1,304 @@
+/*
+ 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 */
+
+/* !!! For inclusion into ha_federatedx.cc */
+
+
+/*
+ This is a quick a dirty implemention of the derived_handler and select_handler
+ interfaces to be used to push select queries and the queries specifying
+ derived tables into FEDERATEDX engine.
+ The functions
+ create_federatedx_derived_handler and
+ create_federatedx_select_handler
+ that return the corresponding interfaces for pushdown capabilities do
+ not check a lot of things. In particular they do not check that the tables
+ of the pushed queries belong to the same foreign server.
+
+ The implementation is provided purely for testing purposes.
+ The pushdown capabilities are enabled by turning on the plugin system
+ variable federated_pushdown:
+ set global federated_pushdown=1;
+*/
+
+
+static derived_handler*
+create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived)
+{
+ if (!use_pushdown)
+ return 0;
+
+ ha_federatedx_derived_handler* handler = NULL;
+ handlerton *ht= 0;
+
+ SELECT_LEX_UNIT *unit= derived->derived;
+
+ for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
+ {
+ if (!(sl->join))
+ return 0;
+ for (TABLE_LIST *tbl= sl->join->tables_list; tbl; tbl= tbl->next_local)
+ {
+ if (!tbl->table)
+ return 0;
+ if (!ht)
+ ht= tbl->table->file->partition_ht();
+ else if (ht != tbl->table->file->partition_ht())
+ return 0;
+ }
+ }
+
+ handler= new ha_federatedx_derived_handler(thd, derived);
+
+ return handler;
+}
+
+
+/*
+ Implementation class of the derived_handler interface for FEDERATEDX:
+ class implementation
+*/
+
+ha_federatedx_derived_handler::ha_federatedx_derived_handler(THD *thd,
+ TABLE_LIST *dt)
+ : derived_handler(thd, federatedx_hton),
+ share(NULL), txn(NULL), iop(NULL), stored_result(NULL)
+{
+ derived= dt;
+}
+
+ha_federatedx_derived_handler::~ha_federatedx_derived_handler() {}
+
+int ha_federatedx_derived_handler::init_scan()
+{
+ THD *thd;
+ int rc= 0;
+
+ DBUG_ENTER("ha_federatedx_derived_handler::init_scan");
+
+ TABLE *table= derived->get_first_table()->table;
+ ha_federatedx *h= (ha_federatedx *) table->file;
+ iop= &h->io;
+ share= get_share(table->s->table_name.str, table);
+ thd= table->in_use;
+ txn= h->get_txn(thd);
+ if ((rc= txn->acquire(share, thd, TRUE, iop)))
+ DBUG_RETURN(rc);
+
+ if ((*iop)->query(derived->derived_spec.str, derived->derived_spec.length))
+ goto err;
+
+ stored_result= (*iop)->store_result();
+ if (!stored_result)
+ goto err;
+
+ DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM);
+}
+
+int ha_federatedx_derived_handler::next_row()
+{
+ int rc;
+ FEDERATEDX_IO_ROW *row;
+ ulong *lengths;
+ Field **field;
+ int column= 0;
+ Time_zone *saved_time_zone= table->in_use->variables.time_zone;
+ DBUG_ENTER("ha_federatedx_derived_handler::next_row");
+
+ if ((rc= txn->acquire(share, table->in_use, TRUE, iop)))
+ DBUG_RETURN(rc);
+
+ if (!(row= (*iop)->fetch_row(stored_result)))
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ /* Convert row to internal format */
+ table->in_use->variables.time_zone= UTC;
+ lengths= (*iop)->fetch_lengths(stored_result);
+
+ for (field= table->field; *field; field++, column++)
+ {
+ if ((*iop)->is_column_null(row, column))
+ (*field)->set_null();
+ else
+ {
+ (*field)->set_notnull();
+ (*field)->store((*iop)->get_column_data(row, column),
+ lengths[column], &my_charset_bin);
+ }
+ }
+ table->in_use->variables.time_zone= saved_time_zone;
+
+ DBUG_RETURN(rc);
+}
+
+int ha_federatedx_derived_handler::end_scan()
+{
+ DBUG_ENTER("ha_federatedx_derived_handler::end_scan");
+
+ (*iop)->free_result(stored_result);
+
+ free_share(txn, share);
+
+ DBUG_RETURN(0);
+}
+
+void ha_federatedx_derived_handler::print_error(int, unsigned long)
+{
+}
+
+
+static select_handler*
+create_federatedx_select_handler(THD* thd, SELECT_LEX *sel)
+{
+ if (!use_pushdown)
+ return 0;
+
+ ha_federatedx_select_handler* handler = NULL;
+ handlerton *ht= 0;
+
+ for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global)
+ {
+ if (!tbl->table)
+ return 0;
+ if (!ht)
+ ht= tbl->table->file->partition_ht();
+ else if (ht != tbl->table->file->partition_ht())
+ return 0;
+ }
+
+ /*
+ Currently, ha_federatedx_select_handler::init_scan just takes the
+ thd->query and sends it to the backend.
+ This obviously won't work if the SELECT uses an "INTO @var" or
+ "INTO OUTFILE". It is also unlikely to work if the select has some
+ other kind of side effect.
+ */
+ if (sel->uncacheable & UNCACHEABLE_SIDEEFFECT)
+ return NULL;
+
+ handler= new ha_federatedx_select_handler(thd, sel);
+
+ return handler;
+}
+
+/*
+ Implementation class of the select_handler interface for FEDERATEDX:
+ class implementation
+*/
+
+ha_federatedx_select_handler::ha_federatedx_select_handler(THD *thd,
+ SELECT_LEX *sel)
+ : select_handler(thd, federatedx_hton),
+ share(NULL), txn(NULL), iop(NULL), stored_result(NULL)
+{
+ select= sel;
+}
+
+ha_federatedx_select_handler::~ha_federatedx_select_handler() {}
+
+int ha_federatedx_select_handler::init_scan()
+{
+ int rc= 0;
+
+ DBUG_ENTER("ha_federatedx_select_handler::init_scan");
+
+ TABLE *table= 0;
+ for (TABLE_LIST *tbl= thd->lex->query_tables; tbl; tbl= tbl->next_global)
+ {
+ if (!tbl->table)
+ continue;
+ table= tbl->table;
+ break;
+ }
+ ha_federatedx *h= (ha_federatedx *) table->file;
+ iop= &h->io;
+ share= get_share(table->s->table_name.str, table);
+ txn= h->get_txn(thd);
+ if ((rc= txn->acquire(share, thd, TRUE, iop)))
+ DBUG_RETURN(rc);
+
+ if ((*iop)->query(thd->query(), thd->query_length()))
+ goto err;
+
+ stored_result= (*iop)->store_result();
+ if (!stored_result)
+ goto err;
+
+ DBUG_RETURN(0);
+
+err:
+ DBUG_RETURN(HA_FEDERATEDX_ERROR_WITH_REMOTE_SYSTEM);
+}
+
+int ha_federatedx_select_handler::next_row()
+{
+ int rc= 0;
+ FEDERATEDX_IO_ROW *row;
+ ulong *lengths;
+ Field **field;
+ int column= 0;
+ Time_zone *saved_time_zone= table->in_use->variables.time_zone;
+ DBUG_ENTER("ha_federatedx_select_handler::next_row");
+
+ if ((rc= txn->acquire(share, table->in_use, TRUE, iop)))
+ DBUG_RETURN(rc);
+
+ if (!(row= (*iop)->fetch_row(stored_result)))
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+
+ /* Convert row to internal format */
+ table->in_use->variables.time_zone= UTC;
+ lengths= (*iop)->fetch_lengths(stored_result);
+
+ for (field= table->field; *field; field++, column++)
+ {
+ if ((*iop)->is_column_null(row, column))
+ (*field)->set_null();
+ else
+ {
+ (*field)->set_notnull();
+ (*field)->store((*iop)->get_column_data(row, column),
+ lengths[column], &my_charset_bin);
+ }
+ }
+ table->in_use->variables.time_zone= saved_time_zone;
+
+ DBUG_RETURN(rc);
+}
+
+int ha_federatedx_select_handler::end_scan()
+{
+ DBUG_ENTER("ha_federatedx_derived_handler::end_scan");
+
+ free_tmp_table(thd, table);
+ table= 0;
+
+ (*iop)->free_result(stored_result);
+
+ free_share(txn, share);
+
+ DBUG_RETURN(0);
+}
+
+void ha_federatedx_select_handler::print_error(int error, myf error_flag)
+{
+ select_handler::print_error(error, error_flag);
+}
+
+
diff --git a/storage/federatedx/federatedx_pushdown.h b/storage/federatedx/federatedx_pushdown.h
new file mode 100644
index 00000000000..673abcfc68d
--- /dev/null
+++ b/storage/federatedx/federatedx_pushdown.h
@@ -0,0 +1,63 @@
+/*
+ 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 */
+
+#include "derived_handler.h"
+#include "select_handler.h"
+
+/*
+ Implementation class of the derived_handler interface for FEDERATEDX:
+ class declaration
+*/
+
+class ha_federatedx_derived_handler: public derived_handler
+{
+private:
+ FEDERATEDX_SHARE *share;
+ federatedx_txn *txn;
+ federatedx_io **iop;
+ FEDERATEDX_IO_RESULT *stored_result;
+
+public:
+ ha_federatedx_derived_handler(THD* thd_arg, TABLE_LIST *tbl);
+ ~ha_federatedx_derived_handler();
+ int init_scan();
+ int next_row();
+ int end_scan();
+ void print_error(int, unsigned long);
+};
+
+
+/*
+ Implementation class of the select_handler interface for FEDERATEDX:
+ class declaration
+*/
+
+class ha_federatedx_select_handler: public select_handler
+{
+private:
+ FEDERATEDX_SHARE *share;
+ federatedx_txn *txn;
+ federatedx_io **iop;
+ FEDERATEDX_IO_RESULT *stored_result;
+
+public:
+ ha_federatedx_select_handler(THD* thd_arg, SELECT_LEX *sel);
+ ~ha_federatedx_select_handler();
+ int init_scan();
+ int next_row();
+ int end_scan();
+ void print_error(int, unsigned long);
+};
diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc
index 4a717eead20..49101447dda 100644
--- a/storage/federatedx/ha_federatedx.cc
+++ b/storage/federatedx/ha_federatedx.cc
@@ -319,6 +319,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "sql_analyse.h" // append_escaped()
#include "sql_show.h" // append_identifier()
#include "tztime.h" // my_tz_find()
+#include "sql_select.h"
#ifdef I_AM_PARANOID
#define MIN_PORT 1023
@@ -401,6 +402,12 @@ static void init_federated_psi_keys(void)
#define init_federated_psi_keys() /* no-op */
#endif /* HAVE_PSI_INTERFACE */
+handlerton* federatedx_hton;
+
+static derived_handler*
+create_federatedx_derived_handler(THD* thd, TABLE_LIST *derived);
+static select_handler*
+create_federatedx_select_handler(THD* thd, SELECT_LEX *sel);
/*
Initialize the federatedx handler.
@@ -418,7 +425,7 @@ int federatedx_db_init(void *p)
{
DBUG_ENTER("federatedx_db_init");
init_federated_psi_keys();
- handlerton *federatedx_hton= (handlerton *)p;
+ federatedx_hton= (handlerton *)p;
federatedx_hton->state= SHOW_OPTION_YES;
/* Needed to work with old .frm files */
federatedx_hton->db_type= DB_TYPE_FEDERATED_DB;
@@ -432,6 +439,8 @@ int federatedx_db_init(void *p)
federatedx_hton->discover_table_structure= ha_federatedx::discover_assisted;
federatedx_hton->create= federatedx_create_handler;
federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED;
+ federatedx_hton->create_derived= create_federatedx_derived_handler;
+ federatedx_hton->create_select= create_federatedx_select_handler;
if (mysql_mutex_init(fe_key_mutex_federatedx,
&federatedx_mutex, MY_MUTEX_INIT_FAST))
@@ -1978,7 +1987,7 @@ bool ha_federatedx::append_stmt_insert(String *query)
sql_insert.cc, sql_select.cc, sql_table.cc, sql_udf.cc, and sql_update.cc.
*/
-int ha_federatedx::write_row(uchar *buf)
+int ha_federatedx::write_row(const uchar *buf)
{
char values_buffer[FEDERATEDX_QUERY_BUFFER_SIZE];
char insert_field_value_buffer[STRING_BUFFER_USUAL_SIZE];
@@ -3671,6 +3680,13 @@ err1:
struct st_mysql_storage_engine federatedx_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
+my_bool use_pushdown;
+static MYSQL_SYSVAR_BOOL(pushdown, use_pushdown, 0,
+ "Use query fragments pushdown capabilities", NULL, NULL, FALSE);
+static struct st_mysql_sys_var* sysvars[]= { MYSQL_SYSVAR(pushdown), NULL };
+
+#include "federatedx_pushdown.cc"
+
maria_declare_plugin(federatedx)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
@@ -3683,8 +3699,9 @@ maria_declare_plugin(federatedx)
federatedx_done, /* Plugin Deinit */
0x0201 /* 2.1 */,
NULL, /* status variables */
- NULL, /* system variables */
+ sysvars, /* system variables */
"2.1", /* string version */
MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
}
maria_declare_plugin_end;
+
diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h
index ffd9274d7eb..1870a83d13d 100644
--- a/storage/federatedx/ha_federatedx.h
+++ b/storage/federatedx/ha_federatedx.h
@@ -1,3 +1,5 @@
+#ifndef HA_FEDERATEDX_INCLUDED
+#define HA_FEDERATEDX_INCLUDED
/*
Copyright (c) 2008, Patrick Galbraith
All rights reserved.
@@ -332,7 +334,7 @@ public:
return (HA_PRIMARY_KEY_IN_READ_INDEX | HA_FILE_BASED
| HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_CAN_REPAIR |
- HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
+ HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | HA_CAN_ONLINE_BACKUPS |
HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
}
/*
@@ -395,7 +397,7 @@ public:
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();
- int write_row(uchar *buf);
+ int write_row(const uchar *buf);
int update_row(const uchar *old_data, const uchar *new_data);
int delete_row(const uchar *buf);
int index_init(uint keynr, bool sorted);
@@ -444,6 +446,9 @@ public:
int external_lock(THD *thd, int lock_type);
int reset(void);
int free_result(void);
+
+ friend class ha_federatedx_derived_handler;
+ friend class ha_federatedx_select_handler;
};
extern const char ident_quote_char; // Character for quoting
@@ -459,3 +464,7 @@ extern federatedx_io *instantiate_io_mysql(MEM_ROOT *server_root,
FEDERATEDX_SERVER *server);
extern federatedx_io *instantiate_io_null(MEM_ROOT *server_root,
FEDERATEDX_SERVER *server);
+
+#include "federatedx_pushdown.h"
+
+#endif /* HA_FEDERATEDX_INCLUDED */
diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc
index 2ffe2da06b2..80fc90eb84b 100644
--- a/storage/heap/ha_heap.cc
+++ b/storage/heap/ha_heap.cc
@@ -228,7 +228,7 @@ void ha_heap::update_key_stats()
}
-int ha_heap::write_row(uchar * buf)
+int ha_heap::write_row(const uchar * buf)
{
int res;
if (table->next_number_field && buf == table->record[0])
diff --git a/storage/heap/ha_heap.h b/storage/heap/ha_heap.h
index e3df6b95cbd..370906bd1f6 100644
--- a/storage/heap/ha_heap.h
+++ b/storage/heap/ha_heap.h
@@ -49,9 +49,9 @@ public:
{
return (HA_FAST_KEY_READ | HA_NO_BLOBS | HA_NULL_IN_KEY |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
- HA_CAN_SQL_HANDLER |
+ HA_CAN_SQL_HANDLER | HA_CAN_ONLINE_BACKUPS |
HA_REC_NOT_IN_SEQ | HA_CAN_INSERT_DELAYED | HA_NO_TRANSACTIONS |
- HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT);
+ HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_CAN_HASH_KEYS);
}
ulong index_flags(uint inx, uint part, bool all_parts) const
{
@@ -65,12 +65,13 @@ public:
double scan_time()
{ return (double) (stats.records+stats.deleted) / 20.0+10; }
double read_time(uint index, uint ranges, ha_rows rows)
- { return (double) rows / 20.0+1; }
-
+ { return (double) rows / 20.0+1; }
+ double keyread_time(uint index, uint ranges, ha_rows rows)
+ { return (double) rows / 20.0+1; }
int open(const char *name, int mode, uint test_if_locked);
int close(void);
void set_keys_for_scanning(void);
- int write_row(uchar * buf);
+ int write_row(const uchar * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index 4513a63049d..cbd280af223 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -113,7 +113,6 @@ SET(INNOBASE_SOURCES
row/row0purge.cc
row/row0row.cc
row/row0sel.cc
- row/row0trunc.cc
row/row0uins.cc
row/row0umod.cc
row/row0undo.cc
@@ -161,6 +160,8 @@ IF(NOT TARGET innobase)
RETURN()
ENDIF()
+ADD_DEFINITIONS(${SSL_DEFINES})
+
# A GCC bug causes crash when compiling these files on ARM64 with -O1+
# Compile them with -O0 as a workaround.
IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64"
@@ -175,7 +176,6 @@ IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64"
mtr/mtr0mtr.cc
row/row0merge.cc
row/row0mysql.cc
- row/row0trunc.cc
srv/srv0srv.cc
COMPILE_FLAGS "-O0"
)
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index ed3b632b300..05cdf758472 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -44,6 +44,8 @@ Created 6/2/1994 Heikki Tuuri
#include "dict0boot.h"
#include "row0sel.h" /* row_search_max_autoinc() */
+Atomic_counter<uint32_t> btr_validate_index_running;
+
/**************************************************************//**
Checks if the page in the cursor can be merged with given page.
If necessary, re-organize the merge_page.
@@ -57,15 +59,12 @@ btr_can_merge_with_page(
buf_block_t** merge_block, /*!< out: the merge block */
mtr_t* mtr); /*!< in: mini-transaction */
-/**************************************************************//**
-Report that an index page is corrupted. */
-void
-btr_corruption_report(
-/*==================*/
- const buf_block_t* block, /*!< in: corrupted block */
- const dict_index_t* index) /*!< in: index tree */
+/** Report that an index page is corrupted.
+@param[in] buffer block
+@param[in] index tree */
+void btr_corruption_report(const buf_block_t* block, const dict_index_t* index)
{
- ib::error()
+ ib::fatal()
<< "Flag mismatch in page " << block->page.id
<< " index " << index->name
<< " of table " << index->table->name;
@@ -226,7 +225,7 @@ btr_root_block_get(
buf_block_t* block = btr_block_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags), mode,
+ index->table->space->zip_size(), mode,
index, mtr);
if (!block) {
@@ -357,7 +356,7 @@ btr_root_adjust_on_import(
page_zip_des_t* page_zip;
dict_table_t* table = index->table;
const page_id_t page_id(table->space_id, index->page);
- const page_size_t page_size(table->space->flags);
+ const ulint zip_size = table->space->zip_size();
DBUG_EXECUTE_IF("ib_import_trigger_corruption_3",
return(DB_CORRUPTION););
@@ -366,7 +365,7 @@ btr_root_adjust_on_import(
mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
- block = btr_block_get(page_id, page_size, RW_X_LATCH, index, &mtr);
+ block = btr_block_get(page_id, zip_size, RW_X_LATCH, index, &mtr);
page = buf_block_get_frame(block);
page_zip = buf_block_get_page_zip(block);
@@ -385,9 +384,21 @@ btr_root_adjust_on_import(
} else {
/* Check that the table flags and the tablespace
flags match. */
- err = (dict_tf_to_fsp_flags(table->flags)
- == table->space->flags)
- ? DB_SUCCESS : DB_CORRUPTION;
+ ulint tf = dict_tf_to_fsp_flags(table->flags);
+ ulint sf = table->space->flags;
+ sf &= ~FSP_FLAGS_MEM_MASK;
+ tf &= ~FSP_FLAGS_MEM_MASK;
+ if (fil_space_t::is_flags_equal(tf, sf)
+ || fil_space_t::is_flags_equal(sf, tf)) {
+ mutex_enter(&fil_system.mutex);
+ table->space->flags = (table->space->flags
+ & ~FSP_FLAGS_MEM_MASK)
+ | (tf & FSP_FLAGS_MEM_MASK);
+ mutex_exit(&fil_system.mutex);
+ err = DB_SUCCESS;
+ } else {
+ err = DB_CORRUPTION;
+ }
}
} else {
err = DB_SUCCESS;
@@ -427,7 +438,7 @@ btr_page_create(
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
if (page_zip) {
- page_create_zip(block, index, level, 0, NULL, mtr);
+ page_create_zip(block, index, level, 0, mtr);
} else {
page_create(block, mtr, dict_table_is_comp(index->table),
dict_index_is_spatial(index));
@@ -467,7 +478,7 @@ btr_page_alloc_for_ibuf(
new_block = buf_page_get(
page_id_t(index->table->space_id, node_addr.page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_X_LATCH, mtr);
new_page = buf_block_get_frame(new_block);
@@ -749,21 +760,17 @@ void btr_page_free(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
: PAGE_HEADER + PAGE_BTR_SEG_TOP];
fseg_free_page(seg_header,
index->table->space, block->page.id.page_no(),
- block->index != NULL, mtr);
+ block->index != NULL, !block->page.flush_observer, mtr);
/* The page was marked free in the allocation bitmap, but it
should remain exclusively latched until mtr_t::commit() or until it
is explicitly freed from the mini-transaction. */
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- if (srv_immediate_scrub_data_uncompressed) {
- /* In MDEV-15528 this code must be removed and the
- check in buf_flush_init_for_writing() re-enabled. We
- should zero out the page after the redo log for this
- mini-transaction has been durably written. The log
- would include the 10.4 MLOG_INIT_FREE_PAGE record. */
- fsp_init_file_page(index->table->space, block, mtr);
- }
+ /* MDEV-15528 FIXME: Zero out the page after the redo log for
+ this mini-transaction has been durably written.
+ This must be done unconditionally if
+ srv_immediate_scrub_data_uncompressed is set. */
}
/**************************************************************//**
@@ -820,7 +827,7 @@ btr_node_ptr_get_child(
return btr_block_get(
page_id_t(index->table->space_id,
btr_node_ptr_get_child_page_no(node_ptr, offsets)),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_SX_LATCH, index, mtr);
}
@@ -1011,7 +1018,7 @@ static void btr_free_root(buf_block_t* block, mtr_t* mtr, bool invalidate)
/** Prepare to free a B-tree.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction
@return root block, to invoke btr_free_but_not_root() and btr_free_root()
@@ -1020,7 +1027,7 @@ static MY_ATTRIBUTE((warn_unused_result))
buf_block_t*
btr_free_root_check(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
index_id_t index_id,
mtr_t* mtr)
{
@@ -1028,7 +1035,7 @@ btr_free_root_check(
ut_ad(index_id != BTR_FREED_INDEX_ID);
buf_block_t* block = buf_page_get(
- page_id, page_size, RW_X_LATCH, mtr);
+ page_id, zip_size, RW_X_LATCH, mtr);
if (block) {
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
@@ -1049,21 +1056,18 @@ btr_free_root_check(
/** Create the root node for a new index tree.
@param[in] type type of the index
-@param[in,out] space tablespace where created
@param[in] index_id index id
-@param[in] index index, or NULL when applying TRUNCATE
-log record during recovery
-@param[in] btr_redo_create_info used for applying TRUNCATE log
-@param[in] mtr mini-transaction handle
-record during recovery
-@return page number of the created root, FIL_NULL if did not succeed */
+@param[in,out] space tablespace where created
+@param[in] index index
+@param[in,out] mtr mini-transaction
+@return page number of the created root
+@retval FIL_NULL if did not succeed */
ulint
btr_create(
ulint type,
fil_space_t* space,
index_id_t index_id,
dict_index_t* index,
- const btr_create_t* btr_redo_create_info,
mtr_t* mtr)
{
buf_block_t* block;
@@ -1078,7 +1082,7 @@ btr_create(
(for an ibuf tree, not in the root, but on a separate ibuf header
page) */
- if (type & DICT_IBUF) {
+ if (UNIV_UNLIKELY(type & DICT_IBUF)) {
/* Allocate first the ibuf header page */
buf_block_t* ibuf_hdr_block = fseg_create(
space, 0,
@@ -1110,8 +1114,7 @@ btr_create(
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- flst_init(block->frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- mtr);
+ flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
} else {
block = fseg_create(space, 0,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
@@ -1140,44 +1143,11 @@ btr_create(
page_zip = buf_block_get_page_zip(block);
if (page_zip) {
- if (index != NULL) {
- page = page_create_zip(block, index, 0, 0, NULL, mtr);
- } else {
- /* Create a compressed index page when applying
- TRUNCATE log record during recovery */
- ut_ad(btr_redo_create_info != NULL);
-
- redo_page_compress_t page_comp_info;
-
- page_comp_info.type = type;
-
- page_comp_info.index_id = index_id;
-
- page_comp_info.n_fields =
- btr_redo_create_info->n_fields;
-
- page_comp_info.field_len =
- btr_redo_create_info->field_len;
-
- page_comp_info.fields = btr_redo_create_info->fields;
-
- page_comp_info.trx_id_pos =
- btr_redo_create_info->trx_id_pos;
-
- page = page_create_zip(block, NULL, 0, 0,
- &page_comp_info, mtr);
- }
+ page = page_create_zip(block, index, 0, 0, mtr);
} else {
- if (index != NULL) {
- page = page_create(block, mtr,
- dict_table_is_comp(index->table),
- dict_index_is_spatial(index));
- } else {
- ut_ad(btr_redo_create_info != NULL);
- page = page_create(
- block, mtr, btr_redo_create_info->format_flags,
- type == DICT_SPATIAL);
- }
+ page = page_create(block, mtr,
+ dict_table_is_comp(index->table),
+ dict_index_is_spatial(index));
/* Set the level of the new index page */
btr_page_set_level(page, NULL, 0, mtr);
}
@@ -1186,21 +1156,32 @@ btr_create(
btr_page_set_index_id(page, page_zip, index_id, mtr);
/* Set the next node and previous node fields */
- btr_page_set_next(page, page_zip, FIL_NULL, mtr);
- btr_page_set_prev(page, page_zip, FIL_NULL, mtr);
-
- /* We reset the free bits for the page to allow creation of several
- trees in the same mtr, otherwise the latch on a bitmap page would
- prevent it because of the latching order.
+ compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+#if MYSQL_VERSION_ID < 100500
+ if (UNIV_LIKELY_NULL(page_zip)) {
+ /* Avoid tripping the ut_a() in mlog_parse_nbytes()
+ when crash-downgrading to an earlier MariaDB 10.4 version. */
+ btr_page_set_next(page, page_zip, FIL_NULL, mtr);
+ btr_page_set_prev(page, page_zip, FIL_NULL, mtr);
+ } else {
+ mlog_memset(block, FIL_PAGE_PREV, 8, 0xff, mtr);
+ }
+#else
+ mlog_memset(block, FIL_PAGE_PREV, 8, 0xff, mtr);
+ if (UNIV_LIKELY_NULL(page_zip)) {
+ memset(page_zip->data + FIL_PAGE_PREV, 0xff, 8);
+ }
+#endif
- index will be NULL if we are recreating the table during recovery
- on behalf of TRUNCATE.
+ /* We reset the free bits for the page in a separate
+ mini-transaction to allow creation of several trees in the
+ same mtr, otherwise the latch on a bitmap page would prevent
+ it because of the latching order.
Note: Insert Buffering is disabled for temporary tables given that
most temporary tables are smaller in size and short-lived. */
- if (!(type & DICT_CLUSTERED)
- && (index == NULL || !index->table->is_temporary())) {
-
+ if (!(type & DICT_CLUSTERED) && !index->table->is_temporary()) {
ibuf_reset_free_bits(block);
}
@@ -1281,18 +1262,18 @@ top_loop:
/** Free a persistent index tree if it exists.
@param[in] page_id root page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction */
void
btr_free_if_exists(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
index_id_t index_id,
mtr_t* mtr)
{
buf_block_t* root = btr_free_root_check(
- page_id, page_size, index_id, mtr);
+ page_id, zip_size, index_id, mtr);
if (root == NULL) {
return;
@@ -1303,20 +1284,15 @@ btr_free_if_exists(
btr_free_root(root, mtr, true);
}
-/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
-@param[in] page_id root page id
-@param[in] page_size page size */
-void
-btr_free(
- const page_id_t page_id,
- const page_size_t& page_size)
+/** Free an index tree in a temporary tablespace.
+@param[in] page_id root page id */
+void btr_free(const page_id_t page_id)
{
mtr_t mtr;
mtr.start();
mtr.set_log_mode(MTR_LOG_NO_REDO);
- buf_block_t* block = buf_page_get(
- page_id, page_size, RW_X_LATCH, &mtr);
+ buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
if (block) {
btr_free_but_not_root(block, MTR_LOG_NO_REDO);
@@ -1340,7 +1316,7 @@ btr_read_autoinc(dict_index_t* index)
ib_uint64_t autoinc;
if (buf_block_t* block = buf_page_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_S_LATCH, &mtr)) {
autoinc = page_get_autoinc(block->frame);
} else {
@@ -1372,7 +1348,7 @@ btr_read_autoinc_with_fallback(const dict_table_t* table, unsigned col_no)
mtr.start();
buf_block_t* block = buf_page_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_S_LATCH, &mtr);
ib_uint64_t autoinc = block ? page_get_autoinc(block->frame) : 0;
@@ -1417,7 +1393,7 @@ btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset)
fil_space_t* space = index->table->space;
mtr.set_named_space(space);
page_set_autoinc(buf_page_get(page_id_t(space->id, index->page),
- page_size_t(space->flags),
+ space->zip_size(),
RW_SX_LATCH, &mtr),
index, autoinc, &mtr, reset);
mtr.commit();
@@ -1544,7 +1520,7 @@ btr_page_reorganize_low(
}
if (page_zip
- && !page_zip_compress(page_zip, page, index, z_level, NULL, mtr)) {
+ && !page_zip_compress(page_zip, page, index, z_level, mtr)) {
/* Restore the old page and exit. */
#if defined UNIV_DEBUG || defined UNIV_ZIP_DEBUG
@@ -1570,11 +1546,6 @@ btr_page_reorganize_low(
goto func_exit;
}
- if (!recovery && !dict_table_is_locking_disabled(index->table)) {
- /* Update the record lock bitmaps */
- lock_move_reorganize_page(block, temp_block);
- }
-
data_size2 = page_get_data_size(page);
max_ins_size2 = page_get_max_insert_size_after_reorganize(page, 1);
@@ -1598,21 +1569,41 @@ btr_page_reorganize_low(
ut_ad(cursor->rec == page_get_infimum_rec(page));
}
-func_exit:
#ifdef UNIV_ZIP_DEBUG
ut_a(!page_zip || page_zip_validate(page_zip, page, index));
#endif /* UNIV_ZIP_DEBUG */
- if (!recovery && block->page.id.page_no() == index->page
- && fil_page_get_type(temp_page) == FIL_PAGE_TYPE_INSTANT) {
- /* Preserve the PAGE_INSTANT information. */
- ut_ad(!page_zip);
- ut_ad(index->is_instant());
- memcpy(FIL_PAGE_TYPE + page, FIL_PAGE_TYPE + temp_page, 2);
- memcpy(PAGE_HEADER + PAGE_INSTANT + page,
- PAGE_HEADER + PAGE_INSTANT + temp_page, 2);
+ if (!recovery) {
+ if (block->page.id.page_no() == index->page
+ && fil_page_get_type(temp_page) == FIL_PAGE_TYPE_INSTANT) {
+ /* Preserve the PAGE_INSTANT information. */
+ ut_ad(!page_zip);
+ ut_ad(index->is_instant());
+ memcpy(FIL_PAGE_TYPE + page,
+ FIL_PAGE_TYPE + temp_page, 2);
+ memcpy(PAGE_HEADER + PAGE_INSTANT + page,
+ PAGE_HEADER + PAGE_INSTANT + temp_page, 2);
+ if (!index->table->instant) {
+ } else if (page_is_comp(page)) {
+ memcpy(PAGE_NEW_INFIMUM + page,
+ PAGE_NEW_INFIMUM + temp_page, 8);
+ memcpy(PAGE_NEW_SUPREMUM + page,
+ PAGE_NEW_SUPREMUM + temp_page, 8);
+ } else {
+ memcpy(PAGE_OLD_INFIMUM + page,
+ PAGE_OLD_INFIMUM + temp_page, 8);
+ memcpy(PAGE_OLD_SUPREMUM + page,
+ PAGE_OLD_SUPREMUM + temp_page, 8);
+ }
+ }
+
+ if (!dict_table_is_locking_disabled(index->table)) {
+ /* Update the record lock bitmaps */
+ lock_move_reorganize_page(block, temp_block);
+ }
}
+func_exit:
buf_block_free(temp_block);
/* Restore logging mode */
@@ -1658,6 +1649,14 @@ func_exit:
mach_read_from_2(PAGE_HEADER + PAGE_INSTANT
+ page),
MLOG_2BYTES, mtr);
+ if (!index->table->instant) {
+ } else if (page_is_comp(page)) {
+ mlog_log_string(PAGE_NEW_INFIMUM + page, 8, mtr);
+ mlog_log_string(PAGE_NEW_SUPREMUM + page, 8, mtr);
+ } else {
+ mlog_log_string(PAGE_OLD_INFIMUM + page, 8, mtr);
+ mlog_log_string(PAGE_OLD_SUPREMUM + page, 8, mtr);
+ }
}
return(success);
@@ -1796,7 +1795,7 @@ btr_page_empty(
: 0;
if (page_zip) {
- page_create_zip(block, index, level, autoinc, NULL, mtr);
+ page_create_zip(block, index, level, autoinc, mtr);
} else {
page_create(block, mtr, dict_table_is_comp(index->table),
dict_index_is_spatial(index));
@@ -1808,6 +1807,65 @@ btr_page_empty(
}
}
+/** Write instant ALTER TABLE metadata to a root page.
+@param[in,out] root clustered index root page
+@param[in] index clustered index with instant ALTER TABLE
+@param[in,out] mtr mini-transaction */
+void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr)
+{
+ ut_ad(index.n_core_fields > 0);
+ ut_ad(index.n_core_fields < REC_MAX_N_FIELDS);
+ ut_ad(index.is_instant());
+ ut_ad(fil_page_get_type(root->frame) == FIL_PAGE_TYPE_INSTANT
+ || fil_page_get_type(root->frame) == FIL_PAGE_INDEX);
+ ut_ad(!page_has_siblings(root->frame));
+ ut_ad(root->page.id.page_no() == index.page);
+
+ rec_t* infimum = page_get_infimum_rec(root->frame);
+ rec_t* supremum = page_get_supremum_rec(root->frame);
+ byte* page_type = root->frame + FIL_PAGE_TYPE;
+ uint16_t i = page_header_get_field(root->frame, PAGE_INSTANT);
+
+ switch (mach_read_from_2(page_type)) {
+ case FIL_PAGE_TYPE_INSTANT:
+ ut_ad(page_get_instant(root->frame) == index.n_core_fields);
+ if (memcmp(infimum, "infimum", 8)
+ || memcmp(supremum, "supremum", 8)) {
+ ut_ad(index.table->instant);
+ ut_ad(!memcmp(infimum, field_ref_zero, 8));
+ ut_ad(!memcmp(supremum, field_ref_zero, 7));
+ /* The n_core_null_bytes only matters for
+ ROW_FORMAT=COMPACT and ROW_FORMAT=DYNAMIC tables. */
+ ut_ad(supremum[7] == index.n_core_null_bytes
+ || !index.table->not_redundant());
+ return;
+ }
+ break;
+ default:
+ ut_ad(!"wrong page type");
+ /* fall through */
+ case FIL_PAGE_INDEX:
+ ut_ad(!page_is_comp(root->frame)
+ || !page_get_instant(root->frame));
+ ut_ad(!memcmp(infimum, "infimum", 8));
+ ut_ad(!memcmp(supremum, "supremum", 8));
+ mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT,
+ MLOG_2BYTES, mtr);
+ ut_ad(i <= PAGE_NO_DIRECTION);
+ i |= index.n_core_fields << 3;
+ mlog_write_ulint(PAGE_HEADER + PAGE_INSTANT + root->frame, i,
+ MLOG_2BYTES, mtr);
+ break;
+ }
+
+ if (index.table->instant) {
+ mlog_memset(root, infimum - root->frame, 8, 0, mtr);
+ mlog_memset(root, supremum - root->frame, 7, 0, mtr);
+ mlog_write_ulint(&supremum[7], index.n_core_null_bytes,
+ MLOG_1BYTE, mtr);
+ }
+}
+
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
@@ -1891,8 +1949,23 @@ btr_root_raise_and_insert(
btr_page_create(new_block, new_page_zip, index, level, mtr);
/* Set the next node and previous node fields of new page */
- btr_page_set_next(new_page, new_page_zip, FIL_NULL, mtr);
- btr_page_set_prev(new_page, new_page_zip, FIL_NULL, mtr);
+ compile_time_assert(FIL_PAGE_NEXT == FIL_PAGE_PREV + 4);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+#if MYSQL_VERSION_ID < 100500
+ if (UNIV_LIKELY_NULL(new_page_zip)) {
+ /* Avoid tripping the ut_a() in mlog_parse_nbytes()
+ when crash-downgrading to an earlier MariaDB 10.4 version. */
+ btr_page_set_next(new_page, new_page_zip, FIL_NULL, mtr);
+ btr_page_set_prev(new_page, new_page_zip, FIL_NULL, mtr);
+ } else {
+ mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, mtr);
+ }
+#else
+ mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, mtr);
+ if (UNIV_LIKELY_NULL(new_page_zip)) {
+ memset(new_page_zip->data + FIL_PAGE_PREV, 0xff, 8);
+ }
+#endif
/* Copy the records from root to the new page one by one. */
@@ -1993,11 +2066,7 @@ btr_root_raise_and_insert(
if (index->is_instant()) {
ut_ad(!root_page_zip);
- byte* page_type = root_block->frame + FIL_PAGE_TYPE;
- ut_ad(mach_read_from_2(page_type) == FIL_PAGE_INDEX);
- mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT,
- MLOG_2BYTES, mtr);
- page_set_instant(root_block->frame, index->n_core_fields, mtr);
+ btr_set_instant(root_block, *index, mtr);
}
ut_ad(!page_has_siblings(root));
@@ -2067,7 +2136,7 @@ rec_t* btr_page_get_split_rec_to_left(const btr_cur_t* cursor)
|| cursor->index->is_instant()
|| !(rec_get_info_bits(page_rec_get_next_const(
page_get_infimum_rec(page)),
- dict_table_is_comp(cursor->index->table))
+ cursor->index->table->not_redundant())
& REC_INFO_MIN_REC_FLAG));
const rec_t* infimum = page_get_infimum_rec(page);
@@ -2510,12 +2579,12 @@ btr_attach_half_pages(
/* for consistency, both blocks should be locked, before change */
if (prev_page_no != FIL_NULL && direction == FSP_DOWN) {
prev_block = btr_block_get(
- page_id_t(space, prev_page_no), block->page.size,
+ page_id_t(space, prev_page_no), block->zip_size(),
RW_X_LATCH, index, mtr);
}
if (next_page_no != FIL_NULL && direction != FSP_DOWN) {
next_block = btr_block_get(
- page_id_t(space, next_page_no), block->page.size,
+ page_id_t(space, next_page_no), block->zip_size(),
RW_X_LATCH, index, mtr);
}
@@ -2665,7 +2734,7 @@ btr_insert_into_right_sibling(
const ulint space = block->page.id.space();
next_block = btr_block_get(
- page_id_t(space, next_page_no), block->page.size,
+ page_id_t(space, next_page_no), block->zip_size(),
RW_X_LATCH, cursor->index, mtr);
next_page = buf_block_get_frame(next_block);
@@ -2691,7 +2760,7 @@ btr_insert_into_right_sibling(
if (rec == NULL) {
if (is_leaf
- && next_block->page.size.is_compressed()
+ && next_block->page.zip.ssize
&& !dict_index_is_clust(cursor->index)
&& !cursor->index->table->is_temporary()) {
/* Reset the IBUF_BITMAP_FREE bits, because
@@ -2739,7 +2808,7 @@ btr_insert_into_right_sibling(
/* Update the free bits of the B-tree page in the
insert buffer bitmap. */
- if (next_block->page.size.is_compressed()) {
+ if (next_block->page.zip.ssize) {
ibuf_update_free_bits_zip(next_block, mtr);
} else {
ibuf_update_free_bits_if_full(
@@ -3152,16 +3221,16 @@ func_exit:
return(rec);
}
-/** Removes a page from the level list of pages.
+/** Remove a page from the level list of pages.
@param[in] space space where removed
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] page page to remove
@param[in] index index tree
@param[in,out] mtr mini-transaction */
void
btr_level_list_remove_func(
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
page_t* page,
dict_index_t* index,
mtr_t* mtr)
@@ -3180,7 +3249,7 @@ btr_level_list_remove_func(
if (prev_page_no != FIL_NULL) {
buf_block_t* prev_block
= btr_block_get(page_id_t(space, prev_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
page_t* prev_page
= buf_block_get_frame(prev_block);
@@ -3198,7 +3267,7 @@ btr_level_list_remove_func(
if (next_page_no != FIL_NULL) {
buf_block_t* next_block
= btr_block_get(
- page_id_t(space, next_page_no), page_size,
+ page_id_t(space, next_page_no), zip_size,
RW_X_LATCH, index, mtr);
page_t* next_page
@@ -3403,12 +3472,7 @@ btr_lift_page_up(
if (index->is_instant()
&& father_block->page.id.page_no() == root_page_no) {
ut_ad(!father_page_zip);
- byte* page_type = father_block->frame + FIL_PAGE_TYPE;
- ut_ad(mach_read_from_2(page_type) == FIL_PAGE_INDEX);
- mlog_write_ulint(page_type, FIL_PAGE_TYPE_INSTANT,
- MLOG_2BYTES, mtr);
- page_set_instant(father_block->frame,
- index->n_core_fields, mtr);
+ btr_set_instant(father_block, *index, mtr);
}
page_level++;
@@ -3545,7 +3609,7 @@ btr_compress(
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
MONITOR_INC(MONITOR_INDEX_MERGE_ATTEMPTS);
@@ -3703,7 +3767,7 @@ retry:
/* Remove the page from the level list */
btr_level_list_remove(index->table->space_id,
- page_size, page, index, mtr);
+ zip_size, page, index, mtr);
if (dict_index_is_spatial(index)) {
rec_t* my_rec = father_cursor.page_cur.rec;
@@ -3833,7 +3897,7 @@ retry:
/* Remove the page from the level list */
btr_level_list_remove(index->table->space_id,
- page_size, page, index, mtr);
+ zip_size, page, index, mtr);
ut_ad(btr_node_ptr_get_child_page_no(
btr_cur_get_rec(&father_cursor), offsets)
@@ -3941,7 +4005,7 @@ retry:
committed mini-transaction, because in crash recovery,
the free bits could momentarily be set too high. */
- if (page_size.is_compressed()) {
+ if (zip_size) {
/* Because the free bits may be incremented
and we cannot update the insert buffer bitmap
in the same mini-transaction, the only safe
@@ -4001,7 +4065,7 @@ func_exit:
err_exit:
/* We play it safe and reset the free bits. */
- if (page_size.is_compressed()
+ if (zip_size
&& merge_page
&& page_is_leaf(merge_page)
&& !dict_index_is_clust(index)) {
@@ -4084,15 +4148,42 @@ btr_discard_only_page_on_level(
}
#endif /* UNIV_BTR_DEBUG */
+ mem_heap_t* heap = NULL;
+ const rec_t* rec = NULL;
+ offset_t* offsets = NULL;
+ if (index->table->instant) {
+ const rec_t* r = page_rec_get_next(page_get_infimum_rec(
+ block->frame));
+ ut_ad(rec_is_metadata(r, *index) == index->is_instant());
+ if (rec_is_alter_metadata(r, *index)) {
+ heap = mem_heap_create(srv_page_size);
+ offsets = rec_get_offsets(r, index, NULL, true,
+ ULINT_UNDEFINED, &heap);
+ rec = rec_copy(mem_heap_alloc(heap,
+ rec_offs_size(offsets)),
+ r, offsets);
+ rec_offs_make_valid(rec, index, true, offsets);
+ }
+ }
+
btr_page_empty(block, buf_block_get_page_zip(block), index, 0, mtr);
ut_ad(page_is_leaf(buf_block_get_frame(block)));
/* btr_page_empty() is supposed to zero-initialize the field. */
ut_ad(!page_get_instant(block->frame));
if (index->is_primary()) {
- /* Concurrent access is prevented by the root_block->lock
- X-latch, so this should be safe. */
- index->remove_instant();
+ if (rec) {
+ DBUG_ASSERT(index->table->instant);
+ DBUG_ASSERT(rec_is_alter_metadata(rec, *index));
+ btr_set_instant(block, *index, mtr);
+ rec = page_cur_insert_rec_low(
+ page_get_infimum_rec(block->frame),
+ index, rec, offsets, mtr);
+ ut_ad(rec);
+ mem_heap_free(heap);
+ } else if (index->is_instant()) {
+ index->clear_instant_add();
+ }
} else if (!index->table->is_temporary()) {
/* We play it safe and reset the free bits for the root */
ibuf_reset_free_bits(block);
@@ -4148,12 +4239,12 @@ btr_discard_page(
left_page_no = btr_page_get_prev(buf_block_get_frame(block));
right_page_no = btr_page_get_next(buf_block_get_frame(block));
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
ut_d(bool parent_is_different = false);
if (left_page_no != FIL_NULL) {
merge_block = btr_block_get(
page_id_t(index->table->space_id, left_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
@@ -4169,7 +4260,7 @@ btr_discard_page(
} else if (right_page_no != FIL_NULL) {
merge_block = btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
merge_page = buf_block_get_frame(merge_block);
#ifdef UNIV_BTR_DEBUG
@@ -4211,7 +4302,7 @@ btr_discard_page(
}
/* Remove the page from the level list */
- btr_level_list_remove(index->table->space_id, page_size,
+ btr_level_list_remove(index->table->space_id, zip_size,
page, index, mtr);
#ifdef UNIV_ZIP_DEBUG
@@ -4386,7 +4477,7 @@ btr_print_index(
mtr_commit(&mtr);
- ut_ad(btr_validate_index(index, 0, false));
+ ut_ad(btr_validate_index(index, 0));
}
#endif /* UNIV_BTR_PRINT */
@@ -4511,14 +4602,32 @@ btr_index_rec_validate(
return(FALSE);
}
+ const bool is_alter_metadata = page_is_leaf(page)
+ && !page_has_prev(page)
+ && index->is_primary() && index->table->instant
+ && rec == page_rec_get_next_const(page_get_infimum_rec(page));
+
+ if (is_alter_metadata
+ && !rec_is_alter_metadata(rec, page_is_comp(page))) {
+ btr_index_rec_validate_report(page, rec, index);
+
+ ib::error() << "First record is not ALTER TABLE metadata";
+ return FALSE;
+ }
+
if (!page_is_comp(page)) {
const ulint n_rec_fields = rec_get_n_fields_old(rec);
if (n_rec_fields == DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD
&& index->id == DICT_INDEXES_ID) {
/* A record for older SYS_INDEXES table
(missing merge_threshold column) is acceptable. */
+ } else if (is_alter_metadata) {
+ if (n_rec_fields != ulint(index->n_fields) + 1) {
+ goto n_field_mismatch;
+ }
} else if (n_rec_fields < index->n_core_fields
|| n_rec_fields > index->n_fields) {
+n_field_mismatch:
btr_index_rec_validate_report(page, rec, index);
ib::error() << "Has " << rec_get_n_fields_old(rec)
@@ -4537,15 +4646,28 @@ btr_index_rec_validate(
offsets = rec_get_offsets(rec, index, offsets, page_is_leaf(page),
ULINT_UNDEFINED, &heap);
+ const dict_field_t* field = index->fields;
+ ut_ad(rec_offs_n_fields(offsets)
+ == ulint(index->n_fields) + is_alter_metadata);
- for (unsigned i = 0; i < index->n_fields; i++) {
- dict_field_t* field = dict_index_get_nth_field(index, i);
- ulint fixed_size = dict_col_get_fixed_size(
- dict_field_get_col(field),
- page_is_comp(page));
-
+ for (unsigned i = 0; i < rec_offs_n_fields(offsets); i++) {
rec_get_nth_field_offs(offsets, i, &len);
+ ulint fixed_size;
+
+ if (is_alter_metadata && i == index->first_user_field()) {
+ fixed_size = FIELD_REF_SIZE;
+ if (len != FIELD_REF_SIZE
+ || !rec_offs_nth_extern(offsets, i)) {
+ goto len_mismatch;
+ }
+
+ continue;
+ } else {
+ fixed_size = dict_col_get_fixed_size(
+ field->col, page_is_comp(page));
+ }
+
/* Note that if fixed_size != 0, it equals the
length of a fixed-size column in the clustered index.
We should adjust it here.
@@ -4557,8 +4679,8 @@ btr_index_rec_validate(
&& (field->prefix_len
? len > field->prefix_len
: (fixed_size && len != fixed_size))) {
+len_mismatch:
btr_index_rec_validate_report(page, rec, index);
-
ib::error error;
error << "Field " << i << " len is " << len
@@ -4576,6 +4698,8 @@ btr_index_rec_validate(
}
return(FALSE);
}
+
+ field++;
}
#ifdef VIRTUAL_INDEX_DEBUG
@@ -4741,19 +4865,7 @@ btr_validate_level(
page = buf_block_get_frame(block);
fil_space_t* space = index->table->space;
- const page_size_t table_page_size(
- dict_table_page_size(index->table));
- const page_size_t space_page_size(space->flags);
-
- if (!table_page_size.equals_to(space_page_size)) {
-
- ib::warn() << "Flags mismatch: table=" << index->table->flags
- << ", tablespace=" << space->flags;
-
- mtr_commit(&mtr);
-
- return(false);
- }
+ const ulint zip_size = space->zip_size();
while (level != btr_page_get_level(page)) {
const rec_t* node_ptr;
@@ -4806,7 +4918,7 @@ btr_validate_level(
block = btr_block_get(
page_id_t(index->table->space_id,
left_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
page = buf_block_get_frame(block);
left_page_no = btr_page_get_prev(page);
@@ -4877,7 +4989,7 @@ loop:
right_block = btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
right_page = buf_block_get_frame(right_block);
@@ -5053,13 +5165,13 @@ loop:
btr_block_get(
page_id_t(index->table->space_id,
parent_right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
right_block = btr_block_get(
page_id_t(index->table->space_id,
right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
}
@@ -5137,21 +5249,21 @@ node_ptr_fails:
page_id_t(
index->table->space_id,
parent_right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
}
} else if (parent_page_no != FIL_NULL) {
btr_block_get(
page_id_t(index->table->space_id,
parent_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
}
}
block = btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- table_page_size,
+ zip_size,
RW_SX_LATCH, index, &mtr);
page = buf_block_get_frame(block);
@@ -5165,57 +5277,16 @@ node_ptr_fails:
}
/**************************************************************//**
-Do an index level validation of spaital index tree.
-@return true if no error found */
-static
-bool
-btr_validate_spatial_index(
-/*=======================*/
- dict_index_t* index, /*!< in: index */
- const trx_t* trx) /*!< in: transaction or NULL */
-{
-
- mtr_t mtr;
- bool ok = true;
-
- mtr.start();
-
- mtr_x_lock_index(index, &mtr);
-
- page_t* root = btr_root_get(index, &mtr);
- ulint n = btr_page_get_level(root);
-
-#ifdef UNIV_RTR_DEBUG
- fprintf(stderr, "R-tree level is %lu\n", n);
-#endif /* UNIV_RTR_DEBUG */
-
- for (ulint i = 0; i <= n; ++i) {
-#ifdef UNIV_RTR_DEBUG
- fprintf(stderr, "Level %lu:\n", n - i);
-#endif /* UNIV_RTR_DEBUG */
-
- if (!btr_validate_level(index, trx, n - i, true)) {
- ok = false;
- break;
- }
- }
-
- mtr.commit();
-
- return(ok);
-}
-
-/**************************************************************//**
Checks the consistency of an index tree.
@return DB_SUCCESS if ok, error code if not */
dberr_t
btr_validate_index(
/*===============*/
dict_index_t* index, /*!< in: index */
- const trx_t* trx, /*!< in: transaction or NULL */
- bool lockout)/*!< in: true if X-latch index is intended */
+ const trx_t* trx) /*!< in: transaction or NULL */
{
dberr_t err = DB_SUCCESS;
+ bool lockout = dict_index_is_spatial(index);
/* Full Text index are implemented by auxiliary tables,
not the B-tree */
@@ -5223,13 +5294,6 @@ btr_validate_index(
return(err);
}
- if (dict_index_is_spatial(index)) {
- if(!btr_validate_spatial_index(index, trx)) {
- err = DB_ERROR;
- }
- return(err);
- }
-
mtr_t mtr;
mtr_start(&mtr);
@@ -5245,13 +5309,13 @@ btr_validate_index(
page_t* root = btr_root_get(index, &mtr);
if (!root) {
- err = DB_CORRUPTION;
mtr_commit(&mtr);
- return err;
+ return DB_CORRUPTION;
}
ulint n = btr_page_get_level(root);
+ btr_validate_index_running++;
for (ulint i = 0; i <= n; ++i) {
if (!btr_validate_level(index, trx, n - i, lockout)) {
@@ -5261,6 +5325,14 @@ btr_validate_index(
}
mtr_commit(&mtr);
+ /* In theory we need release barrier here, so that
+ btr_validate_index_running decrement is guaranteed to
+ happen after latches are released.
+
+ Original code issued SEQ_CST on update and non-atomic
+ access on load. Which means it had broken synchronisation
+ as well. */
+ btr_validate_index_running--;
return(err);
}
@@ -5297,9 +5369,9 @@ btr_can_merge_with_page(
page = btr_cur_get_page(cursor);
const page_id_t page_id(index->table->space_id, page_no);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
- mblock = btr_block_get(page_id, page_size, RW_X_LATCH, index, mtr);
+ mblock = btr_block_get(page_id, zip_size, RW_X_LATCH, index, mtr);
mpage = buf_block_get_frame(mblock);
n_recs = page_get_n_recs(page);
@@ -5315,7 +5387,7 @@ btr_can_merge_with_page(
/* If compression padding tells us that merging will result in
too packed up page i.e.: which is likely to cause compression
failure then don't merge the pages. */
- if (page_size.is_compressed() && page_is_leaf(mpage)
+ if (zip_size && page_is_leaf(mpage)
&& (page_get_data_size(mpage) + data_size
>= dict_index_zip_pad_optimal_page_size(index))) {
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index 3e170017408..4f341d3b2c6 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -94,7 +94,7 @@ PageBulk::init()
if (new_page_zip) {
page_create_zip(new_block, m_index, m_level, 0,
- NULL, &m_mtr);
+ &m_mtr);
memset(FIL_PAGE_PREV + new_page, 0xff, 8);
page_zip_write_header(new_page_zip,
FIL_PAGE_PREV + new_page,
@@ -107,12 +107,12 @@ PageBulk::init()
} else {
ut_ad(!dict_index_is_spatial(m_index));
page_create(new_block, &m_mtr,
- dict_table_is_comp(m_index->table),
+ m_index->table->not_redundant(),
false);
- mlog_write_ulint(FIL_PAGE_PREV + new_page, FIL_NULL,
- MLOG_4BYTES, &m_mtr);
- mlog_write_ulint(FIL_PAGE_NEXT + new_page, FIL_NULL,
- MLOG_4BYTES, &m_mtr);
+ compile_time_assert(FIL_PAGE_NEXT
+ == FIL_PAGE_PREV + 4);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mlog_memset(new_block, FIL_PAGE_PREV, 8, 0xff, &m_mtr);
mlog_write_ulint(PAGE_HEADER + PAGE_LEVEL + new_page,
m_level, MLOG_2BYTES, &m_mtr);
mlog_write_ull(PAGE_HEADER + PAGE_INDEX_ID + new_page,
@@ -121,7 +121,7 @@ PageBulk::init()
} else {
new_block = btr_block_get(
page_id_t(m_index->table->space_id, m_page_no),
- page_size_t(m_index->table->space->flags),
+ m_index->table->space->zip_size(),
RW_X_LATCH, m_index, &m_mtr);
new_page = buf_block_get_frame(new_block);
@@ -374,7 +374,7 @@ PageBulk::compress()
ut_ad(m_page_zip != NULL);
return(page_zip_compress(m_page_zip, m_page, m_index,
- page_zip_level, NULL, &m_mtr));
+ page_zip_level, &m_mtr));
}
/** Get node pointer
@@ -589,8 +589,9 @@ PageBulk::needExt(
const dtuple_t* tuple,
ulint rec_size)
{
- return(page_zip_rec_needs_ext(rec_size, m_is_comp,
- dtuple_get_n_fields(tuple), m_block->page.size));
+ return page_zip_rec_needs_ext(rec_size, m_is_comp,
+ dtuple_get_n_fields(tuple),
+ m_block->zip_size());
}
/** Store external record
@@ -662,7 +663,7 @@ PageBulk::latch()
__FILE__, __LINE__, &m_mtr)) {
m_block = buf_page_get_gen(page_id_t(m_index->table->space_id,
m_page_no),
- univ_page_size, RW_X_LATCH,
+ 0, RW_X_LATCH,
m_block, BUF_GET_IF_IN_POOL,
__FILE__, __LINE__, &m_mtr, &m_err);
@@ -1019,7 +1020,7 @@ BtrBulk::finish(dberr_t err)
ut_ad(last_page_no != FIL_NULL);
last_block = btr_block_get(
page_id_t(m_index->table->space_id, last_page_no),
- page_size_t(m_index->table->space->flags),
+ m_index->table->space->zip_size(),
RW_X_LATCH, m_index, &mtr);
first_rec = page_rec_get_next(
page_get_infimum_rec(last_block->frame));
@@ -1048,6 +1049,6 @@ BtrBulk::finish(dberr_t err)
ut_ad(!sync_check_iterate(dict_sync_check()));
ut_ad(err != DB_SUCCESS
- || btr_validate_index(m_index, NULL, false) == DB_SUCCESS);
+ || btr_validate_index(m_index, NULL) == DB_SUCCESS);
return(err);
}
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index c79ea1c5467..f58628c5113 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -98,7 +98,7 @@ throughput clearly from about 100000. */
#define BTR_CUR_FINE_HISTORY_LENGTH 100000
/** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */
-ulint btr_cur_n_non_sea;
+Atomic_counter<ulint> btr_cur_n_non_sea;
/** Old value of btr_cur_n_non_sea. Copied by
srv_refresh_innodb_monitor_stats(). Referenced by
srv_printf_innodb_monitor(). */
@@ -210,6 +210,7 @@ btr_rec_free_externally_stored_fields(
/** Latches the leaf page or pages requested.
@param[in] block leaf page where the search converged
@param[in] page_id page id of the leaf
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] latch_mode BTR_SEARCH_LEAF, ...
@param[in] cursor cursor
@param[in] mtr mini-transaction
@@ -218,7 +219,7 @@ btr_latch_leaves_t
btr_cur_latch_leaves(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint latch_mode,
btr_cur_t* cursor,
mtr_t* mtr)
@@ -249,7 +250,7 @@ btr_cur_latch_leaves(
mode = latch_mode == BTR_MODIFY_LEAF ? RW_X_LATCH : RW_S_LATCH;
latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(page_id, page_size, mode,
+ get_block = btr_block_get(page_id, zip_size, mode,
cursor->index, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -282,7 +283,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
page_id_t(page_id.space(), left_page_no),
- page_size, RW_X_LATCH, cursor->index, mtr);
+ zip_size, RW_X_LATCH, cursor->index, mtr);
latch_leaves.blocks[0] = get_block;
if (spatial) {
@@ -298,7 +299,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
- page_id, page_size, RW_X_LATCH, cursor->index, mtr);
+ page_id, zip_size, RW_X_LATCH, cursor->index, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -328,7 +329,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[2] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
page_id_t(page_id.space(), right_page_no),
- page_size, RW_X_LATCH, cursor->index, mtr);
+ zip_size, RW_X_LATCH, cursor->index, mtr);
latch_leaves.blocks[2] = get_block;
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(get_block->frame)
@@ -356,7 +357,7 @@ btr_cur_latch_leaves(
latch_leaves.savepoints[0] = mtr_set_savepoint(mtr);
get_block = btr_block_get(
page_id_t(page_id.space(), left_page_no),
- page_size, mode, cursor->index, mtr);
+ zip_size, mode, cursor->index, mtr);
latch_leaves.blocks[0] = get_block;
cursor->left_block = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -368,7 +369,7 @@ btr_cur_latch_leaves(
}
latch_leaves.savepoints[1] = mtr_set_savepoint(mtr);
- get_block = btr_block_get(page_id, page_size, mode,
+ get_block = btr_block_get(page_id, zip_size, mode,
cursor->index, mtr);
latch_leaves.blocks[1] = get_block;
#ifdef UNIV_BTR_DEBUG
@@ -421,8 +422,12 @@ unreadable:
}
btr_cur_t cur;
+ /* Relax the assertion in rec_init_offsets(). */
+ ut_ad(!index->in_instant_init);
+ ut_d(index->in_instant_init = true);
dberr_t err = btr_cur_open_at_index_side(true, index, BTR_SEARCH_LEAF,
&cur, 0, mtr);
+ ut_d(index->in_instant_init = false);
if (err != DB_SUCCESS) {
index->table->corrupted = true;
return err;
@@ -456,8 +461,8 @@ unreadable:
return DB_CORRUPTION;
}
- if (info_bits != REC_INFO_MIN_REC_FLAG
- || (comp && rec_get_status(rec) != REC_STATUS_COLUMNS_ADDED)) {
+ if ((info_bits & ~REC_INFO_DELETED_FLAG) != REC_INFO_MIN_REC_FLAG
+ || (comp && rec_get_status(rec) != REC_STATUS_INSTANT)) {
incompatible:
ib::error() << "Table " << index->table->name
<< " contains unrecognizable instant ALTER metadata";
@@ -475,6 +480,117 @@ incompatible:
concurrent operations on the table, including table eviction
from the cache. */
+ if (info_bits & REC_INFO_DELETED_FLAG) {
+ /* This metadata record includes a BLOB that identifies
+ any dropped or reordered columns. */
+ ulint trx_id_offset = index->trx_id_offset;
+ /* If !index->trx_id_offset, the PRIMARY KEY contains
+ variable-length columns. For the metadata record,
+ variable-length columns should be written with zero
+ length. However, before MDEV-21088 was fixed, for
+ variable-length encoded PRIMARY KEY column of type
+ CHAR, we wrote more than zero bytes. That is why we
+ must determine the actual length of each PRIMARY KEY
+ column. The DB_TRX_ID will start right after any
+ PRIMARY KEY columns. */
+ ut_ad(index->n_uniq);
+
+ /* We cannot invoke rec_get_offsets() before
+ index->table->deserialise_columns(). Therefore,
+ we must duplicate some logic here. */
+ if (trx_id_offset) {
+ } else if (index->table->not_redundant()) {
+ /* The PRIMARY KEY contains variable-length columns.
+ For the metadata record, variable-length columns are
+ always written with zero length. The DB_TRX_ID will
+ start right after any fixed-length columns. */
+
+ /* OK, before MDEV-21088 was fixed, for
+ variable-length encoded PRIMARY KEY column of
+ type CHAR, we wrote more than zero bytes. In
+ order to allow affected tables to be accessed,
+ it would be nice to determine the actual
+ length of each PRIMARY KEY column. However, to
+ be able to do that, we should determine the
+ size of the null-bit bitmap in the metadata
+ record. And we cannot know that before reading
+ the metadata BLOB, whose starting point we are
+ trying to find here. (Although the PRIMARY KEY
+ columns cannot be NULL, we would have to know
+ where the lengths of variable-length PRIMARY KEY
+ columns start.)
+
+ So, unfortunately we cannot help users who
+ were affected by MDEV-21088 on a ROW_FORMAT=COMPACT
+ or ROW_FORMAT=DYNAMIC table. */
+
+ for (uint i = index->n_uniq; i--; ) {
+ trx_id_offset += index->fields[i].fixed_len;
+ }
+ } else if (rec_get_1byte_offs_flag(rec)) {
+ trx_id_offset = rec_1_get_field_end_info(
+ rec, index->n_uniq - 1);
+ ut_ad(!(trx_id_offset & REC_1BYTE_SQL_NULL_MASK));
+ trx_id_offset &= ~REC_1BYTE_SQL_NULL_MASK;
+ } else {
+ trx_id_offset = rec_2_get_field_end_info(
+ rec, index->n_uniq - 1);
+ ut_ad(!(trx_id_offset & REC_2BYTE_SQL_NULL_MASK));
+ trx_id_offset &= ~REC_2BYTE_SQL_NULL_MASK;
+ }
+
+ const byte* ptr = rec + trx_id_offset
+ + (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN);
+
+ if (mach_read_from_4(ptr + BTR_EXTERN_LEN)) {
+ goto incompatible;
+ }
+
+ uint len = mach_read_from_4(ptr + BTR_EXTERN_LEN + 4);
+ if (!len
+ || mach_read_from_4(ptr + BTR_EXTERN_OFFSET)
+ != FIL_PAGE_DATA
+ || mach_read_from_4(ptr + BTR_EXTERN_SPACE_ID)
+ != space->id) {
+ goto incompatible;
+ }
+
+ buf_block_t* block = buf_page_get(
+ page_id_t(space->id,
+ mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
+ 0, RW_S_LATCH, mtr);
+ buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
+ if (fil_page_get_type(block->frame) != FIL_PAGE_TYPE_BLOB
+ || mach_read_from_4(&block->frame[FIL_PAGE_DATA
+ + BTR_BLOB_HDR_NEXT_PAGE_NO])
+ != FIL_NULL
+ || mach_read_from_4(&block->frame[FIL_PAGE_DATA
+ + BTR_BLOB_HDR_PART_LEN])
+ != len) {
+ goto incompatible;
+ }
+
+ /* The unused part of the BLOB page should be zero-filled. */
+ for (const byte* b = block->frame
+ + (FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE) + len,
+ * const end = block->frame + srv_page_size
+ - BTR_EXTERN_LEN;
+ b < end; ) {
+ if (*b++) {
+ goto incompatible;
+ }
+ }
+
+ if (index->table->deserialise_columns(
+ &block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE],
+ len)) {
+ goto incompatible;
+ }
+
+ /* Proceed to initialize the default values of
+ any instantly added columns. */
+ }
+
mem_heap_t* heap = NULL;
offset_t* offsets = rec_get_offsets(rec, index, NULL, true,
ULINT_UNDEFINED, &heap);
@@ -488,7 +604,8 @@ inconsistent:
record, it is also OK to perform READ UNCOMMITTED and
then ignore any extra fields, provided that
trx_sys.is_registered(DB_TRX_ID). */
- if (rec_offs_n_fields(offsets) > index->n_fields
+ if (rec_offs_n_fields(offsets)
+ > ulint(index->n_fields) + !!index->table->instant
&& !trx_sys.is_registered(current_trx(),
row_get_rec_trx_id(rec, index,
offsets))) {
@@ -496,10 +613,11 @@ inconsistent:
}
for (unsigned i = index->n_core_fields; i < index->n_fields; i++) {
- ulint len;
- const byte* data = rec_get_nth_field(rec, offsets, i, &len);
dict_col_t* col = index->fields[i].col;
- ut_ad(!col->is_instant());
+ const unsigned o = i + !!index->table->instant;
+ ulint len;
+ const byte* data = rec_get_nth_field(rec, offsets, o, &len);
+ ut_ad(!col->is_added());
ut_ad(!col->def_val.data);
col->def_val.len = len;
switch (len) {
@@ -510,7 +628,7 @@ inconsistent:
continue;
}
ut_ad(len != UNIV_SQL_DEFAULT);
- if (!rec_offs_nth_extern(offsets, i)) {
+ if (!rec_offs_nth_extern(offsets, o)) {
col->def_val.data = mem_heap_dup(
index->table->heap, data, len);
} else if (len < BTR_EXTERN_FIELD_REF_SIZE
@@ -522,7 +640,7 @@ inconsistent:
} else {
col->def_val.data = btr_copy_externally_stored_field(
&col->def_val.len, data,
- dict_table_page_size(index->table),
+ cur.page_cur.block->zip_size(),
len, index->table->heap);
}
}
@@ -591,30 +709,49 @@ bool btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
const uint16_t n = page_get_instant(page);
- if (n < index->n_uniq + DATA_ROLL_PTR || n > index->n_fields) {
+ if (n < index->n_uniq + DATA_ROLL_PTR) {
/* The PRIMARY KEY (or hidden DB_ROW_ID) and
DB_TRX_ID,DB_ROLL_PTR columns must always be present
- as 'core' fields. All fields, including those for
- instantly added columns, must be present in the data
- dictionary. */
+ as 'core' fields. */
return true;
}
- if (memcmp(page_get_infimum_rec(page), "infimum", 8)
- || memcmp(page_get_supremum_rec(page), "supremum", 8)) {
- /* In a later format, these fields in a FIL_PAGE_TYPE_INSTANT
- root page could be repurposed for something else. */
+ if (n > REC_MAX_N_FIELDS) {
return true;
}
index->n_core_fields = n;
- ut_ad(!index->is_dummy);
- ut_d(index->is_dummy = true);
- index->n_core_null_bytes = n == index->n_fields
- ? UT_BITS_IN_BYTES(unsigned(index->n_nullable))
- : UT_BITS_IN_BYTES(index->get_n_nullable(n));
- ut_d(index->is_dummy = false);
- return false;
+
+ const rec_t* infimum = page_get_infimum_rec(page);
+ const rec_t* supremum = page_get_supremum_rec(page);
+
+ if (!memcmp(infimum, "infimum", 8)
+ && !memcmp(supremum, "supremum", 8)) {
+ if (n > index->n_fields) {
+ /* All fields, including those for instantly
+ added columns, must be present in the
+ data dictionary. */
+ return true;
+ }
+
+ ut_ad(!index->is_dummy);
+ ut_d(index->is_dummy = true);
+ index->n_core_null_bytes = UT_BITS_IN_BYTES(
+ index->get_n_nullable(n));
+ ut_d(index->is_dummy = false);
+ return false;
+ }
+
+ if (memcmp(infimum, field_ref_zero, 8)
+ || memcmp(supremum, field_ref_zero, 7)) {
+ /* The infimum and supremum records must either contain
+ the original strings, or they must be filled with zero
+ bytes, except for the bytes that we have repurposed. */
+ return true;
+ }
+
+ index->n_core_null_bytes = supremum[7];
+ return index->n_core_null_bytes > 128;
}
/** Optimistically latches the leaf page or pages requested.
@@ -672,8 +809,7 @@ btr_cur_optimistic_latch_leaves(
cursor->left_block = btr_block_get(
page_id_t(cursor->index->table->space_id,
left_page_no),
- page_size_t(cursor->index->table->space
- ->flags),
+ cursor->index->table->space->zip_size(),
mode, cursor->index, mtr);
} else {
cursor->left_block = NULL;
@@ -774,7 +910,7 @@ btr_cur_latch_for_root_leaf(
@param[in] lock_intention lock intention for the tree operation
@param[in] rec record (current node_ptr)
@param[in] rec_size size of the record or max size of node_ptr
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] mtr mtr
@return true if tree modification is needed */
static
@@ -785,7 +921,7 @@ btr_cur_will_modify_tree(
btr_intention_t lock_intention,
const rec_t* rec,
ulint rec_size,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr)
{
ut_ad(!page_is_leaf(page));
@@ -893,9 +1029,8 @@ btr_cur_will_modify_tree(
This is based on the worst case, and we could invoke
page_zip_available() on the block->page.zip. */
/* needs 2 records' space also for worst compress rate. */
- if (page_size.is_compressed()
- && page_zip_empty_size(index->n_fields,
- page_size.physical())
+ if (zip_size
+ && page_zip_empty_size(index->n_fields, zip_size)
<= rec_size * 2 + page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + 2)) {
return(true);
@@ -1311,7 +1446,7 @@ btr_cur_search_to_nth_level_func(
}
# endif /* BTR_CUR_HASH_ADAPT */
#endif /* BTR_CUR_ADAPT */
- my_atomic_addlint(&btr_cur_n_non_sea, 1);
+ btr_cur_n_non_sea++;
/* If the hash search did not succeed, do binary search down the
tree */
@@ -1334,7 +1469,7 @@ btr_cur_search_to_nth_level_func(
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
- && trx_sys.history_size() > BTR_CUR_FINE_HISTORY_LENGTH
+ && trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
x_latch_index:
mtr_x_lock_index(index, mtr);
@@ -1391,7 +1526,7 @@ x_latch_index:
page_cursor = btr_cur_get_page_cur(cursor);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* Start with the root page. */
page_id_t page_id(index->table->space_id, index->page);
@@ -1474,7 +1609,7 @@ search_loop:
retry_page_get:
ut_ad(n_blocks < BTR_MAX_LEVELS);
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, guess,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, guess,
buf_mode, file, line, mtr, &err);
tree_blocks[n_blocks] = block;
@@ -1510,7 +1645,7 @@ retry_page_get:
ut_ad(!dict_index_is_spatial(index));
if (ibuf_insert(IBUF_OP_INSERT, tuple, index,
- page_id, page_size, cursor->thr)) {
+ page_id, zip_size, cursor->thr)) {
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
@@ -1523,7 +1658,7 @@ retry_page_get:
ut_ad(!dict_index_is_spatial(index));
if (ibuf_insert(IBUF_OP_DELETE_MARK, tuple,
- index, page_id, page_size,
+ index, page_id, zip_size,
cursor->thr)) {
cursor->flag = BTR_CUR_DEL_MARK_IBUF;
@@ -1543,7 +1678,7 @@ retry_page_get:
/* The record cannot be purged yet. */
cursor->flag = BTR_CUR_DELETE_REF;
} else if (ibuf_insert(IBUF_OP_DELETE, tuple,
- index, page_id, page_size,
+ index, page_id, zip_size,
cursor->thr)) {
/* The purge was buffered. */
@@ -1589,7 +1724,7 @@ retry_page_get:
= mtr_set_savepoint(mtr);
get_block = buf_page_get_gen(
page_id_t(page_id.space(), left_page_no),
- page_size, rw_latch, NULL, buf_mode,
+ zip_size, rw_latch, NULL, buf_mode,
file, line, mtr, &err);
prev_tree_blocks[prev_n_blocks] = get_block;
prev_n_blocks++;
@@ -1619,7 +1754,7 @@ retry_page_get:
tree_blocks[n_blocks]);
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, NULL,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL,
buf_mode, file, line, mtr, &err);
tree_blocks[n_blocks] = block;
@@ -1717,7 +1852,7 @@ retry_page_get:
if (rw_latch == RW_NO_LATCH) {
latch_leaves = btr_cur_latch_leaves(
- block, page_id, page_size, latch_mode,
+ block, page_id, zip_size, latch_mode,
cursor, mtr);
}
@@ -2081,7 +2216,7 @@ need_opposite_intention:
&& latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
index, page, lock_intention, node_ptr,
- node_ptr_max_size, page_size, mtr)
+ node_ptr_max_size, zip_size, mtr)
&& !rtree_parent_modified) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -2279,12 +2414,12 @@ need_opposite_intention:
if (latch_mode == BTR_CONT_MODIFY_TREE) {
child_block = btr_block_get(
- page_id, page_size, RW_X_LATCH,
+ page_id, zip_size, RW_X_LATCH,
index, mtr);
} else {
ut_ad(latch_mode == BTR_CONT_SEARCH_TREE);
child_block = btr_block_get(
- page_id, page_size, RW_SX_LATCH,
+ page_id, zip_size, RW_SX_LATCH,
index, mtr);
}
@@ -2339,9 +2474,10 @@ need_opposite_intention:
ut_ad(index->is_instant());
/* This may be a search tuple for
btr_pcur_restore_position(). */
- ut_ad(tuple->info_bits == REC_INFO_METADATA
- || tuple->info_bits == REC_INFO_MIN_REC_FLAG);
- } else if (rec_is_metadata(btr_cur_get_rec(cursor), index)) {
+ ut_ad(tuple->is_metadata()
+ || (tuple->is_metadata(tuple->info_bits
+ ^ REC_STATUS_INSTANT)));
+ } else if (rec_is_metadata(btr_cur_get_rec(cursor), *index)) {
/* Only user records belong in the adaptive
hash index. */
} else {
@@ -2468,7 +2604,7 @@ btr_cur_open_at_index_side_func(
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
- && trx_sys.history_size() > BTR_CUR_FINE_HISTORY_LENGTH
+ && trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
mtr_x_lock_index(index, mtr);
} else {
@@ -2501,7 +2637,7 @@ btr_cur_open_at_index_side_func(
cursor->index = index;
page_id_t page_id(index->table->space_id, index->page);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
if (root_leaf_rw_latch == RW_X_LATCH) {
node_ptr_max_size = btr_node_ptr_max_size(index);
@@ -2524,7 +2660,7 @@ btr_cur_open_at_index_side_func(
}
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, NULL,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL,
BUF_GET, file, line, mtr, &err);
ut_ad((block != NULL) == (err == DB_SUCCESS));
tree_blocks[n_blocks] = block;
@@ -2580,12 +2716,12 @@ btr_cur_open_at_index_side_func(
if (height == level) {
if (srv_read_only_mode) {
btr_cur_latch_leaves(
- block, page_id, page_size,
+ block, page_id, zip_size,
latch_mode, cursor, mtr);
} else if (height == 0) {
if (rw_latch == RW_NO_LATCH) {
btr_cur_latch_leaves(
- block, page_id, page_size,
+ block, page_id, zip_size,
latch_mode, cursor, mtr);
}
/* In versions <= 3.23.52 we had
@@ -2716,7 +2852,7 @@ btr_cur_open_at_index_side_func(
if (latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
cursor->index, page, lock_intention, node_ptr,
- node_ptr_max_size, page_size, mtr)) {
+ node_ptr_max_size, zip_size, mtr)) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -2813,7 +2949,7 @@ btr_cur_open_at_rnd_pos_func(
Free blocks and read IO bandwidth should be prior
for them, when the history list is glowing huge. */
if (lock_intention == BTR_INTENTION_DELETE
- && trx_sys.history_size() > BTR_CUR_FINE_HISTORY_LENGTH
+ && trx_sys.rseg_history_len > BTR_CUR_FINE_HISTORY_LENGTH
&& buf_get_n_pending_read_ios()) {
mtr_x_lock_index(index, mtr);
} else {
@@ -2858,7 +2994,7 @@ btr_cur_open_at_rnd_pos_func(
cursor->index = index;
page_id_t page_id(index->table->space_id, index->page);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
dberr_t err = DB_SUCCESS;
if (root_leaf_rw_latch == RW_X_LATCH) {
@@ -2882,7 +3018,7 @@ btr_cur_open_at_rnd_pos_func(
}
tree_savepoints[n_blocks] = mtr_set_savepoint(mtr);
- block = buf_page_get_gen(page_id, page_size, rw_latch, NULL,
+ block = buf_page_get_gen(page_id, zip_size, rw_latch, NULL,
BUF_GET, file, line, mtr, &err);
tree_blocks[n_blocks] = block;
@@ -2935,7 +3071,7 @@ btr_cur_open_at_rnd_pos_func(
if (rw_latch == RW_NO_LATCH
|| srv_read_only_mode) {
btr_cur_latch_leaves(
- block, page_id, page_size,
+ block, page_id, zip_size,
latch_mode, cursor, mtr);
}
@@ -3011,7 +3147,7 @@ btr_cur_open_at_rnd_pos_func(
if (latch_mode == BTR_MODIFY_TREE
&& !btr_cur_will_modify_tree(
cursor->index, page, lock_intention, node_ptr,
- node_ptr_max_size, page_size, mtr)) {
+ node_ptr_max_size, zip_size, mtr)) {
ut_ad(upper_rw_latch == RW_X_LATCH);
ut_ad(n_releases <= n_blocks);
@@ -3187,8 +3323,11 @@ btr_cur_ins_lock_and_undo(
roll_ptr = roll_ptr_t(1) << ROLL_PTR_INSERT_FLAG_POS;
if (!(flags & BTR_KEEP_SYS_FLAG)) {
upd_sys:
- row_upd_index_entry_sys_field(entry, index,
- DATA_ROLL_PTR, roll_ptr);
+ dfield_t* r = dtuple_get_nth_field(
+ entry, index->db_roll_ptr());
+ ut_ad(r->len == DATA_ROLL_PTR_LEN);
+ trx_write_roll_ptr(static_cast<byte*>(r->data),
+ roll_ptr);
}
} else {
err = trx_undo_report_row_operation(thr, index, entry,
@@ -3220,12 +3359,12 @@ btr_cur_prefetch_siblings(
if (left_page_no != FIL_NULL) {
buf_read_page_background(
page_id_t(block->page.id.space(), left_page_no),
- block->page.size, false);
+ block->zip_size(), false);
}
if (right_page_no != FIL_NULL) {
buf_read_page_background(
page_id_t(block->page.id.space(), right_page_no),
- block->page.size, false);
+ block->zip_size(), false);
}
if (left_page_no != FIL_NULL
|| right_page_no != FIL_NULL) {
@@ -3292,23 +3431,28 @@ btr_cur_optimistic_insert(
|| (flags & BTR_CREATE_FLAG));
ut_ad(dtuple_check_typed(entry));
- const page_size_t& page_size = block->page.size;
-
#ifdef UNIV_DEBUG_VALGRIND
- if (page_size.is_compressed()) {
- UNIV_MEM_ASSERT_RW(page, page_size.logical());
- UNIV_MEM_ASSERT_RW(block->page.zip.data, page_size.physical());
+ if (block->page.zip.data) {
+ UNIV_MEM_ASSERT_RW(page, srv_page_size);
+ UNIV_MEM_ASSERT_RW(block->page.zip.data,
+ block->zip_size());
}
#endif /* UNIV_DEBUG_VALGRIND */
leaf = page_is_leaf(page);
+ if (UNIV_UNLIKELY(entry->is_alter_metadata())) {
+ ut_ad(leaf);
+ goto convert_big_rec;
+ }
+
/* Calculate the record size when entry is converted to a record */
rec_size = rec_get_converted_size(index, entry, n_ext);
if (page_zip_rec_needs_ext(rec_size, page_is_comp(page),
- dtuple_get_n_fields(entry), page_size)) {
-
+ dtuple_get_n_fields(entry),
+ block->zip_size())) {
+convert_big_rec:
/* The record is so big that we have to store some fields
externally on separate database pages */
big_rec_vec = dtuple_convert_big_rec(index, 0, entry, &n_ext);
@@ -3321,7 +3465,7 @@ btr_cur_optimistic_insert(
rec_size = rec_get_converted_size(index, entry, n_ext);
}
- if (page_size.is_compressed() && page_zip_is_too_big(index, entry)) {
+ if (block->page.zip.data && page_zip_is_too_big(index, entry)) {
if (big_rec_vec != NULL) {
dtuple_convert_back_big_rec(index, entry, big_rec_vec);
}
@@ -3332,7 +3476,7 @@ btr_cur_optimistic_insert(
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page),
goto fail);
- if (leaf && page_size.is_compressed()
+ if (block->page.zip.data && leaf
&& (page_get_data_size(page) + rec_size
>= dict_index_zip_pad_optimal_page_size(index))) {
/* If compression padding tells us that insertion will
@@ -3375,7 +3519,7 @@ fail_err:
we have to split the page to reserve enough free space for
future updates of records. */
- if (leaf && !page_size.is_compressed() && dict_index_is_clust(index)
+ if (leaf && !block->page.zip.data && dict_index_is_clust(index)
&& page_get_n_recs(page) >= 2
&& dict_index_get_space_reserve() + rec_size > max_size
&& (btr_page_get_split_rec_to_right(cursor, &dummy)
@@ -3438,7 +3582,7 @@ fail_err:
}
if (*rec) {
- } else if (page_size.is_compressed()) {
+ } else if (block->page.zip.data) {
ut_ad(!index->table->is_temporary());
/* Reset the IBUF_BITMAP_FREE bits, because
page_cur_tuple_insert() will have attempted page
@@ -3479,7 +3623,7 @@ fail_err:
} else if (index->disable_ahi) {
# endif
} else if (entry->info_bits & REC_INFO_MIN_REC_FLAG) {
- ut_ad(entry->info_bits == REC_INFO_METADATA);
+ ut_ad(entry->is_metadata());
ut_ad(index->is_instant());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else {
@@ -3514,7 +3658,7 @@ fail_err:
committed mini-transaction, because in crash recovery,
the free bits could momentarily be set too high. */
- if (page_size.is_compressed()) {
+ if (block->page.zip.data) {
/* Update the bits in the same mini-transaction. */
ibuf_update_free_bits_zip(block, mtr);
} else {
@@ -3612,9 +3756,14 @@ btr_cur_pessimistic_insert(
}
if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext),
- dict_table_is_comp(index->table),
+ index->table->not_redundant(),
dtuple_get_n_fields(entry),
- dict_table_page_size(index->table))) {
+ btr_cur_get_block(cursor)->zip_size())
+ || UNIV_UNLIKELY(entry->is_alter_metadata()
+ && !dfield_is_ext(
+ dtuple_get_nth_field(
+ entry,
+ index->first_user_field())))) {
/* The record is so big that we have to store some fields
externally on separate database pages */
@@ -3684,7 +3833,7 @@ btr_cur_pessimistic_insert(
if (index->disable_ahi); else
# endif
if (entry->info_bits & REC_INFO_MIN_REC_FLAG) {
- ut_ad(entry->info_bits == REC_INFO_METADATA);
+ ut_ad(entry->is_metadata());
ut_ad(index->is_instant());
ut_ad(flags & BTR_NO_LOCKING_FLAG);
ut_ad(!(flags & BTR_CREATE_FLAG));
@@ -3769,6 +3918,50 @@ btr_cur_upd_lock_and_undo(
cmpl_info, rec, offsets, roll_ptr));
}
+/** Copy DB_TRX_ID,DB_ROLL_PTR to the redo log.
+@param[in] index clustered index
+@param[in] trx_id_t DB_TRX_ID
+@param[in] roll_ptr DB_ROLL_PTR
+@param[in,out] log_ptr redo log buffer
+@return current end of the redo log buffer */
+static byte*
+btr_cur_log_sys(
+ const dict_index_t* index,
+ trx_id_t trx_id,
+ roll_ptr_t roll_ptr,
+ byte* log_ptr)
+{
+ log_ptr += mach_write_compressed(log_ptr, index->db_trx_id());
+ /* Yes, we are writing DB_ROLL_PTR,DB_TRX_ID in reverse order,
+ after emitting the position of DB_TRX_ID in the index.
+ This is how row_upd_write_sys_vals_to_log()
+ originally worked, and it is part of the redo log format. */
+ trx_write_roll_ptr(log_ptr, roll_ptr);
+ log_ptr += DATA_ROLL_PTR_LEN;
+ log_ptr += mach_u64_write_compressed(log_ptr, trx_id);
+
+ return log_ptr;
+}
+
+/** Write DB_TRX_ID,DB_ROLL_PTR to a clustered index entry.
+@param[in,out] entry clustered index entry
+@param[in] index clustered index
+@param[in] trx_id DB_TRX_ID
+@param[in] roll_ptr DB_ROLL_PTR */
+static void btr_cur_write_sys(
+ dtuple_t* entry,
+ const dict_index_t* index,
+ trx_id_t trx_id,
+ roll_ptr_t roll_ptr)
+{
+ dfield_t* t = dtuple_get_nth_field(entry, index->db_trx_id());
+ ut_ad(t->len == DATA_TRX_ID_LEN);
+ trx_write_trx_id(static_cast<byte*>(t->data), trx_id);
+ dfield_t* r = dtuple_get_nth_field(entry, index->db_roll_ptr());
+ ut_ad(r->len == DATA_ROLL_PTR_LEN);
+ trx_write_roll_ptr(static_cast<byte*>(r->data), roll_ptr);
+}
+
/***********************************************************//**
Writes a redo log record of updating a record in-place. */
void
@@ -3808,8 +4001,7 @@ btr_cur_update_in_place_log(
log_ptr++;
if (dict_index_is_clust(index)) {
- log_ptr = row_upd_write_sys_vals_to_log(
- index, trx_id, roll_ptr, log_ptr, mtr);
+ log_ptr = btr_cur_log_sys(index, trx_id, roll_ptr, log_ptr);
} else {
/* Dummy system fields for a secondary index */
/* TRX_ID Position */
@@ -4162,6 +4354,72 @@ func_exit:
return(err);
}
+/** Trim a metadata record during the rollback of instant ALTER TABLE.
+@param[in] entry metadata tuple
+@param[in] index primary key
+@param[in] update update vector for the rollback */
+ATTRIBUTE_COLD
+static void btr_cur_trim_alter_metadata(dtuple_t* entry,
+ const dict_index_t* index,
+ const upd_t* update)
+{
+ ut_ad(index->is_instant());
+ ut_ad(update->is_alter_metadata());
+ ut_ad(entry->is_alter_metadata());
+
+ ut_ad(update->fields[0].field_no == index->first_user_field());
+ ut_ad(update->fields[0].new_val.ext);
+ ut_ad(update->fields[0].new_val.len == FIELD_REF_SIZE);
+ ut_ad(entry->n_fields - 1 == index->n_fields);
+
+ const byte* ptr = static_cast<const byte*>(
+ update->fields[0].new_val.data);
+ ut_ad(!mach_read_from_4(ptr + BTR_EXTERN_LEN));
+ ut_ad(mach_read_from_4(ptr + BTR_EXTERN_LEN + 4) > 4);
+ ut_ad(mach_read_from_4(ptr + BTR_EXTERN_OFFSET) == FIL_PAGE_DATA);
+ ut_ad(mach_read_from_4(ptr + BTR_EXTERN_SPACE_ID)
+ == index->table->space->id);
+
+ ulint n_fields = update->fields[1].field_no;
+ ut_ad(n_fields <= index->n_fields);
+ if (n_fields != index->n_uniq) {
+ ut_ad(n_fields
+ >= index->n_core_fields);
+ entry->n_fields = n_fields;
+ return;
+ }
+
+ /* This is based on dict_table_t::deserialise_columns()
+ and btr_cur_instant_init_low(). */
+ mtr_t mtr;
+ mtr.start();
+ buf_block_t* block = buf_page_get(
+ page_id_t(index->table->space->id,
+ mach_read_from_4(ptr + BTR_EXTERN_PAGE_NO)),
+ 0, RW_S_LATCH, &mtr);
+ buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
+ ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_TYPE_BLOB);
+ ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA
+ + BTR_BLOB_HDR_NEXT_PAGE_NO])
+ == FIL_NULL);
+ ut_ad(mach_read_from_4(&block->frame[FIL_PAGE_DATA
+ + BTR_BLOB_HDR_PART_LEN])
+ == mach_read_from_4(ptr + BTR_EXTERN_LEN + 4));
+ n_fields = mach_read_from_4(
+ &block->frame[FIL_PAGE_DATA + BTR_BLOB_HDR_SIZE])
+ + index->first_user_field();
+ /* Rollback should not increase the number of fields. */
+ ut_ad(n_fields <= index->n_fields);
+ ut_ad(n_fields + 1 <= entry->n_fields);
+ /* dict_index_t::clear_instant_alter() cannot be invoked while
+ rollback of an instant ALTER TABLE transaction is in progress
+ for an is_alter_metadata() record. */
+ ut_ad(n_fields >= index->n_core_fields);
+
+ mtr.commit();
+ entry->n_fields = n_fields + 1;
+}
+
/** Trim an update tuple due to instant ADD COLUMN, if needed.
For normal records, the trailing instantly added fields that match
the initial default values are omitted.
@@ -4183,13 +4441,12 @@ btr_cur_trim(
const que_thr_t* thr)
{
if (!index->is_instant()) {
- } else if (UNIV_UNLIKELY(update->info_bits == REC_INFO_METADATA)) {
+ } else if (UNIV_UNLIKELY(update->is_metadata())) {
/* We are either updating a metadata record
- (instantly adding columns to a table where instant ADD was
+ (instant ALTER TABLE on a table where instant ALTER was
already executed) or rolling back such an operation. */
ut_ad(!upd_get_nth_field(update, 0)->orig_len);
- ut_ad(upd_get_nth_field(update, 0)->field_no
- > index->n_core_fields);
+ ut_ad(entry->is_metadata());
if (thr->graph->trx->in_rollback) {
/* This rollback can occur either as part of
@@ -4206,6 +4463,13 @@ btr_cur_trim(
first instantly added column logged by
innobase_add_instant_try(). */
ut_ad(update->n_fields > 2);
+ if (update->is_alter_metadata()) {
+ btr_cur_trim_alter_metadata(
+ entry, index, update);
+ return;
+ }
+ ut_ad(!entry->is_alter_metadata());
+
ulint n_fields = upd_get_nth_field(update, 0)
->field_no;
ut_ad(n_fields + 1 >= entry->n_fields);
@@ -4290,9 +4554,7 @@ btr_cur_optimistic_update(
|| trx_is_recv(thr_get_trx(thr)));
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const bool is_metadata = update->info_bits == REC_INFO_METADATA;
-
- if (UNIV_LIKELY(!is_metadata)
+ if (UNIV_LIKELY(!update->is_metadata())
&& !row_upd_changes_field_size_or_external(index, *offsets,
update)) {
@@ -4318,6 +4580,10 @@ any_extern:
return(DB_OVERFLOW);
}
+ if (rec_is_metadata(rec, *index) && index->table->instant) {
+ goto any_extern;
+ }
+
for (i = 0; i < upd_get_n_fields(update); i++) {
if (dfield_is_ext(&upd_get_nth_field(update, i)->new_val)) {
@@ -4360,7 +4626,7 @@ any_extern:
if (page_zip_rec_needs_ext(new_rec_size, page_is_comp(page),
dict_index_get_n_fields(index),
- dict_table_page_size(index->table))) {
+ block->zip_size())) {
goto any_extern;
}
@@ -4374,10 +4640,10 @@ any_extern:
}
/* We limit max record size to 16k even for 64k page size. */
- if (new_rec_size >= COMPRESSED_REC_MAX_DATA_SIZE ||
- (!dict_table_is_comp(index->table)
- && new_rec_size >= REDUNDANT_REC_MAX_DATA_SIZE)) {
- err = DB_OVERFLOW;
+ if (new_rec_size >= COMPRESSED_REC_MAX_DATA_SIZE ||
+ (!dict_table_is_comp(index->table)
+ && new_rec_size >= REDUNDANT_REC_MAX_DATA_SIZE)) {
+ err = DB_OVERFLOW;
goto func_exit;
}
@@ -4450,8 +4716,8 @@ any_extern:
lock_rec_store_on_page_infimum(block, rec);
}
- if (UNIV_UNLIKELY(is_metadata)) {
- ut_ad(new_entry->info_bits == REC_INFO_METADATA);
+ if (UNIV_UNLIKELY(update->is_metadata())) {
+ ut_ad(new_entry->is_metadata());
ut_ad(index->is_instant());
/* This can be innobase_add_instant_try() performing a
subsequent instant ADD COLUMN, or its rollback by
@@ -4466,10 +4732,7 @@ any_extern:
page_cur_move_to_prev(page_cursor);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
- roll_ptr);
- row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
- trx_id);
+ btr_cur_write_sys(new_entry, index, trx_id, roll_ptr);
}
/* There are no externally stored columns in new_entry */
@@ -4477,7 +4740,7 @@ any_extern:
cursor, new_entry, offsets, heap, 0/*n_ext*/, mtr);
ut_a(rec); /* <- We calculated above the insert would fit */
- if (UNIV_UNLIKELY(is_metadata)) {
+ if (UNIV_UNLIKELY(update->is_metadata())) {
/* We must empty the PAGE_FREE list, because if this
was a rollback, the shortened metadata record
would have too many fields, and we would be unable to
@@ -4542,7 +4805,8 @@ btr_cur_pess_upd_restore_supremum(
const page_id_t page_id(block->page.id.space(), prev_page_no);
ut_ad(prev_page_no != FIL_NULL);
- prev_block = buf_page_get_with_no_latch(page_id, block->page.size, mtr);
+ prev_block = buf_page_get_with_no_latch(page_id, block->zip_size(),
+ mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(btr_page_get_next(prev_block->frame) == block->page.id.page_no());
#endif /* UNIV_BTR_DEBUG */
@@ -4666,8 +4930,24 @@ btr_cur_pessimistic_update(
rec = btr_cur_get_rec(cursor);
ut_ad(rec_offs_validate(rec, index, *offsets));
- dtuple_t* new_entry = row_rec_to_index_entry(
- rec, index, *offsets, entry_heap);
+ dtuple_t* new_entry;
+
+ const bool is_metadata = rec_is_metadata(rec, *index);
+
+ if (UNIV_UNLIKELY(is_metadata)) {
+ ut_ad(update->is_metadata());
+ ut_ad(flags & BTR_NO_LOCKING_FLAG);
+ ut_ad(index->is_instant());
+ new_entry = row_metadata_to_tuple(
+ rec, index, *offsets, entry_heap,
+ update->info_bits, !thr_get_trx(thr)->in_rollback);
+ ut_ad(new_entry->n_fields
+ == ulint(index->n_fields)
+ + update->is_alter_metadata());
+ } else {
+ new_entry = row_rec_to_index_entry(rec, index, *offsets,
+ entry_heap);
+ }
/* The page containing the clustered index record
corresponding to new_entry is latched in mtr. If the
@@ -4679,9 +4959,6 @@ btr_cur_pessimistic_update(
entry_heap);
btr_cur_trim(new_entry, index, update, thr);
- const bool is_metadata = new_entry->info_bits
- & REC_INFO_MIN_REC_FLAG;
-
/* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */
@@ -4707,14 +4984,17 @@ btr_cur_pessimistic_update(
index, rec, page_zip, *offsets, update, true, mtr);
}
- ulint n_ext = dtuple_get_n_ext(new_entry);
+ ulint n_ext = index->is_primary() ? dtuple_get_n_ext(new_entry) : 0;
if (page_zip_rec_needs_ext(
- rec_get_converted_size(index, new_entry, n_ext),
- page_is_comp(page),
- dict_index_get_n_fields(index),
- block->page.size)) {
-
+ rec_get_converted_size(index, new_entry, n_ext),
+ page_is_comp(page),
+ dict_index_get_n_fields(index),
+ block->zip_size())
+ || (UNIV_UNLIKELY(update->is_alter_metadata())
+ && !dfield_is_ext(dtuple_get_nth_field(
+ new_entry,
+ index->first_user_field())))) {
big_rec_vec = dtuple_convert_big_rec(index, update, new_entry, &n_ext);
if (UNIV_UNLIKELY(big_rec_vec == NULL)) {
@@ -4763,10 +5043,7 @@ btr_cur_pessimistic_update(
}
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
- roll_ptr);
- row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
- trx_id);
+ btr_cur_write_sys(new_entry, index, trx_id, roll_ptr);
}
if (!page_zip) {
@@ -4775,10 +5052,10 @@ btr_cur_pessimistic_update(
}
if (UNIV_UNLIKELY(is_metadata)) {
- ut_ad(new_entry->info_bits == REC_INFO_METADATA);
+ ut_ad(new_entry->is_metadata());
ut_ad(index->is_instant());
/* This can be innobase_add_instant_try() performing a
- subsequent instant ADD COLUMN, or its rollback by
+ subsequent instant ALTER TABLE, or its rollback by
row_undo_mod_clust_low(). */
ut_ad(flags & BTR_NO_LOCKING_FLAG);
} else {
@@ -4827,7 +5104,8 @@ btr_cur_pessimistic_update(
btr_cur_get_block(cursor), rec, block);
}
- if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))) {
+ if (!rec_get_deleted_flag(rec, rec_offs_comp(*offsets))
+ || rec_is_alter_metadata(rec, *index)) {
/* The new inserted record owns its possible externally
stored fields */
btr_cur_unmark_extern_fields(
@@ -5037,8 +5315,7 @@ btr_cur_del_mark_set_clust_rec_log(
*log_ptr++ = 0;
*log_ptr++ = 1;
- log_ptr = row_upd_write_sys_vals_to_log(
- index, trx_id, roll_ptr, log_ptr, mtr);
+ log_ptr = btr_cur_log_sys(index, trx_id, roll_ptr, log_ptr);
mach_write_to_2(log_ptr, page_offset(rec));
log_ptr += 2;
@@ -5470,42 +5747,41 @@ btr_cur_optimistic_delete_func(
if (UNIV_UNLIKELY(block->page.id.page_no() == cursor->index->page
&& page_get_n_recs(block->frame) == 1
+ (cursor->index->is_instant()
- && !rec_is_metadata(rec, cursor->index)))) {
+ && !rec_is_metadata(rec, *cursor->index)))) {
/* The whole index (and table) becomes logically empty.
Empty the whole page. That is, if we are deleting the
only user record, also delete the metadata record
- if one exists (it exists if and only if is_instant()).
+ if one exists for instant ADD COLUMN (not generic ALTER TABLE).
If we are deleting the metadata record and the
table becomes empty, clean up the whole page. */
dict_index_t* index = cursor->index;
+ const rec_t* first_rec = page_rec_get_next_const(
+ page_get_infimum_rec(block->frame));
ut_ad(!index->is_instant()
- || rec_is_metadata(
- page_rec_get_next_const(
- page_get_infimum_rec(block->frame)),
- index));
- if (UNIV_UNLIKELY(rec_get_info_bits(rec, page_rec_is_comp(rec))
- & REC_INFO_MIN_REC_FLAG)) {
- /* This should be rolling back instant ADD COLUMN.
- If this is a recovered transaction, then
- index->is_instant() will hold until the
- insert into SYS_COLUMNS is rolled back. */
- ut_ad(index->table->supports_instant());
- ut_ad(index->is_primary());
- } else {
- lock_update_delete(block, rec);
- }
- btr_page_empty(block, buf_block_get_page_zip(block),
- index, 0, mtr);
- page_cur_set_after_last(block, btr_cur_get_page_cur(cursor));
-
- if (index->is_primary()) {
- /* Concurrent access is prevented by
- root_block->lock X-latch, so this should be
- safe. */
- index->remove_instant();
+ || rec_is_metadata(first_rec, *index));
+ const bool is_metadata = rec_is_metadata(rec, *index);
+ /* We can remove the metadata when rolling back an
+ instant ALTER TABLE operation, or when deleting the
+ last user record on the page such that only metadata for
+ instant ADD COLUMN (not generic ALTER TABLE) remains. */
+ const bool empty_table = is_metadata
+ || !index->is_instant()
+ || (first_rec != rec
+ && rec_is_add_metadata(first_rec, *index));
+ if (UNIV_LIKELY(empty_table)) {
+ if (UNIV_LIKELY(!is_metadata)) {
+ lock_update_delete(block, rec);
+ }
+ btr_page_empty(block, buf_block_get_page_zip(block),
+ index, 0, mtr);
+ if (index->is_instant()) {
+ /* MDEV-17383: free metadata BLOBs! */
+ index->clear_instant_alter();
+ }
+ page_cur_set_after_last(block,
+ btr_cur_get_page_cur(cursor));
+ return true;
}
-
- return true;
}
offsets = rec_get_offsets(rec, cursor->index, offsets, true,
@@ -5690,10 +5966,10 @@ btr_cur_pessimistic_delete(
bool min_mark_next_rec = false;
if (page_is_leaf(page)) {
- const bool is_metadata = rec_get_info_bits(
- rec, page_rec_is_comp(rec)) & REC_INFO_MIN_REC_FLAG;
+ const bool is_metadata = rec_is_metadata(
+ rec, page_rec_is_comp(rec));
if (UNIV_UNLIKELY(is_metadata)) {
- /* This should be rolling back instant ADD COLUMN.
+ /* This should be rolling back instant ALTER TABLE.
If this is a recovered transaction, then
index->is_instant() will hold until the
insert into SYS_COLUMNS is rolled back. */
@@ -5709,30 +5985,34 @@ btr_cur_pessimistic_delete(
goto discard_page;
}
} else if (page_get_n_recs(page) == 1
- + (index->is_instant()
- && !rec_is_metadata(rec, index))) {
+ + (index->is_instant() && !is_metadata)) {
/* The whole index (and table) becomes logically empty.
Empty the whole page. That is, if we are deleting the
only user record, also delete the metadata record
- if one exists (it exists if and only if is_instant()).
- If we are deleting the metadata record and the
+ if one exists for instant ADD COLUMN
+ (not generic ALTER TABLE).
+ If we are deleting the metadata record
+ (in the rollback of instant ALTER TABLE) and the
table becomes empty, clean up the whole page. */
+
+ const rec_t* first_rec = page_rec_get_next_const(
+ page_get_infimum_rec(page));
ut_ad(!index->is_instant()
- || rec_is_metadata(
- page_rec_get_next_const(
- page_get_infimum_rec(page)),
- index));
- btr_page_empty(block, page_zip, index, 0, mtr);
- page_cur_set_after_last(block,
- btr_cur_get_page_cur(cursor));
- if (index->is_primary()) {
- /* Concurrent access is prevented by
- index->lock and root_block->lock
- X-latch, so this should be safe. */
- index->remove_instant();
+ || rec_is_metadata(first_rec, *index));
+ if (is_metadata || !index->is_instant()
+ || (first_rec != rec
+ && rec_is_add_metadata(first_rec, *index))) {
+ btr_page_empty(block, page_zip, index, 0, mtr);
+ if (index->is_instant()) {
+ /* MDEV-17383: free metadata BLOBs! */
+ index->clear_instant_alter();
+ }
+ page_cur_set_after_last(
+ block,
+ btr_cur_get_page_cur(cursor));
+ ret = TRUE;
+ goto return_after_reservations;
}
- ret = TRUE;
- goto return_after_reservations;
}
if (UNIV_LIKELY(!is_metadata)) {
@@ -5834,7 +6114,7 @@ discard_page:
|| btr_cur_will_modify_tree(
index, page, BTR_INTENTION_DELETE, rec,
btr_node_ptr_max_size(index),
- block->page.size, mtr);
+ block->zip_size(), mtr);
page_cur_delete_rec(btr_cur_get_page_cur(cursor), index,
offsets, mtr);
@@ -6006,7 +6286,7 @@ btr_estimate_n_rows_in_range_on_level(
const fil_space_t* space = index->table->space;
page_id_t page_id(space->id, slot1->page_no);
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
level = slot1->page_level;
@@ -6023,7 +6303,7 @@ btr_estimate_n_rows_in_range_on_level(
attempting to read a page that is no longer part of
the B-tree. We pass BUF_GET_POSSIBLY_FREED in order to
silence a debug assertion about this. */
- block = buf_page_get_gen(page_id, page_size, RW_S_LATCH,
+ block = buf_page_get_gen(page_id, zip_size, RW_S_LATCH,
NULL, BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err);
@@ -7165,7 +7445,7 @@ struct btr_blob_log_check_t {
if (UNIV_UNLIKELY(m_op == BTR_STORE_INSERT_BULK)) {
m_pcur->btr_cur.page_cur.block = btr_block_get(
page_id_t(index->table->space_id, page_no),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_X_LATCH, index, m_mtr);
m_pcur->btr_cur.page_cur.rec
= m_pcur->btr_cur.page_cur.block->frame
@@ -7256,9 +7536,6 @@ btr_store_big_rec_extern_fields(
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
ut_a(dict_index_is_clust(index));
- ut_a(dict_table_page_size(index->table)
- .equals_to(rec_block->page.size));
-
btr_blob_log_check_t redo_log(pcur, btr_mtr, offsets, &rec_block,
&rec, op);
page_zip = buf_block_get_page_zip(rec_block);
@@ -7302,15 +7579,13 @@ btr_store_big_rec_extern_fields(
}
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
- const page_size_t page_size(dict_table_page_size(index->table));
-
/* Space available in compressed page to carry blob data */
- const ulint payload_size_zip = page_size.physical()
+ const ulint payload_size_zip = rec_block->physical_size()
- FIL_PAGE_DATA;
/* Space available in uncompressed page to carry blob data */
- const ulint payload_size = page_size.physical()
- - FIL_PAGE_DATA - BTR_BLOB_HDR_SIZE - FIL_PAGE_DATA_END;
+ const ulint payload_size = payload_size_zip
+ - (BTR_BLOB_HDR_SIZE + FIL_PAGE_DATA_END);
/* We have to create a file segment to the tablespace
for each field and put the pointer to the field in rec */
@@ -7366,7 +7641,7 @@ btr_store_big_rec_extern_fields(
mtr.set_flush_observer(btr_mtr->get_flush_observer());
buf_page_get(rec_block->page.id,
- rec_block->page.size, RW_X_LATCH, &mtr);
+ rec_block->zip_size(), RW_X_LATCH, &mtr);
if (prev_page_no == FIL_NULL) {
hint_page_no = 1 + rec_page_no;
@@ -7414,7 +7689,7 @@ btr_store_big_rec_extern_fields(
prev_block = buf_page_get(
page_id_t(space_id, prev_page_no),
- rec_block->page.size,
+ rec_block->zip_size(),
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(prev_block,
@@ -7470,22 +7745,25 @@ btr_store_big_rec_extern_fields(
ut_a(err == Z_STREAM_END
|| c_stream.avail_out == 0);
- /* Write the "next BLOB page" pointer */
- mlog_write_ulint(page + FIL_PAGE_NEXT,
- FIL_NULL, MLOG_4BYTES, &mtr);
- /* Initialize the unused "prev page" pointer */
- mlog_write_ulint(page + FIL_PAGE_PREV,
- FIL_NULL, MLOG_4BYTES, &mtr);
-
- /* Zero out the unused part of the page. */
- memset(page + page_zip_get_size(page_zip)
- - c_stream.avail_out,
- 0, c_stream.avail_out);
+ compile_time_assert(FIL_PAGE_NEXT
+ == FIL_PAGE_PREV + 4);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mlog_memset(block, FIL_PAGE_PREV, 8, 0xff,
+ &mtr);
mlog_log_string(page
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
page_zip_get_size(page_zip)
- - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ - c_stream.avail_out,
&mtr);
+ /* Zero out the unused part of the page. */
+ if (c_stream.avail_out) {
+ mlog_memset(block,
+ page_zip_get_size(page_zip)
+ - c_stream.avail_out,
+ c_stream.avail_out,
+ 0, &mtr);
+ }
/* Copy the page to compressed storage,
because it will be flushed to disk
from there. */
@@ -7746,10 +8024,9 @@ btr_free_externally_stored_field(
ut_ad(space_id == index->table->space->id);
ut_ad(space_id == index->table->space_id);
- const page_size_t ext_page_size(dict_table_page_size(index->table));
- const page_size_t& rec_page_size(rec == NULL
- ? univ_page_size
- : ext_page_size);
+ const ulint ext_zip_size = index->table->space->zip_size();
+ const ulint rec_zip_size = rec ? ext_zip_size : 0;
+
if (rec == NULL) {
/* This is a call from row_purge_upd_exist_or_extern(). */
ut_ad(!page_zip);
@@ -7776,7 +8053,7 @@ btr_free_externally_stored_field(
#ifdef UNIV_DEBUG
rec_block =
#endif /* UNIV_DEBUG */
- buf_page_get(page_id, rec_page_size, RW_X_LATCH, &mtr);
+ buf_page_get(page_id, rec_zip_size, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(rec_block, SYNC_NO_ORDER_CHECK);
page_no = mach_read_from_4(field_ref + BTR_EXTERN_PAGE_NO);
@@ -7802,13 +8079,13 @@ btr_free_externally_stored_field(
}
ext_block = buf_page_get(
- page_id_t(space_id, page_no), ext_page_size,
+ page_id_t(space_id, page_no), ext_zip_size,
RW_X_LATCH, &mtr);
buf_block_dbg_add_level(ext_block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(ext_block);
- if (ext_page_size.is_compressed()) {
+ if (ext_zip_size) {
/* Note that page_zip will be NULL
in row_purge_upd_exist_or_extern(). */
switch (fil_page_get_type(page)) {
@@ -7977,7 +8254,7 @@ btr_copy_blob_prefix(
mtr_start(&mtr);
block = buf_page_get(page_id_t(space_id, page_no),
- univ_page_size, RW_S_LATCH, &mtr);
+ 0, RW_S_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE);
page = buf_block_get_frame(block);
@@ -8015,7 +8292,7 @@ by a lock or a page latch.
@param[out] buf the externally stored part of the field,
or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size compressed BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size
@param[in] space_id space id of the BLOB pages
@param[in] offset offset on the first BLOB page
@return number of bytes written to buf */
@@ -8024,7 +8301,7 @@ ulint
btr_copy_zblob_prefix(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
ulint space_id,
ulint page_no,
ulint offset)
@@ -8044,7 +8321,8 @@ btr_copy_zblob_prefix(
heap = mem_heap_create(40000);
page_zip_set_alloc(&d_stream, heap);
- ut_ad(page_size.is_compressed());
+ ut_ad(zip_size);
+ ut_ad(ut_is_2pow(zip_size));
ut_ad(space_id);
err = inflateInit(&d_stream);
@@ -8059,7 +8337,7 @@ btr_copy_zblob_prefix(
is being held on the clustered index record, or,
in row_merge_copy_blobs(), by an exclusive table lock. */
bpage = buf_page_get_zip(page_id_t(space_id, page_no),
- page_size);
+ zip_size);
if (UNIV_UNLIKELY(!bpage)) {
ib::error() << "Cannot load compressed BLOB "
@@ -8091,8 +8369,7 @@ btr_copy_zblob_prefix(
}
d_stream.next_in = bpage->zip.data + offset;
- d_stream.avail_in = static_cast<uInt>(page_size.physical()
- - offset);
+ d_stream.avail_in = uInt(zip_size - offset);
err = inflate(&d_stream, Z_NO_FLUSH);
switch (err) {
@@ -8162,7 +8439,7 @@ by a lock or a page latch.
@param[out] buf the externally stored part of the
field, or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] space_id space id of the first BLOB page
@param[in] page_no page number of the first BLOB page
@param[in] offset offset on the first BLOB page
@@ -8172,7 +8449,7 @@ ulint
btr_copy_externally_stored_field_prefix_low(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
ulint space_id,
ulint page_no,
ulint offset)
@@ -8181,11 +8458,10 @@ btr_copy_externally_stored_field_prefix_low(
return(0);
}
- if (page_size.is_compressed()) {
- return(btr_copy_zblob_prefix(buf, len, page_size,
+ if (zip_size) {
+ return(btr_copy_zblob_prefix(buf, len, zip_size,
space_id, page_no, offset));
} else {
- ut_ad(page_size.equals_to(univ_page_size));
return(btr_copy_blob_prefix(buf, len, space_id,
page_no, offset));
}
@@ -8195,7 +8471,7 @@ btr_copy_externally_stored_field_prefix_low(
The clustered index record must be protected by a lock or a page latch.
@param[out] buf the field, or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
@@ -8206,7 +8482,7 @@ ulint
btr_copy_externally_stored_field_prefix(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte* data,
ulint local_len)
{
@@ -8245,7 +8521,7 @@ btr_copy_externally_stored_field_prefix(
return(local_len
+ btr_copy_externally_stored_field_prefix_low(buf + local_len,
len - local_len,
- page_size,
+ zip_size,
space_id, page_no,
offset));
}
@@ -8256,7 +8532,7 @@ The clustered index record must be protected by a lock or a page latch.
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] local_len length of data
@param[in,out] heap mem heap
@return the whole field copied to heap */
@@ -8264,7 +8540,7 @@ byte*
btr_copy_externally_stored_field(
ulint* len,
const byte* data,
- const page_size_t& page_size,
+ ulint zip_size,
ulint local_len,
mem_heap_t* heap)
{
@@ -8295,7 +8571,7 @@ btr_copy_externally_stored_field(
*len = local_len
+ btr_copy_externally_stored_field_prefix_low(buf + local_len,
extern_len,
- page_size,
+ zip_size,
space_id,
page_no, offset);
@@ -8306,7 +8582,7 @@ btr_copy_externally_stored_field(
@param[in] rec record in a clustered index; must be
protected by a lock or a page latch
@param[in] offset array returned by rec_get_offsets()
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] no field number
@param[out] len length of the field
@param[in,out] heap mem heap
@@ -8315,7 +8591,7 @@ byte*
btr_rec_copy_externally_stored_field(
const rec_t* rec,
const offset_t* offsets,
- const page_size_t& page_size,
+ ulint zip_size,
ulint no,
ulint* len,
mem_heap_t* heap)
@@ -8349,5 +8625,5 @@ btr_rec_copy_externally_stored_field(
}
return(btr_copy_externally_stored_field(len, data,
- page_size, local_len, heap));
+ zip_size, local_len, heap));
}
diff --git a/storage/innobase/btr/btr0defragment.cc b/storage/innobase/btr/btr0defragment.cc
index dd8a2546691..1929d339ebf 100644
--- a/storage/innobase/btr/btr0defragment.cc
+++ b/storage/innobase/btr/btr0defragment.cc
@@ -62,14 +62,14 @@ UNIV_INTERN mysql_pfs_key_t btr_defragment_mutex_key;
/* Number of compression failures caused by defragmentation since server
start. */
-ulint btr_defragment_compression_failures = 0;
+Atomic_counter<ulint> btr_defragment_compression_failures;
/* Number of btr_defragment_n_pages calls that altered page but didn't
manage to release any page. */
-ulint btr_defragment_failures = 0;
+Atomic_counter<ulint> btr_defragment_failures;
/* Total number of btr_defragment_n_pages calls that altered page.
The difference between btr_defragment_count and btr_defragment_failures shows
the amount of effort wasted. */
-ulint btr_defragment_count = 0;
+Atomic_counter<ulint> btr_defragment_count;
/******************************************************************//**
Constructor for btr_defragment_item_t. */
@@ -165,7 +165,7 @@ btr_defragment_add_index(
// Load index rood page.
buf_block_t* block = btr_block_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_NO_LATCH, index, &mtr);
page_t* page = NULL;
@@ -375,7 +375,7 @@ btr_defragment_merge_pages(
dict_index_t* index, /*!< in: index tree */
buf_block_t* from_block, /*!< in: origin of merge */
buf_block_t* to_block, /*!< in: destination of merge */
- const page_size_t page_size, /*!< in: page size of the block */
+ ulint zip_size, /*!< in: ROW_FORMAT=COMPRESSED size */
ulint reserved_space, /*!< in: space reserved for future
insert to avoid immediate page split */
ulint* max_data_size, /*!< in/out: max data size to
@@ -403,7 +403,7 @@ btr_defragment_merge_pages(
// Estimate how many records can be moved from the from_page to
// the to_page.
- if (page_size.is_compressed()) {
+ if (zip_size) {
ulint page_diff = srv_page_size - *max_data_size;
max_ins_size_to_use = (max_ins_size_to_use > page_diff)
? max_ins_size_to_use - page_diff : 0;
@@ -447,8 +447,7 @@ btr_defragment_merge_pages(
// n_recs_to_move number of records to to_page. We try to reduce
// the targeted data size on the to_page by
// BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE and try again.
- my_atomic_addlint(
- &btr_defragment_compression_failures, 1);
+ btr_defragment_compression_failures++;
max_ins_size_to_use =
move_size > BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE
? move_size - BTR_DEFRAGMENT_PAGE_REDUCTION_STEP_SIZE
@@ -472,7 +471,7 @@ btr_defragment_merge_pages(
// Set ibuf free bits if necessary.
if (!dict_index_is_clust(index)
&& page_is_leaf(to_page)) {
- if (page_size.is_compressed()) {
+ if (zip_size) {
ibuf_reset_free_bits(to_block);
} else {
ibuf_update_free_bits_if_full(
@@ -490,7 +489,7 @@ btr_defragment_merge_pages(
btr_search_drop_page_hash_index(from_block);
btr_level_list_remove(
index->table->space_id,
- page_size, from_page, index, mtr);
+ zip_size, from_page, index, mtr);
btr_page_get_father(index, from_block, mtr, &parent);
btr_cur_node_ptr_delete(&parent, mtr);
/* btr_blob_dbg_remove(from_page, index,
@@ -577,7 +576,7 @@ btr_defragment_n_pages(
}
first_page = buf_block_get_frame(block);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* 1. Load the pages and calculate the total data size. */
blocks[0] = block;
@@ -593,7 +592,7 @@ btr_defragment_n_pages(
}
blocks[i] = btr_block_get(page_id_t(index->table->space_id,
- page_no), page_size,
+ page_no), zip_size,
RW_X_LATCH, index, mtr);
}
@@ -619,7 +618,7 @@ btr_defragment_n_pages(
optimal_page_size = page_get_free_space_of_empty(
page_is_comp(first_page));
// For compressed pages, we take compression failures into account.
- if (page_size.is_compressed()) {
+ if (zip_size) {
ulint size = 0;
uint i = 0;
// We estimate the optimal data size of the index use samples of
@@ -662,7 +661,7 @@ btr_defragment_n_pages(
// Start from the second page.
for (uint i = 1; i < n_pages; i ++) {
buf_block_t* new_block = btr_defragment_merge_pages(
- index, blocks[i], current_block, page_size,
+ index, blocks[i], current_block, zip_size,
reserved_space, &max_data_size, heap, mtr);
if (new_block != current_block) {
n_defragmented ++;
@@ -671,11 +670,9 @@ btr_defragment_n_pages(
}
mem_heap_free(heap);
n_defragmented ++;
- my_atomic_addlint(
- &btr_defragment_count, 1);
+ btr_defragment_count++;
if (n_pages == n_defragmented) {
- my_atomic_addlint(
- &btr_defragment_failures, 1);
+ btr_defragment_failures++;
} else {
index->stat_defrag_n_pages_freed += (n_pages - n_defragmented);
}
diff --git a/storage/innobase/btr/btr0pcur.cc b/storage/innobase/btr/btr0pcur.cc
index 46549c13c3d..d227d128471 100644
--- a/storage/innobase/btr/btr0pcur.cc
+++ b/storage/innobase/btr/btr0pcur.cc
@@ -150,17 +150,26 @@ before_first:
rec = page_rec_get_prev(rec);
ut_ad(!page_rec_is_infimum(rec));
- ut_ad(!rec_is_metadata(rec, index));
+ if (UNIV_UNLIKELY(rec_is_metadata(rec, *index))) {
+ ut_ad(index->table->instant);
+ ut_ad(page_get_n_recs(block->frame) == 1);
+ ut_ad(page_is_leaf(block->frame));
+ ut_ad(page_get_page_no(block->frame) == index->page);
+ cursor->rel_pos = BTR_PCUR_AFTER_LAST_IN_TREE;
+ return;
+ }
cursor->rel_pos = BTR_PCUR_AFTER;
} else if (page_rec_is_infimum_low(offs)) {
rec = page_rec_get_next(rec);
- if (rec_is_metadata(rec, index)) {
+ if (rec_is_metadata(rec, *index)) {
ut_ad(!page_has_prev(block->frame));
+ ut_d(const rec_t* p = rec);
rec = page_rec_get_next(rec);
if (page_rec_is_supremum(rec)) {
- ut_ad(page_has_next(block->frame));
+ ut_ad(page_has_next(block->frame)
+ || rec_is_alter_metadata(p, *index));
goto before_first;
}
}
@@ -170,10 +179,25 @@ before_first:
cursor->rel_pos = BTR_PCUR_ON;
}
- cursor->old_rec = dict_index_copy_rec_order_prefix(
- index, rec, &cursor->old_n_fields,
- &cursor->old_rec_buf, &cursor->buf_size);
+ if (index->is_ibuf()) {
+ ut_ad(!index->table->not_redundant());
+ cursor->old_n_fields = rec_get_n_fields_old(rec);
+ } else if (page_rec_is_leaf(rec)) {
+ cursor->old_n_fields = dict_index_get_n_unique_in_tree(index);
+ } else if (index->is_spatial()) {
+ ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index)
+ == DICT_INDEX_SPATIAL_NODEPTR_SIZE);
+ /* For R-tree, we have to compare
+ the child page numbers as well. */
+ cursor->old_n_fields = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1;
+ } else {
+ cursor->old_n_fields = dict_index_get_n_unique_in_tree(index);
+ }
+ cursor->old_rec = rec_copy_prefix_to_buf(rec, index,
+ cursor->old_n_fields,
+ &cursor->old_rec_buf,
+ &cursor->buf_size);
cursor->block_when_stored = block;
/* Function try to check if block is S/X latch. */
@@ -457,7 +481,7 @@ btr_pcur_move_to_next_page(
next_block = btr_block_get(
page_id_t(block->page.id.space(), next_page_no),
- block->page.size, mode,
+ block->zip_size(), mode,
btr_pcur_get_btr_cur(cursor)->index, mtr);
if (UNIV_UNLIKELY(!next_block)) {
diff --git a/storage/innobase/btr/btr0scrub.cc b/storage/innobase/btr/btr0scrub.cc
index b0d1c91e5d8..448c0d9ff91 100644
--- a/storage/innobase/btr/btr0scrub.cc
+++ b/storage/innobase/btr/btr0scrub.cc
@@ -1,5 +1,5 @@
// Copyright (c) 2014, Google Inc.
-// Copyright (c) 2017, MariaDB Corporation.
+// Copyright (c) 2017, 2019, MariaDB Corporation.
/**************************************************//**
@file btr/btr0scrub.cc
@@ -119,13 +119,13 @@ btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table,
time_t last = start;
/* FIXME: this is not the proper way of doing things. The
- dict_sys->mutex should not be held by any thread for longer
+ dict_sys.mutex should not be held by any thread for longer
than a few microseconds. It must not be held during I/O,
for example. So, what is the purpose for this busy-waiting?
This function should be rewritten as part of MDEV-8139:
Fix scrubbing tests. */
- while (mutex_enter_nowait(&(dict_sys->mutex))) {
+ while (mutex_enter_nowait(&dict_sys.mutex)) {
/* if we lock to close a table, we wait forever
* if we don't lock to close a table, we check if space
* is closing, and then instead give up
@@ -157,7 +157,7 @@ btr_scrub_lock_dict_func(ulint space_id, bool lock_to_close_table,
}
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
return true;
}
@@ -204,10 +204,10 @@ btr_scrub_table_close_for_thread(
/* If tablespace is not marked as stopping perform
the actual close. */
if (!space->is_stopping()) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
/* perform the actual closing */
btr_scrub_table_close(scrub_data->current_table);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
space->release();
}
@@ -431,10 +431,10 @@ btr_pessimistic_scrub(
}
/* read block variables */
- const ulint page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
+ const uint32_t page_no = mach_read_from_4(page + FIL_PAGE_OFFSET);
const uint32_t left_page_no = btr_page_get_prev(page);
const uint32_t right_page_no = btr_page_get_next(page);
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/**
* When splitting page, we need X-latches on left/right brothers
@@ -449,16 +449,16 @@ btr_pessimistic_scrub(
*/
mtr->release_block_at_savepoint(scrub_data->savepoint, block);
- buf_block_t* get_block __attribute__((unused)) = btr_block_get(
+ btr_block_get(
page_id_t(index->table->space_id, left_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
/**
* Refetch block and re-initialize page
*/
block = btr_block_get(
page_id_t(index->table->space_id, page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
page = buf_block_get_frame(block);
@@ -470,9 +470,9 @@ btr_pessimistic_scrub(
}
if (right_page_no != FIL_NULL) {
- buf_block_t* get_block __attribute__((unused))= btr_block_get(
+ btr_block_get(
page_id_t(index->table->space_id, right_page_no),
- page_size, RW_X_LATCH, index, mtr);
+ zip_size, RW_X_LATCH, index, mtr);
}
/* arguments to btr_page_split_and_insert */
@@ -837,13 +837,15 @@ btr_scrub_start_space(
ulint space, /*!< in: space */
btr_scrub_t* scrub_data) /*!< in/out: scrub data */
{
- bool found;
scrub_data->space = space;
scrub_data->current_table = NULL;
scrub_data->current_index = NULL;
- const page_size_t page_size = fil_space_get_page_size(space, &found);
-
- scrub_data->compressed = page_size.is_compressed();
+ if (fil_space_t* s = fil_space_acquire_silent(space)) {
+ scrub_data->compressed = s->zip_size();
+ s->release();
+ } else {
+ scrub_data->compressed = 0;
+ }
scrub_data->scrubbing = check_scrub_setting(scrub_data);
return scrub_data->scrubbing;
}
diff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index ee1eaaac8ea..32f85832e6c 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -342,7 +342,7 @@ btr_search_disable_ref_count(
{
dict_index_t* index;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
for (index = dict_table_get_first_index(table);
index != NULL;
@@ -352,21 +352,21 @@ btr_search_disable_ref_count(
}
/** Disable the adaptive hash search system and empty the index.
-@param[in] need_mutex need to acquire dict_sys->mutex */
+@param[in] need_mutex need to acquire dict_sys.mutex */
void btr_search_disable(bool need_mutex)
{
dict_table_t* table;
if (need_mutex) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
btr_search_x_lock_all();
if (!btr_search_enabled) {
if (need_mutex) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
btr_search_x_unlock_all();
@@ -377,20 +377,20 @@ void btr_search_disable(bool need_mutex)
/* Clear the index->search_info->ref_count of every index in
the data dictionary cache. */
- for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
+ for (table = UT_LIST_GET_FIRST(dict_sys.table_LRU); table;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
btr_search_disable_ref_count(table);
}
- for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU); table;
+ for (table = UT_LIST_GET_FIRST(dict_sys.table_non_LRU); table;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
btr_search_disable_ref_count(table);
}
if (need_mutex) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
/* Set all block->index = NULL. */
@@ -1107,7 +1107,7 @@ retry:
ut_ad(page_is_leaf(block->frame));
/* We must not dereference index here, because it could be freed
- if (index->table->n_ref_count == 0 && !mutex_own(&dict_sys->mutex)).
+ if (index->table->n_ref_count == 0 && !mutex_own(&dict_sys.mutex)).
Determine the ahi_slot based on the block contents. */
const index_id_t index_id
@@ -1184,7 +1184,7 @@ retry:
rec = page_get_infimum_rec(page);
rec = page_rec_get_next_low(rec, page_is_comp(page));
- if (rec_is_metadata(rec, index)) {
+ if (rec_is_metadata(rec, *index)) {
rec = page_rec_get_next_low(rec, page_is_comp(page));
}
@@ -1281,7 +1281,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id)
are possibly holding, we cannot s-latch the page, but must
(recursively) x-latch it, even though we are only reading. */
- block = buf_page_get_gen(page_id, univ_page_size, RW_X_LATCH, NULL,
+ block = buf_page_get_gen(page_id, 0, RW_X_LATCH, NULL,
BUF_PEEK_IF_IN_POOL, __FILE__, __LINE__,
&mtr, &err);
@@ -1299,7 +1299,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id)
be open, or we should be in the process of
dropping the table (preventing eviction). */
ut_ad(index->table->get_ref_count() > 0
- || mutex_own(&dict_sys->mutex));
+ || mutex_own(&dict_sys.mutex));
btr_search_drop_page_hash_index(block);
}
}
@@ -1392,7 +1392,7 @@ btr_search_build_page_hash_index(
rec = page_rec_get_next_const(page_get_infimum_rec(page));
- if (rec_is_metadata(rec, index)) {
+ if (rec_is_metadata(rec, *index)) {
rec = page_rec_get_next_const(rec);
if (!--n_recs) return;
}
@@ -1856,7 +1856,7 @@ btr_search_update_hash_on_insert(btr_cur_t* cursor, rw_lock_t* ahi_latch)
n_bytes, index->id);
}
- if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, index)) {
+ if (!page_rec_is_infimum(rec) && !rec_is_metadata(rec, *index)) {
offsets = rec_get_offsets(
rec, index, offsets, true,
btr_search_get_n_fields(n_fields, n_bytes), &heap);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index cff6dcb50a6..d261465066e 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -33,14 +33,11 @@ Created 11/5/1995 Heikki Tuuri
#include "mtr0types.h"
#include "mach0data.h"
-#include "page0size.h"
#include "buf0buf.h"
+#include "buf0checksum.h"
+#include "ut0crc32.h"
#include <string.h>
-#ifdef UNIV_NONINL
-#include "buf0buf.ic"
-#endif
-
#ifndef UNIV_INNOCHECKSUM
#include "mem0mem.h"
#include "btr0btr.h"
@@ -61,19 +58,14 @@ Created 11/5/1995 Heikki Tuuri
#include "log0recv.h"
#include "srv0mon.h"
#include "log0crypt.h"
+#include "fil0pagecompress.h"
+#include "fsp0pagecompress.h"
#endif /* !UNIV_INNOCHECKSUM */
#include "page0zip.h"
#include "sync0sync.h"
#include "buf0dump.h"
-#include <new>
#include <map>
#include <sstream>
-#ifndef UNIV_INNOCHECKSUM
-#include "fil0pagecompress.h"
-#include "fsp0pagecompress.h"
-#endif
-#include "ut0byte.h"
-#include <new>
#ifdef UNIV_LINUX
#include <stdlib.h>
@@ -133,6 +125,17 @@ struct set_numa_interleave_t
#include "snappy-c.h"
#endif
+#ifndef UNIV_INNOCHECKSUM
+buf_pool_t::io_buf_t::~io_buf_t()
+{
+ for (buf_tmp_buffer_t* s = slots, *e = slots + n_slots; s != e; s++) {
+ aligned_free(s->crypt_buf);
+ aligned_free(s->comp_buf);
+ }
+ ut_free(slots);
+}
+#endif /* !UNIV_INNOCHECKSUM */
+
/*
IMPLEMENTATION OF THE BUFFER POOL
=================================
@@ -405,16 +408,9 @@ on the io_type */
@return reserved buffer slot */
static buf_tmp_buffer_t* buf_pool_reserve_tmp_slot(buf_pool_t* buf_pool)
{
- for (ulint i = 0; i < buf_pool->tmp_arr->n_slots; i++) {
- buf_tmp_buffer_t* slot = &buf_pool->tmp_arr->slots[i];
- if (slot->acquire()) {
- return slot;
- }
- }
-
- /* We assume that free slot is found */
- ut_error;
- return NULL;
+ buf_tmp_buffer_t* slot = buf_pool->io_buf.reserve();
+ ut_a(slot);
+ return slot;
}
/** Reserve a buffer for encryption, decryption or decompression.
@@ -468,7 +464,7 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame)
}
/* read space & lsn */
- uint header_len = FIL_PAGE_DATA;
+ uint header_len = FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
/* Copy FIL page header, it is not encrypted */
memcpy(tmp_frame, src_frame, header_len);
@@ -477,7 +473,7 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame)
const byte* src = src_frame + header_len;
byte* dst = tmp_frame + header_len;
uint srclen = uint(srv_page_size)
- - header_len - FIL_PAGE_DATA_END;
+ - (header_len + FIL_PAGE_FCRC32_CHECKSUM);
ulint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
if (!log_tmp_block_decrypt(src, srclen, dst,
@@ -485,9 +481,9 @@ static bool buf_tmp_page_decrypt(byte* tmp_frame, byte* src_frame)
return false;
}
- memcpy(tmp_frame + srv_page_size - FIL_PAGE_DATA_END,
- src_frame + srv_page_size - FIL_PAGE_DATA_END,
- FIL_PAGE_DATA_END);
+ memcpy(tmp_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM,
+ src_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM,
+ FIL_PAGE_FCRC32_CHECKSUM);
memcpy(src_frame, tmp_frame, srv_page_size);
srv_stats.pages_decrypted.inc();
@@ -507,7 +503,8 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space)
byte* dst_frame = bpage->zip.data ? bpage->zip.data :
((buf_block_t*) bpage)->frame;
- bool page_compressed = fil_page_is_compressed(dst_frame);
+ bool page_compressed = space->is_compressed()
+ && buf_page_is_compressed(dst_frame, space->flags);
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
if (bpage->id.page_no() == 0) {
@@ -536,39 +533,45 @@ static bool buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space)
also for pages first compressed and then encrypted. */
buf_tmp_buffer_t* slot;
+ uint key_version = buf_page_get_key_version(dst_frame, space->flags);
- if (page_compressed) {
+ if (page_compressed && !key_version) {
/* the page we read is unencrypted */
/* Find free slot from temporary memory array */
decompress:
+ if (space->full_crc32()
+ && buf_page_is_corrupted(true, dst_frame, space->flags)) {
+ return false;
+ }
+
slot = buf_pool_reserve_tmp_slot(buf_pool);
/* For decompression, use crypt_buf. */
buf_tmp_reserve_crypt_buf(slot);
+
decompress_with_slot:
- ut_d(fil_page_type_validate(dst_frame));
+ ut_d(fil_page_type_validate(space, dst_frame));
- bpage->write_size = fil_page_decompress(slot->crypt_buf,
- dst_frame);
+ bpage->write_size = fil_page_decompress(
+ slot->crypt_buf, dst_frame, space->flags);
slot->release();
- ut_ad(!bpage->write_size || fil_page_type_validate(dst_frame));
+ ut_ad(!bpage->write_size
+ || fil_page_type_validate(space, dst_frame));
+
ut_ad(space->pending_io());
+
return bpage->write_size != 0;
}
- if (space->crypt_data
- && mach_read_from_4(FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- + dst_frame)) {
+ if (key_version && space->crypt_data) {
/* Verify encryption checksum before we even try to
decrypt. */
- if (!fil_space_verify_crypt_checksum(dst_frame, bpage->size)) {
+ if (!buf_page_verify_crypt_checksum(dst_frame, space->flags)) {
decrypt_failed:
ib::error() << "Encrypted page " << bpage->id
<< " in file " << space->chain.start->name
<< " looks corrupted; key_version="
- << mach_read_from_4(
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- + dst_frame);
+ << key_version;
return false;
}
@@ -576,7 +579,7 @@ decrypt_failed:
slot = buf_pool_reserve_tmp_slot(buf_pool);
buf_tmp_reserve_crypt_buf(slot);
- ut_d(fil_page_type_validate(dst_frame));
+ ut_d(fil_page_type_validate(space, dst_frame));
/* decrypt using crypt_buf to dst_frame */
if (!fil_space_decrypt(space, slot->crypt_buf, dst_frame)) {
@@ -584,9 +587,10 @@ decrypt_failed:
goto decrypt_failed;
}
- ut_d(fil_page_type_validate(dst_frame));
+ ut_d(fil_page_type_validate(space, dst_frame));
- if (fil_page_is_compressed_encrypted(dst_frame)) {
+ if ((space->full_crc32() && page_compressed)
+ || fil_page_is_compressed_encrypted(dst_frame)) {
goto decompress_with_slot;
}
@@ -794,11 +798,7 @@ buf_page_is_checksum_valid_crc32(
return false;
}
- return checksum_field1 == crc32
-#ifdef INNODB_BUG_ENDIAN_CRC32
- || checksum_field1 == buf_calc_page_crc32(read_buf, true)
-#endif
- ;
+ return checksum_field1 == crc32;
}
/** Checks if the page is in innodb checksum format.
@@ -927,28 +927,44 @@ buf_page_is_checksum_valid_none(
&& checksum_field1 == BUF_NO_CHECKSUM_MAGIC);
}
-#ifdef INNODB_BUG_ENDIAN_CRC32
-/** Validate the CRC-32C checksum of a page.
-@param[in] page buffer page (srv_page_size bytes)
-@param[in] checksum CRC-32C checksum stored on page
-@return computed checksum */
-static uint32_t buf_page_check_crc32(const byte* page, uint32_t checksum)
+/** Checks whether the lsn present in the page is lesser than the
+peek current lsn.
+@param[in] check_lsn lsn to check
+@param[in] read_buf page. */
+static void buf_page_check_lsn(bool check_lsn, const byte* read_buf)
{
- uint32_t crc32 = buf_calc_page_crc32(page);
+#ifndef UNIV_INNOCHECKSUM
+ if (check_lsn && recv_lsn_checks_on) {
+ lsn_t current_lsn;
+ const lsn_t page_lsn
+ = mach_read_from_8(read_buf + FIL_PAGE_LSN);
- if (checksum != crc32) {
- crc32 = buf_calc_page_crc32(page, true);
- }
+ /* Since we are going to reset the page LSN during the import
+ phase it makes no sense to spam the log with error messages. */
+
+ if (log_peek_lsn(&current_lsn) && current_lsn < page_lsn) {
+
+ const ulint space_id = mach_read_from_4(
+ read_buf + FIL_PAGE_SPACE_ID);
+ const ulint page_no = mach_read_from_4(
+ read_buf + FIL_PAGE_OFFSET);
+
+ ib::error() << "Page " << page_id_t(space_id, page_no)
+ << " log sequence number " << page_lsn
+ << " is in the future! Current system"
+ << " log sequence number "
+ << current_lsn << ".";
- return crc32;
+ ib::error() << "Your database may be corrupt or"
+ " you may have copied the InnoDB"
+ " tablespace but not the InnoDB"
+ " log files. "
+ << FORCE_RECOVERY_MSG;
+
+ }
+ }
+#endif /* !UNIV_INNOCHECKSUM */
}
-#else /* INNODB_BUG_ENDIAN_CRC32 */
-/** Validate the CRC-32C checksum of a page.
-@param[in] page buffer page (srv_page_size bytes)
-@param[in] checksum CRC-32C checksum stored on page
-@return computed checksum */
-# define buf_page_check_crc32(page, checksum) buf_calc_page_crc32(page)
-#endif /* INNODB_BUG_ENDIAN_CRC32 */
/** Check if a buffer is all zeroes.
@@ -963,29 +979,64 @@ bool buf_is_zeroes(span<const byte> buf)
/** Check if a page is corrupt.
@param[in] check_lsn whether the LSN should be checked
@param[in] read_buf database page
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] space tablespace
@return whether the page is corrupted */
bool
buf_page_is_corrupted(
bool check_lsn,
const byte* read_buf,
- const page_size_t& page_size,
-#ifndef UNIV_INNOCHECKSUM
- const fil_space_t* space)
-#else
- const void* space)
-#endif
+ ulint fsp_flags)
{
- ut_ad(page_size.logical() == srv_page_size);
#ifndef UNIV_INNOCHECKSUM
DBUG_EXECUTE_IF("buf_page_import_corrupt_failure", return(true); );
#endif
+ if (fil_space_t::full_crc32(fsp_flags)) {
+ bool compressed = false, corrupted = false;
+ const uint size = buf_page_full_crc32_size(
+ read_buf, &compressed, &corrupted);
+ if (corrupted) {
+ return true;
+ }
+ const byte* end = read_buf + (size - FIL_PAGE_FCRC32_CHECKSUM);
+ uint crc32 = mach_read_from_4(end);
+
+ if (!crc32 && size == srv_page_size
+ && buf_is_zeroes(span<const byte>(read_buf, size))) {
+ return false;
+ }
+
+ DBUG_EXECUTE_IF(
+ "page_intermittent_checksum_mismatch", {
+ static int page_counter;
+ if (page_counter++ == 2) {
+ crc32++;
+ }
+ });
+
+ if (crc32 != ut_crc32(read_buf,
+ size - FIL_PAGE_FCRC32_CHECKSUM)) {
+ return true;
+ }
+ if (!compressed
+ && !mach_read_from_4(FIL_PAGE_FCRC32_KEY_VERSION
+ + read_buf)
+ && memcmp(read_buf + (FIL_PAGE_LSN + 4),
+ end - (FIL_PAGE_FCRC32_END_LSN
+ - FIL_PAGE_FCRC32_CHECKSUM), 4)) {
+ return true;
+ }
+
+ buf_page_check_lsn(check_lsn, read_buf);
+ return false;
+ }
+
size_t checksum_field1 = 0;
size_t checksum_field2 = 0;
uint32_t crc32 = 0;
bool crc32_inited = false;
-
+ bool crc32_chksum = false;
+ const ulint zip_size = fil_space_t::zip_size(fsp_flags);
ulint page_type = mach_read_from_2(read_buf + FIL_PAGE_TYPE);
/* We can trust page type if page compression is set on tablespace
@@ -1000,16 +1051,15 @@ buf_page_is_corrupted(
if ((page_type == FIL_PAGE_PAGE_COMPRESSED ||
page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED)
#ifndef UNIV_INNOCHECKSUM
- && space && FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags)
+ && FSP_FLAGS_HAS_PAGE_COMPRESSION(fsp_flags)
#endif
) {
return(false);
}
- if (!page_size.is_compressed()
- && memcmp(read_buf + FIL_PAGE_LSN + 4,
- read_buf + page_size.logical()
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
+ if (!zip_size && memcmp(read_buf + FIL_PAGE_LSN + 4,
+ read_buf + srv_page_size
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4, 4)) {
/* Stored log sequence numbers at the start and the end
of page do not match */
@@ -1017,37 +1067,7 @@ buf_page_is_corrupted(
return(true);
}
-#ifndef UNIV_INNOCHECKSUM
- if (check_lsn && recv_lsn_checks_on) {
- lsn_t current_lsn;
- const lsn_t page_lsn
- = mach_read_from_8(read_buf + FIL_PAGE_LSN);
-
- /* Since we are going to reset the page LSN during the import
- phase it makes no sense to spam the log with error messages. */
-
- if (log_peek_lsn(&current_lsn) && current_lsn < page_lsn) {
-
- const ulint space_id = mach_read_from_4(
- read_buf + FIL_PAGE_SPACE_ID);
- const ulint page_no = mach_read_from_4(
- read_buf + FIL_PAGE_OFFSET);
-
- ib::error() << "Page " << page_id_t(space_id, page_no)
- << " log sequence number " << page_lsn
- << " is in the future! Current system"
- << " log sequence number "
- << current_lsn << ".";
-
- ib::error() << "Your database may be corrupt or"
- " you may have copied the InnoDB"
- " tablespace but not the InnoDB"
- " log files. "
- << FORCE_RECOVERY_MSG;
-
- }
- }
-#endif /* !UNIV_INNOCHECKSUM */
+ buf_page_check_lsn(check_lsn, read_buf);
/* Check whether the checksum fields have correct values */
@@ -1058,23 +1078,26 @@ buf_page_is_corrupted(
return(false);
}
- if (page_size.is_compressed()) {
- return(!page_zip_verify_checksum(read_buf,
- page_size.physical()));
+ if (zip_size) {
+ return !page_zip_verify_checksum(read_buf, zip_size);
}
checksum_field1 = mach_read_from_4(
read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
checksum_field2 = mach_read_from_4(
- read_buf + page_size.logical() - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ read_buf + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM);
compile_time_assert(!(FIL_PAGE_LSN % 8));
/* A page filled with NUL bytes is considered not corrupted.
- The FIL_PAGE_FILE_FLUSH_LSN field may be written nonzero for
- the first page of the system tablespace.
- Ignore it for the system tablespace. */
+ Before MariaDB Server 10.1.25 (MDEV-12113) or 10.2.2 (or MySQL 5.7),
+ the FIL_PAGE_FILE_FLUSH_LSN field may have been written nonzero
+ for the first page of each file of the system tablespace.
+ We want to ignore it for the system tablespace, but because
+ we do not know the expected tablespace here, we ignore the
+ field for all data files, except for
+ innodb_checksum_algorithm=full_crc32 which we handled above. */
if (!checksum_field1 && !checksum_field2) {
/* Checksum fields can have valid value as zero.
If the page is not empty then do the checksum
@@ -1082,8 +1105,7 @@ buf_page_is_corrupted(
bool all_zeroes = true;
for (size_t i = 0; i < srv_page_size; i++) {
#ifndef UNIV_INNOCHECKSUM
- if (i == FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- && (!space || !space->id)) {
+ if (i == FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) {
i += 8;
}
#endif
@@ -1099,6 +1121,7 @@ buf_page_is_corrupted(
}
switch (curr_algo) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
return !buf_page_is_checksum_valid_crc32(
read_buf, checksum_field1, checksum_field2);
@@ -1108,6 +1131,7 @@ buf_page_is_corrupted(
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
return !buf_page_is_checksum_valid_none(
read_buf, checksum_field1, checksum_field2);
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_CRC32:
case SRV_CHECKSUM_ALGORITHM_INNODB:
if (buf_page_is_checksum_valid_none(read_buf,
@@ -1132,6 +1156,9 @@ buf_page_is_corrupted(
return false;
}
+ crc32_chksum = curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32
+ || curr_algo == SRV_CHECKSUM_ALGORITHM_FULL_CRC32;
+
/* Very old versions of InnoDB only stored 8 byte lsn to the
start and the end of the page. */
@@ -1142,19 +1169,18 @@ buf_page_is_corrupted(
!= mach_read_from_4(read_buf + FIL_PAGE_LSN)
&& checksum_field2 != BUF_NO_CHECKSUM_MAGIC) {
- if (curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32) {
+ if (crc32_chksum) {
+ crc32 = buf_calc_page_crc32(read_buf);
+ crc32_inited = true;
+
DBUG_EXECUTE_IF(
"page_intermittent_checksum_mismatch", {
static int page_counter;
if (page_counter++ == 2) {
- checksum_field2++;
+ crc32++;
}
});
- crc32 = buf_page_check_crc32(read_buf,
- checksum_field2);
- crc32_inited = true;
-
if (checksum_field2 != crc32
&& checksum_field2
!= buf_calc_page_old_checksum(read_buf)) {
@@ -1166,8 +1192,7 @@ buf_page_is_corrupted(
if (checksum_field2
!= buf_calc_page_old_checksum(read_buf)) {
- crc32 = buf_page_check_crc32(
- read_buf, checksum_field2);
+ crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
if (checksum_field2 != crc32) {
@@ -1179,10 +1204,10 @@ buf_page_is_corrupted(
if (checksum_field1 == 0
|| checksum_field1 == BUF_NO_CHECKSUM_MAGIC) {
- } else if (curr_algo == SRV_CHECKSUM_ALGORITHM_CRC32) {
+ } else if (crc32_chksum) {
+
if (!crc32_inited) {
- crc32 = buf_page_check_crc32(
- read_buf, checksum_field2);
+ crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
}
@@ -1198,8 +1223,7 @@ buf_page_is_corrupted(
!= buf_calc_page_new_checksum(read_buf)) {
if (!crc32_inited) {
- crc32 = buf_page_check_crc32(
- read_buf, checksum_field2);
+ crc32 = buf_calc_page_crc32(read_buf);
crc32_inited = true;
}
@@ -1252,10 +1276,10 @@ buf_madvise_do_dump()
srv_log_buffer_size * 2,
MADV_DODUMP);
}
- /* mirrors recv_sys_init() */
- if (recv_sys->buf)
+ /* mirrors recv_sys_t::create() */
+ if (recv_sys.buf)
{
- ret+= madvise(recv_sys->buf, recv_sys->len, MADV_DODUMP);
+ ret+= madvise(recv_sys.buf, recv_sys.len, MADV_DODUMP);
}
buf_pool_mutex_enter_all();
@@ -1279,22 +1303,21 @@ buf_madvise_do_dump()
/** Dump a page to stderr.
@param[in] read_buf database page
-@param[in] page_size page size */
-UNIV_INTERN
-void
-buf_page_print(const byte* read_buf, const page_size_t& page_size)
+@param[in] zip_size compressed page size, or 0 */
+void buf_page_print(const byte* read_buf, ulint zip_size)
{
dict_index_t* index;
#ifndef UNIV_DEBUG
+ const ulint size = zip_size ? zip_size : srv_page_size;
ib::info() << "Page dump in ascii and hex ("
- << page_size.physical() << " bytes):";
+ << size << " bytes):";
- ut_print_buf(stderr, read_buf, page_size.physical());
+ ut_print_buf(stderr, read_buf, size);
fputs("\nInnoDB: End of page dump\n", stderr);
#endif
- if (page_size.is_compressed()) {
+ if (zip_size) {
/* Print compressed page. */
ib::info() << "Compressed page type ("
<< fil_page_get_type(read_buf)
@@ -1306,27 +1329,21 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
SRV_CHECKSUM_ALGORITHM_CRC32)
<< " "
<< page_zip_calc_checksum(
- read_buf, page_size.physical(),
+ read_buf, zip_size,
SRV_CHECKSUM_ALGORITHM_CRC32)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- << "/"
- << page_zip_calc_checksum(
- read_buf, page_size.physical(),
- SRV_CHECKSUM_ALGORITHM_CRC32, true)
-#endif
<< ", "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_INNODB)
<< " "
<< page_zip_calc_checksum(
- read_buf, page_size.physical(),
+ read_buf, zip_size,
SRV_CHECKSUM_ALGORITHM_INNODB)
<< ", "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_NONE)
<< " "
<< page_zip_calc_checksum(
- read_buf, page_size.physical(),
+ read_buf, zip_size,
SRV_CHECKSUM_ALGORITHM_NONE)
<< "; page LSN "
<< mach_read_from_8(read_buf + FIL_PAGE_LSN)
@@ -1339,10 +1356,6 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
} else {
const uint32_t crc32 = buf_calc_page_crc32(read_buf);
-#ifdef INNODB_BUG_ENDIAN_CRC32
- const uint32_t crc32_legacy = buf_calc_page_crc32(read_buf,
- true);
-#endif /* INNODB_BUG_ENDIAN_CRC32 */
ulint page_type = fil_page_get_type(read_buf);
ib::info() << "Uncompressed page, stored checksum in field1 "
@@ -1352,9 +1365,6 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_CRC32) << " "
<< crc32
-#ifdef INNODB_BUG_ENDIAN_CRC32
- << "/" << crc32_legacy
-#endif
<< ", "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_INNODB) << " "
@@ -1366,15 +1376,12 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
SRV_CHECKSUM_ALGORITHM_NONE) << " "
<< BUF_NO_CHECKSUM_MAGIC
<< ", stored checksum in field2 "
- << mach_read_from_4(read_buf + page_size.logical()
+ << mach_read_from_4(read_buf + srv_page_size
- FIL_PAGE_END_LSN_OLD_CHKSUM)
<< ", calculated checksums for field2: "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_CRC32) << " "
<< crc32
-#ifdef INNODB_BUG_ENDIAN_CRC32
- << "/" << crc32_legacy
-#endif
<< ", "
<< buf_checksum_algorithm_name(
SRV_CHECKSUM_ALGORITHM_INNODB) << " "
@@ -1388,7 +1395,7 @@ buf_page_print(const byte* read_buf, const page_size_t& page_size)
<< " "
<< mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
<< ", low 4 bytes of LSN at page end "
- << mach_read_from_4(read_buf + page_size.logical()
+ << mach_read_from_4(read_buf + srv_page_size
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)
<< ", page number (if stored to page already) "
<< mach_read_from_4(read_buf + FIL_PAGE_OFFSET)
@@ -1502,7 +1509,7 @@ pfs_register_buffer_block(
: NULL;
# ifdef UNIV_DEBUG
- rwlock = &block->debug_latch;
+ rwlock = block->debug_latch;
ut_a(!rwlock->pfs_psi);
rwlock->pfs_psi = (PSI_server)
? PSI_server->init_rwlock(buf_block_debug_latch_key,
@@ -1563,6 +1570,7 @@ buf_block_init(
page_zip_des_init(&block->page.zip);
mutex_create(LATCH_ID_BUF_BLOCK_MUTEX, &block->mutex);
+ ut_d(block->debug_latch = (rw_lock_t *) ut_malloc_nokey(sizeof(rw_lock_t)));
#if defined PFS_SKIP_BUFFER_MUTEX_RWLOCK || defined PFS_GROUP_BUFFER_SYNC
/* If PFS_SKIP_BUFFER_MUTEX_RWLOCK is defined, skip registration
@@ -1574,7 +1582,7 @@ buf_block_init(
rw_lock_create(PFS_NOT_INSTRUMENTED, &block->lock, SYNC_LEVEL_VARYING);
- ut_d(rw_lock_create(PFS_NOT_INSTRUMENTED, &block->debug_latch,
+ ut_d(rw_lock_create(PFS_NOT_INSTRUMENTED, block->debug_latch,
SYNC_LEVEL_VARYING));
#else /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
@@ -1582,7 +1590,7 @@ buf_block_init(
rw_lock_create(buf_block_lock_key, &block->lock, SYNC_LEVEL_VARYING);
ut_d(rw_lock_create(buf_block_debug_latch_key,
- &block->debug_latch, SYNC_LEVEL_VARYING));
+ block->debug_latch, SYNC_LEVEL_VARYING));
#endif /* PFS_SKIP_BUFFER_MUTEX_RWLOCK || PFS_GROUP_BUFFER_SYNC */
@@ -1609,11 +1617,6 @@ buf_chunk_init(
/* Round down to a multiple of page size,
although it already should be. */
mem_size = ut_2pow_round<ulint>(mem_size, srv_page_size);
- /* Reserve space for the block descriptors. */
- mem_size += ut_2pow_round<ulint>((mem_size >> srv_page_size_shift)
- * (sizeof *block)
- + (srv_page_size - 1),
- srv_page_size);
DBUG_EXECUTE_IF("ib_buf_chunk_init_fails", return(NULL););
@@ -1792,7 +1795,7 @@ buf_chunk_not_freed(
== block->page.newest_modification);
ut_ad(block->page.oldest_modification == 0
|| block->page.oldest_modification
- == recv_sys->recovered_lsn
+ == recv_sys.recovered_lsn
|| srv_force_recovery
== SRV_FORCE_NO_LOG_REDO);
ut_ad(block->page.buf_fix_count == 0);
@@ -1841,6 +1844,16 @@ buf_pool_set_sizes(void)
buf_pool_mutex_exit_all();
}
+/** Free the synchronization objects of a buffer pool block descriptor
+@param[in,out] block buffer pool block descriptor */
+static void buf_block_free_mutexes(buf_block_t* block)
+{
+ mutex_free(&block->mutex);
+ rw_lock_free(&block->lock);
+ ut_d(rw_lock_free(block->debug_latch));
+ ut_d(ut_free(block->debug_latch));
+}
+
/********************************************************************//**
Initialize a buffer pool instance.
@return DB_SUCCESS if all goes well. */
@@ -1904,11 +1917,7 @@ buf_pool_init_instance(
buf_block_t* block = chunk->blocks;
for (i = chunk->size; i--; block++) {
- mutex_free(&block->mutex);
- rw_lock_free(&block->lock);
-
- ut_d(rw_lock_free(
- &block->debug_latch));
+ buf_block_free_mutexes(block);
}
buf_pool->allocator.deallocate_large_dodump(
@@ -1928,8 +1937,7 @@ buf_pool_init_instance(
ut_min(BUF_READ_AHEAD_PAGES,
ut_2_power_up(buf_pool->curr_size /
BUF_READ_AHEAD_PORTION));
- buf_pool->curr_pool_size = buf_pool->curr_size
- << srv_page_size_shift;
+ buf_pool->curr_pool_size = buf_pool_size;
buf_pool->old_size = buf_pool->curr_size;
buf_pool->n_chunks_new = buf_pool->n_chunks;
@@ -1986,12 +1994,9 @@ buf_pool_init_instance(
new(&buf_pool->single_scan_itr) LRUItr(buf_pool, &buf_pool->mutex);
/* Initialize the temporal memory array and slots */
- buf_pool->tmp_arr = (buf_tmp_array_t *)ut_malloc_nokey(sizeof(buf_tmp_array_t));
- memset(buf_pool->tmp_arr, 0, sizeof(buf_tmp_array_t));
- ulint n_slots = (srv_n_read_io_threads + srv_n_write_io_threads) * (8 * OS_AIO_N_PENDING_IOS_PER_THREAD);
- buf_pool->tmp_arr->n_slots = n_slots;
- buf_pool->tmp_arr->slots = (buf_tmp_buffer_t*)ut_malloc_nokey(sizeof(buf_tmp_buffer_t) * n_slots);
- memset(buf_pool->tmp_arr->slots, 0, (sizeof(buf_tmp_buffer_t) * n_slots));
+ new(&buf_pool->io_buf) buf_pool_t::io_buf_t(
+ (srv_n_read_io_threads + srv_n_write_io_threads)
+ * (8 * OS_AIO_N_PENDING_IOS_PER_THREAD));
buf_pool_mutex_exit(buf_pool);
@@ -2053,10 +2058,7 @@ buf_pool_free_instance(
buf_block_t* block = chunk->blocks;
for (ulint i = chunk->size; i--; block++) {
- mutex_free(&block->mutex);
- rw_lock_free(&block->lock);
-
- ut_d(rw_lock_free(&block->debug_latch));
+ buf_block_free_mutexes(block);
}
buf_pool->allocator.deallocate_large_dodump(
@@ -2072,26 +2074,7 @@ buf_pool_free_instance(
hash_table_free(buf_pool->page_hash);
hash_table_free(buf_pool->zip_hash);
- /* Free all used temporary slots */
- if (buf_pool->tmp_arr) {
- for(ulint i = 0; i < buf_pool->tmp_arr->n_slots; i++) {
- buf_tmp_buffer_t* slot = &(buf_pool->tmp_arr->slots[i]);
- if (slot && slot->crypt_buf) {
- aligned_free(slot->crypt_buf);
- slot->crypt_buf = NULL;
- }
-
- if (slot && slot->comp_buf) {
- aligned_free(slot->comp_buf);
- slot->comp_buf = NULL;
- }
- }
-
- ut_free(buf_pool->tmp_arr->slots);
- ut_free(buf_pool->tmp_arr);
- buf_pool->tmp_arr = NULL;
- }
-
+ buf_pool->io_buf.~io_buf_t();
buf_pool->allocator.~ut_allocator();
}
@@ -2719,12 +2702,12 @@ buf_pool_resize()
ut_ad(UT_LIST_GET_LEN(buf_pool->withdraw) == 0);
ut_ad(buf_pool->flush_rbt == NULL);
- buf_pool->curr_size = new_instance_size;
-
buf_pool->n_chunks_new =
(new_instance_size << srv_page_size_shift)
/ srv_buf_pool_chunk_unit;
+ buf_pool->curr_size = buf_pool->n_chunks_new * buf_pool->chunks->size;
+
buf_pool_mutex_exit(buf_pool);
}
#ifdef BTR_CUR_HASH_ADAPT
@@ -2914,11 +2897,7 @@ withdraw_retry:
for (ulint j = chunk->size;
j--; block++) {
- mutex_free(&block->mutex);
- rw_lock_free(&block->lock);
-
- ut_d(rw_lock_free(
- &block->debug_latch));
+ buf_block_free_mutexes(block);
}
buf_pool->allocator.deallocate_large_dodump(
@@ -3060,7 +3039,7 @@ calc_buf_pool_size:
ut_2_power_up(buf_pool->curr_size /
BUF_READ_AHEAD_PORTION));
buf_pool->curr_pool_size
- = buf_pool->curr_size << srv_page_size_shift;
+ = buf_pool->n_chunks * srv_buf_pool_chunk_unit;
curr_size += buf_pool->curr_pool_size;
buf_pool->old_size = buf_pool->curr_size;
}
@@ -3120,8 +3099,7 @@ calc_buf_pool_size:
btr_search_sys_resize(
buf_pool_get_curr_size() / sizeof(void*) / 64);
- /* normalize dict_sys */
- dict_resize();
+ dict_sys.resize();
ib::info() << "Resized hash tables at lock_sys,"
#ifdef BTR_CUR_HASH_ADAPT
@@ -3493,7 +3471,7 @@ page_found:
}
/* Add to an existing watch. */
- buf_block_fix(bpage);
+ bpage->fix();
return(NULL);
}
@@ -3633,7 +3611,7 @@ void buf_pool_watch_unset(const page_id_t page_id)
increments buf_fix_count. */
bpage = buf_page_hash_get_low(buf_pool, page_id);
- if (buf_block_unfix(bpage) == 0
+ if (bpage->unfix() == 0
&& buf_pool_watch_is_sentinel(buf_pool, bpage)) {
buf_pool_watch_remove(buf_pool, bpage);
}
@@ -3800,12 +3778,9 @@ be implemented at a higher level. In other words, all possible
accesses to a given page through this function must be protected by
the same set of mutexes or latches.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size
@return pointer to the block */
-buf_page_t*
-buf_page_get_zip(
- const page_id_t page_id,
- const page_size_t& page_size)
+buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size)
{
buf_page_t* bpage;
BPageMutex* block_mutex;
@@ -3814,6 +3789,8 @@ buf_page_get_zip(
ibool must_read;
buf_pool_t* buf_pool = buf_pool_get(page_id);
+ ut_ad(zip_size);
+ ut_ad(ut_is_2pow(zip_size));
buf_pool->stat.n_page_gets++;
for (;;) {
@@ -3831,7 +3808,7 @@ lookup:
/* Page not in buf_pool: needs to be read from file */
ut_ad(!hash_lock);
- dberr_t err = buf_read_page(page_id, page_size);
+ dberr_t err = buf_read_page(page_id, zip_size);
if (err != DB_SUCCESS) {
ib::error() << "Reading compressed page " << page_id
@@ -3859,7 +3836,7 @@ err_exit:
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
- buf_block_fix(bpage);
+ bpage->fix();
block_mutex = &buf_pool->zip_mutex;
goto got_block;
case BUF_BLOCK_FILE_PAGE:
@@ -3970,7 +3947,7 @@ buf_zip_decompress(
&& (!crypt_data->is_default_encryption()
|| srv_encrypt_tables);
- ut_ad(block->page.size.is_compressed());
+ ut_ad(block->zip_size());
ut_a(block->page.id.space() != 0);
if (UNIV_UNLIKELY(check && !page_zip_verify_checksum(frame, size))) {
@@ -3982,12 +3959,6 @@ buf_zip_decompress(
<< ", crc32: "
<< page_zip_calc_checksum(
frame, size, SRV_CHECKSUM_ALGORITHM_CRC32)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- << "/"
- << page_zip_calc_checksum(
- frame, size, SRV_CHECKSUM_ALGORITHM_CRC32,
- true)
-#endif
<< " innodb: "
<< page_zip_calc_checksum(
frame, size, SRV_CHECKSUM_ALGORITHM_INNODB)
@@ -3995,7 +3966,6 @@ buf_zip_decompress(
<< page_zip_calc_checksum(
frame, size, SRV_CHECKSUM_ALGORITHM_NONE)
<< " (algorithm: " << srv_checksum_algorithm << ")";
-
goto err_exit;
}
@@ -4022,7 +3992,7 @@ buf_zip_decompress(
case FIL_PAGE_TYPE_ZBLOB:
case FIL_PAGE_TYPE_ZBLOB2:
/* Copy to uncompressed storage. */
- memcpy(block->frame, frame, block->page.size.physical());
+ memcpy(block->frame, frame, block->zip_size());
if (space) {
space->release_for_io();
}
@@ -4276,6 +4246,7 @@ static buf_block_t* buf_page_mtr_lock(buf_block_t *block,
/** This is the low level function used to get access to a database page.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
@@ -4283,11 +4254,12 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
@param[in] file file name
@param[in] line line where called
@param[in] mtr mini-transaction
+@param[out] err DB_SUCCESS or error code
@return pointer to the block or NULL */
buf_block_t*
buf_page_get_low(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint rw_latch,
buf_block_t* guess,
ulint mode,
@@ -4335,16 +4307,15 @@ buf_page_get_low(
case BUF_GET:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_GET_POSSIBLY_FREED:
- bool found;
- const page_size_t& space_page_size
- = fil_space_get_page_size(page_id.space(), &found);
- ut_ad(found);
- ut_ad(page_size.equals_to(space_page_size));
+ fil_space_t* s = fil_space_acquire_for_io(page_id.space());
+ ut_ad(s);
+ ut_ad(s->zip_size() == zip_size);
+ s->release_for_io();
}
#endif /* UNIV_DEBUG */
ut_ad(!mtr || !ibuf_inside(mtr)
- || ibuf_page_low(page_id, page_size, FALSE, file, line, NULL));
+ || ibuf_page_low(page_id, zip_size, FALSE, file, line, NULL));
buf_pool->stat.n_page_gets++;
hash_lock = buf_page_hash_lock_get(buf_pool, page_id);
@@ -4417,10 +4388,10 @@ loop:
= buf_page_get_mutex(
&fix_block->page);
mutex_enter(fix_mutex);
- buf_block_fix(fix_block);
+ fix_block->fix();
mutex_exit(fix_mutex);
} else {
- buf_block_fix(fix_block);
+ fix_block->fix();
}
/* Now safe to release page_hash mutex */
@@ -4453,10 +4424,10 @@ loop:
corrupted, or if an encrypted page with a valid
checksum cannot be decypted. */
- dberr_t local_err = buf_read_page(page_id, page_size);
+ dberr_t local_err = buf_read_page(page_id, zip_size);
if (local_err == DB_SUCCESS) {
- buf_read_ahead_random(page_id, page_size,
+ buf_read_ahead_random(page_id, zip_size,
ibuf_inside(mtr));
retries = 0;
@@ -4532,18 +4503,20 @@ loop:
BPageMutex* fix_mutex = buf_page_get_mutex(
&fix_block->page);
mutex_enter(fix_mutex);
- buf_block_fix(fix_block);
+ fix_block->fix();
mutex_exit(fix_mutex);
} else {
- buf_block_fix(fix_block);
+ fix_block->fix();
}
/* Now safe to release page_hash mutex */
rw_lock_s_unlock(hash_lock);
got_block:
-
switch (mode) {
+ default:
+ ut_ad(block->zip_size() == zip_size);
+ break;
case BUF_GET_IF_IN_POOL:
case BUF_PEEK_IF_IN_POOL:
case BUF_EVICT_IF_IN_POOL:
@@ -4558,7 +4531,7 @@ got_block:
/* The page is being read to buffer pool,
but we cannot wait around for the read to
complete. */
- buf_block_unfix(fix_block);
+ fix_block->unfix();
return(NULL);
}
@@ -4574,7 +4547,7 @@ got_block:
/* This suggests that the page is being flushed.
Avoid returning reference to this page.
Instead wait for the flush action to complete. */
- buf_block_unfix(fix_block);
+ fix_block->unfix();
os_thread_sleep(WAIT_FOR_WRITE);
goto loop;
}
@@ -4583,7 +4556,7 @@ got_block:
evict_from_pool:
ut_ad(!fix_block->page.oldest_modification);
buf_pool_mutex_enter(buf_pool);
- buf_block_unfix(fix_block);
+ fix_block->unfix();
if (!buf_LRU_free_page(&fix_block->page, true)) {
ut_ad(0);
@@ -4601,7 +4574,7 @@ evict_from_pool:
adaptive hash index. There cannot be an
adaptive hash index for a compressed-only
page, so do not bother decompressing the page. */
- buf_block_unfix(fix_block);
+ fix_block->unfix();
return(NULL);
}
@@ -4615,7 +4588,7 @@ evict_from_pool:
/* This condition often occurs when the buffer
is not buffer-fixed, but I/O-fixed by
buf_page_init_for_read(). */
- buf_block_unfix(fix_block);
+ fix_block->unfix();
/* The block is buffer-fixed or I/O-fixed.
Try again later. */
@@ -4644,7 +4617,7 @@ evict_from_pool:
/* Buffer-fixing prevents the page_hash from changing. */
ut_ad(bpage == buf_page_hash_get_low(buf_pool, page_id));
- buf_block_unfix(fix_block);
+ fix_block->unfix();
buf_page_mutex_enter(block);
mutex_enter(&buf_pool->zip_mutex);
@@ -4736,7 +4709,7 @@ evict_from_pool:
buf_page_mutex_exit(fix_block);
--buf_pool->n_pend_unzip;
- buf_block_unfix(fix_block);
+ fix_block->unfix();
buf_pool_mutex_exit(buf_pool);
rw_lock_x_unlock(&fix_block->lock);
@@ -4749,7 +4722,7 @@ evict_from_pool:
if (!access_time && !recv_no_ibuf_operations) {
ibuf_merge_or_delete_for_page(
- block, page_id, &page_size, TRUE);
+ block, block->page.id, zip_size, true);
}
buf_pool_mutex_enter(buf_pool);
@@ -4795,7 +4768,7 @@ evict_from_pool:
buf_pool_mutex_enter(buf_pool);
- buf_block_unfix(fix_block);
+ fix_block->unfix();
/* Now we are only holding the buf_pool->mutex,
not block->mutex or hash_lock. Blocks cannot be
@@ -4854,7 +4827,7 @@ evict_from_pool:
buf_page_mutex_exit(fix_block);
- buf_block_fix(fix_block);
+ fix_block->fix();
/* Failed to evict the page; change it directly */
@@ -4872,7 +4845,7 @@ evict_from_pool:
if (!fsp_is_system_temporary(page_id.space())) {
ibool ret;
ret = rw_lock_s_lock_nowait(
- &fix_block->debug_latch, file, line);
+ fix_block->debug_latch, file, line);
ut_a(ret);
}
#endif /* UNIV_DEBUG */
@@ -4915,12 +4888,11 @@ evict_from_pool:
buf_wait_for_read(fix_block);
if (fix_block->page.id != page_id) {
-
- buf_block_unfix(fix_block);
+ fix_block->unfix();
#ifdef UNIV_DEBUG
if (!fsp_is_system_temporary(page_id.space())) {
- rw_lock_s_unlock(&fix_block->debug_latch);
+ rw_lock_s_unlock(fix_block->debug_latch);
}
#endif /* UNIV_DEBUG */
@@ -4937,7 +4909,7 @@ evict_from_pool:
/* In the case of a first access, try to apply linear
read-ahead */
- buf_read_ahead_linear(page_id, page_size, ibuf_inside(mtr));
+ buf_read_ahead_linear(page_id, zip_size, ibuf_inside(mtr));
}
ut_ad(!rw_lock_own_flagged(hash_lock,
@@ -4949,6 +4921,7 @@ evict_from_pool:
/** This is the general function used to get access to a database page.
It does page initialization and applies the buffered redo logs.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
@@ -4961,7 +4934,7 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
buf_block_t*
buf_page_get_gen(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint rw_latch,
buf_block_t* guess,
ulint mode,
@@ -4970,15 +4943,15 @@ buf_page_get_gen(
mtr_t* mtr,
dberr_t* err)
{
- if (buf_block_t *block = recv_recovery_create_page(page_id))
+ if (buf_block_t *block= recv_recovery_create_page(page_id))
{
- buf_block_fix(block);
- ut_ad(rw_lock_s_lock_nowait(&block->debug_latch, file, line));
+ block->fix();
+ ut_ad(rw_lock_s_lock_nowait(block->debug_latch, file, line));
block= buf_page_mtr_lock(block, rw_latch, mtr, file, line);
return block;
}
- return buf_page_get_low(page_id, page_size, rw_latch,
+ return buf_page_get_low(page_id, zip_size, rw_latch,
guess, mode, file, line, mtr, err);
}
@@ -5025,7 +4998,7 @@ buf_page_optimistic_get(
buf_page_make_young_if_needed(&block->page);
ut_ad(!ibuf_inside(mtr)
- || ibuf_page(block->page.id, block->page.size, NULL));
+ || ibuf_page(block->page.id, block->zip_size(), NULL));
mtr_memo_type_t fix_type;
@@ -5079,7 +5052,7 @@ buf_page_optimistic_get(
if (!access_time) {
/* In the case of a first access, try to apply linear
read-ahead */
- buf_read_ahead_linear(block->page.id, block->page.size,
+ buf_read_ahead_linear(block->page.id, block->zip_size(),
ibuf_inside(mtr));
}
@@ -5301,13 +5274,14 @@ buf_page_init_low(
/** Inits a page to the buffer buf_pool.
@param[in,out] buf_pool buffer pool
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] block block to init */
static
void
buf_page_init(
buf_pool_t* buf_pool,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
buf_block_t* block)
{
buf_page_t* hash_page;
@@ -5352,7 +5326,7 @@ buf_page_init(
ut_a(buf_fix_count > 0);
- my_atomic_add32((int32*) &block->page.buf_fix_count, buf_fix_count);
+ block->page.buf_fix_count += buf_fix_count;
buf_pool_watch_remove(buf_pool, hash_page);
} else {
@@ -5375,14 +5349,11 @@ buf_page_init(
ut_d(block->page.in_page_hash = TRUE);
block->page.id = page_id;
- block->page.size.copy_from(page_size);
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash,
page_id.fold(), &block->page);
- if (page_size.is_compressed()) {
- page_zip_set_size(&block->page.zip, page_size.physical());
- }
+ page_zip_set_size(&block->page.zip, zip_size);
}
/** Initialize a page for read to the buffer buf_pool. If the page is
@@ -5396,6 +5367,7 @@ and the lock released later.
@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] unzip whether the uncompressed page is
requested (for ROW_FORMAT=COMPRESSED)
@return pointer to the block
@@ -5405,7 +5377,7 @@ buf_page_init_for_read(
dberr_t* err,
ulint mode,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
bool unzip)
{
buf_block_t* block;
@@ -5424,12 +5396,12 @@ buf_page_init_for_read(
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
/* It is a read-ahead within an ibuf routine */
- ut_ad(!ibuf_bitmap_page(page_id, page_size));
+ ut_ad(!ibuf_bitmap_page(page_id, zip_size));
ibuf_mtr_start(&mtr);
- if (!recv_no_ibuf_operations &&
- !ibuf_page(page_id, page_size, &mtr)) {
+ if (!recv_no_ibuf_operations
+ && !ibuf_page(page_id, zip_size, &mtr)) {
ibuf_mtr_commit(&mtr);
@@ -5439,7 +5411,7 @@ buf_page_init_for_read(
ut_ad(mode == BUF_READ_ANY_PAGE);
}
- if (page_size.is_compressed() && !unzip && !recv_recovery_is_on()) {
+ if (zip_size && !unzip && !recv_recovery_is_on()) {
block = NULL;
} else {
block = buf_LRU_get_free_block(buf_pool);
@@ -5474,7 +5446,7 @@ buf_page_init_for_read(
ut_ad(buf_pool_from_bpage(bpage) == buf_pool);
- buf_page_init(buf_pool, page_id, page_size, block);
+ buf_page_init(buf_pool, page_id, zip_size, block);
/* Note: We are using the hash_lock for protection. This is
safe because no other thread can lookup the block from the
@@ -5498,7 +5470,7 @@ buf_page_init_for_read(
rw_lock_x_lock_gen(&block->lock, BUF_IO_READ);
- if (page_size.is_compressed()) {
+ if (zip_size) {
/* buf_pool->mutex may be released and
reacquired by buf_buddy_alloc(). Thus, we
must release block->mutex in order not to
@@ -5508,8 +5480,7 @@ buf_page_init_for_read(
been added to buf_pool->LRU and
buf_pool->page_hash. */
buf_page_mutex_exit(block);
- data = buf_buddy_alloc(buf_pool, page_size.physical(),
- &lru);
+ data = buf_buddy_alloc(buf_pool, zip_size, &lru);
buf_page_mutex_enter(block);
block->page.zip.data = (page_zip_t*) data;
@@ -5530,7 +5501,7 @@ buf_page_init_for_read(
control block (bpage), in order to avoid the
invocation of buf_buddy_relocate_block() on
uninitialized data. */
- data = buf_buddy_alloc(buf_pool, page_size.physical(), &lru);
+ data = buf_buddy_alloc(buf_pool, zip_size, &lru);
rw_lock_x_lock(hash_lock);
@@ -5548,8 +5519,7 @@ buf_page_init_for_read(
/* The block was added by some other thread. */
rw_lock_x_unlock(hash_lock);
watch_page = NULL;
- buf_buddy_free(buf_pool, data,
- page_size.physical());
+ buf_buddy_free(buf_pool, data, zip_size);
bpage = NULL;
goto func_exit;
@@ -5562,13 +5532,11 @@ buf_page_init_for_read(
bpage->buf_pool_index = buf_pool_index(buf_pool);
page_zip_des_init(&bpage->zip);
- page_zip_set_size(&bpage->zip, page_size.physical());
+ page_zip_set_size(&bpage->zip, zip_size);
bpage->zip.data = (page_zip_t*) data;
- bpage->size.copy_from(page_size);
-
mutex_enter(&buf_pool->zip_mutex);
- UNIV_MEM_DESC(bpage->zip.data, bpage->size.physical());
+ UNIV_MEM_DESC(bpage->zip.data, zip_size);
buf_page_init_low(bpage);
@@ -5593,7 +5561,7 @@ buf_page_init_for_read(
ut_a(buf_fix_count > 0);
- my_atomic_add32((int32*) &bpage->buf_fix_count, buf_fix_count);
+ bpage->buf_fix_count += buf_fix_count;
ut_ad(buf_pool_watch_is_sentinel(buf_pool, watch_page));
buf_pool_watch_remove(buf_pool, watch_page);
@@ -5632,18 +5600,18 @@ func_exit:
return(bpage);
}
-/** Initializes a page to the buffer buf_pool. The page is usually not read
+/** Initialize a page in the buffer pool. The page is usually not read
from a file even if it cannot be found in the buffer buf_pool. This is one
of the functions which perform to a block a state transition NOT_USED =>
FILE_PAGE (the other is buf_page_get_gen).
@param[in] page_id page id
-@param[in] page_size page size
-@param[in] mtr mini-transaction
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] mtr mini-transaction
@return pointer to the block, page bufferfixed */
buf_block_t*
buf_page_create(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr)
{
buf_frame_t* frame;
@@ -5653,7 +5621,7 @@ buf_page_create(
rw_lock_t* hash_lock;
ut_ad(mtr->is_active());
- ut_ad(page_id.space() != 0 || !page_size.is_compressed());
+ ut_ad(page_id.space() != 0 || !zip_size);
free_block = buf_LRU_get_free_block(buf_pool);
@@ -5676,13 +5644,13 @@ buf_page_create(
buf_block_free(free_block);
if (!recv_recovery_is_on()) {
- return buf_page_get_with_no_latch(page_id, page_size,
+ return buf_page_get_with_no_latch(page_id, zip_size,
mtr);
}
- mutex_exit(&recv_sys->mutex);
- block = buf_page_get_with_no_latch(page_id, page_size, mtr);
- mutex_enter(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
+ block = buf_page_get_with_no_latch(page_id, zip_size, mtr);
+ mutex_enter(&recv_sys.mutex);
return block;
}
@@ -5695,7 +5663,7 @@ buf_page_create(
buf_page_mutex_enter(block);
- buf_page_init(buf_pool, page_id, page_size, block);
+ buf_page_init(buf_pool, page_id, zip_size, block);
rw_lock_x_unlock(hash_lock);
@@ -5705,7 +5673,7 @@ buf_page_create(
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
buf_pool->stat.n_pages_created++;
- if (page_size.is_compressed()) {
+ if (zip_size) {
void* data;
bool lru;
@@ -5723,7 +5691,7 @@ buf_page_create(
the reacquisition of buf_pool->mutex. We also must
defer this operation until after the block descriptor
has been added to buf_pool->LRU and buf_pool->page_hash. */
- data = buf_buddy_alloc(buf_pool, page_size.physical(), &lru);
+ data = buf_buddy_alloc(buf_pool, zip_size, &lru);
buf_page_mutex_enter(block);
block->page.zip.data = (page_zip_t*) data;
@@ -5750,7 +5718,7 @@ buf_page_create(
/* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */
if (!recv_recovery_is_on()) {
- ibuf_merge_or_delete_for_page(NULL, page_id, &page_size, TRUE);
+ ibuf_merge_or_delete_for_page(NULL, page_id, zip_size, true);
}
frame = block->frame;
@@ -5946,6 +5914,29 @@ buf_corrupt_page_release(buf_page_t* bpage, const fil_space_t* space)
buf_pool_mutex_exit(buf_pool);
}
+/** Check if the encrypted page is corrupted for the full crc32 format.
+@param[in] space_id page belongs to space id
+@param[in] dst_frame page
+@param[in] is_compressed compressed page
+@return true if page is corrupted or false if it isn't */
+static bool buf_page_full_crc32_is_corrupted(
+ ulint space_id,
+ const byte* dst_frame,
+ bool is_compressed)
+{
+ if (!is_compressed
+ && memcmp(dst_frame + FIL_PAGE_LSN + 4,
+ dst_frame + srv_page_size - FIL_PAGE_FCRC32_END_LSN, 4)) {
+ return true;
+ }
+
+ if (space_id != mach_read_from_4(dst_frame + FIL_PAGE_SPACE_ID)) {
+ return true;
+ }
+
+ return false;
+}
+
/** Check if page is maybe compressed, encrypted or both when we encounter
corrupted page. Note that we can't be 100% sure if page is corrupted
or decrypt/decompress just failed.
@@ -5964,6 +5955,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space)
byte* dst_frame = (bpage->zip.data) ? bpage->zip.data :
((buf_block_t*) bpage)->frame;
dberr_t err = DB_SUCCESS;
+ uint key_version = buf_page_get_key_version(dst_frame, space->flags);
/* In buf_decrypt_after_read we have either decrypted the page if
page post encryption checksum matches and used key_id is found
@@ -5971,15 +5963,23 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space)
not decrypted and it could be either encrypted and corrupted
or corrupted or good page. If we decrypted, there page could
still be corrupted if used key does not match. */
- const bool seems_encrypted = mach_read_from_4(
- dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
+ const bool seems_encrypted = !space->full_crc32() && key_version
&& space->crypt_data
&& space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED;
+ ut_ad(space->purpose != FIL_TYPE_TEMPORARY || space->full_crc32());
/* If traditional checksums match, we assume that page is
not anymore encrypted. */
- if (buf_page_is_corrupted(
- true, dst_frame, bpage->size, space)) {
+ if (space->full_crc32()
+ && !buf_is_zeroes(span<const byte>(dst_frame,
+ space->physical_size()))
+ && (key_version || space->is_compressed()
+ || space->purpose == FIL_TYPE_TEMPORARY)) {
+ if (buf_page_full_crc32_is_corrupted(
+ space->id, dst_frame, space->is_compressed())) {
+ err = DB_PAGE_CORRUPTED;
+ }
+ } else if (buf_page_is_corrupted(true, dst_frame, space->flags)) {
err = DB_PAGE_CORRUPTED;
}
@@ -5994,8 +5994,7 @@ static dberr_t buf_page_check_corrupt(buf_page_t* bpage, fil_space_t* space)
ib::info()
<< "However key management plugin or used key_version "
- << mach_read_from_4(dst_frame
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
+ << key_version
<< " is not found or"
" used encryption algorithm or method does not match.";
@@ -6040,7 +6039,7 @@ buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict)
io_type = buf_page_get_io_fix(bpage);
ut_ad(io_type == BUF_IO_READ || io_type == BUF_IO_WRITE);
- ut_ad(bpage->size.is_compressed() == (bpage->zip.data != NULL));
+ ut_ad(!!bpage->zip.ssize == (bpage->zip.data != NULL));
ut_ad(uncompressed || bpage->zip.data);
if (io_type == BUF_IO_READ) {
@@ -6064,10 +6063,10 @@ buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict)
}
if (bpage->zip.data && uncompressed) {
- my_atomic_addlint(&buf_pool->n_pend_unzip, 1);
+ buf_pool->n_pend_unzip++;
ibool ok = buf_zip_decompress((buf_block_t*) bpage,
FALSE);
- my_atomic_addlint(&buf_pool->n_pend_unzip, ulint(-1));
+ buf_pool->n_pend_unzip--;
if (!ok) {
ib::info() << "Page "
@@ -6094,13 +6093,26 @@ buf_page_io_complete(buf_page_t* bpage, bool dblwr, bool evict)
} else if (read_space_id == 0 && read_page_no == 0) {
/* This is likely an uninitialized page. */
- } else if ((bpage->id.space() != TRX_SYS_SPACE
+ } else if (((!space->full_crc32()
+ || bpage->id.space() != TRX_SYS_SPACE)
&& bpage->id.space() != read_space_id)
|| bpage->id.page_no() != read_page_no) {
- /* We did not compare space_id to read_space_id
- in the system tablespace, because the field
- was written as garbage before MySQL 4.1.1,
- which did not support innodb_file_per_table. */
+ /* We do not compare space_id to read_space_id
+ in the system tablespace unless space->full_crc32(),
+ because the field was written as garbage before
+ MySQL 4.1.1, which introduced support for
+ innodb_file_per_table. */
+
+ if (space->full_crc32()
+ && *reinterpret_cast<uint32_t*>
+ (&frame[FIL_PAGE_FCRC32_KEY_VERSION])
+ && space->crypt_data
+ && space->crypt_data->type
+ != CRYPT_SCHEME_UNENCRYPTED) {
+ ib::error() << "Cannot decrypt " << bpage->id;
+ err = DB_DECRYPTION_FAILED;
+ goto release_page;
+ }
ib::error() << "Space id and page no stored in "
"the page, read in are "
@@ -6137,7 +6149,7 @@ database_corrupted:
<< ". You may have to recover from "
<< "a backup.";
- buf_page_print(frame, bpage->size);
+ buf_page_print(frame, bpage->zip_size());
ib::info()
<< "It is also possible that your"
@@ -6174,6 +6186,7 @@ database_corrupted:
if (err == DB_PAGE_CORRUPTED
|| err == DB_DECRYPTION_FAILED) {
+release_page:
const page_id_t corrupt_page_id = bpage->id;
buf_corrupt_page_release(bpage, space);
@@ -6190,19 +6203,15 @@ database_corrupted:
recv_recover_page(bpage);
}
- /* If space is being truncated then avoid ibuf operation.
- During re-init we have already freed ibuf entries. */
if (uncompressed
&& !recv_no_ibuf_operations
&& (bpage->id.space() == 0
|| !is_predefined_tablespace(bpage->id.space()))
- && !srv_is_tablespace_truncated(bpage->id.space())
&& fil_page_get_type(frame) == FIL_PAGE_INDEX
&& page_is_leaf(frame)) {
-
ibuf_merge_or_delete_for_page(
- (buf_block_t*) bpage, bpage->id,
- &bpage->size, TRUE);
+ reinterpret_cast<buf_block_t*>(bpage),
+ bpage->id, bpage->zip_size(), true);
}
space->release_for_io();
@@ -7296,6 +7305,21 @@ buf_all_freed(void)
return(TRUE);
}
+/** Verify that post encryption checksum match with the calculated checksum.
+This function should be called only if tablespace contains crypt data metadata.
+@param[in] page page frame
+@param[in] fsp_flags tablespace flags
+@return true if true if page is encrypted and OK, false otherwise */
+bool buf_page_verify_crypt_checksum(const byte* page, ulint fsp_flags)
+{
+ if (!fil_space_t::full_crc32(fsp_flags)) {
+ return fil_space_verify_crypt_checksum(
+ page, fil_space_t::zip_size(fsp_flags));
+ }
+
+ return !buf_page_is_corrupted(true, page, fsp_flags);
+}
+
/*********************************************************************//**
Checks that there currently are no pending i/o-operations for the buffer
pool.
@@ -7378,28 +7402,21 @@ static byte* buf_tmp_page_encrypt(
byte* src_frame,
byte* dst_frame)
{
- uint header_len = FIL_PAGE_DATA;
- /* FIL page header is not encrypted */
- memcpy(dst_frame, src_frame, header_len);
-
/* Calculate the start offset in a page */
- uint unencrypted_bytes = header_len + FIL_PAGE_DATA_END;
- uint srclen = srv_page_size - unencrypted_bytes;
- const byte* src = src_frame + header_len;
- byte* dst = dst_frame + header_len;
+ uint srclen = srv_page_size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ + FIL_PAGE_FCRC32_CHECKSUM);
+ const byte* src = src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
+ byte* dst = dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
+
+ memcpy(dst_frame, src_frame, FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
if (!log_tmp_block_encrypt(src, srclen, dst, (offset * srv_page_size),
true)) {
return NULL;
}
- memcpy(dst_frame + srv_page_size - FIL_PAGE_DATA_END,
- src_frame + srv_page_size - FIL_PAGE_DATA_END,
- FIL_PAGE_DATA_END);
-
- /* Handle post encryption checksum */
- mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
- buf_calc_page_crc32(dst_frame));
+ const ulint payload = srv_page_size - FIL_PAGE_FCRC32_CHECKSUM;
+ mach_write_to_4(dst_frame + payload, ut_crc32(dst_frame, payload));
srv_stats.pages_encrypted.inc();
srv_stats.n_temp_blocks_encrypted.inc();
@@ -7415,7 +7432,7 @@ a page is written to disk.
(may be src_frame or an encrypted/compressed copy of it) */
UNIV_INTERN
byte*
-buf_page_encrypt_before_write(
+buf_page_encrypt(
fil_space_t* space,
buf_page_t* bpage,
byte* src_frame)
@@ -7423,7 +7440,7 @@ buf_page_encrypt_before_write(
ut_ad(space->id == bpage->id.space());
bpage->real_size = srv_page_size;
- fil_page_type_validate(src_frame);
+ ut_d(fil_page_type_validate(space, src_frame));
switch (bpage->id.page_no()) {
case 0:
@@ -7451,18 +7468,23 @@ buf_page_encrypt_before_write(
&& crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
&& (!crypt_data->is_default_encryption()
|| srv_encrypt_tables);
-
- page_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(space->flags);
+ page_compressed = space->is_compressed();
}
if (!encrypted && !page_compressed) {
/* No need to encrypt or page compress the page.
Clear key-version & crypt-checksum. */
- memset(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
+ if (space->full_crc32()) {
+ memset(src_frame + FIL_PAGE_FCRC32_KEY_VERSION, 0, 4);
+ } else {
+ memset(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ 0, 8);
+ }
+
return src_frame;
}
- ut_ad(!bpage->size.is_compressed() || !page_compressed);
+ ut_ad(!bpage->zip_size() || !page_compressed);
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
/* Find free slot from temporary memory array */
buf_tmp_buffer_t* slot = buf_pool_reserve_tmp_slot(buf_pool);
@@ -7471,6 +7493,19 @@ buf_page_encrypt_before_write(
buf_tmp_reserve_crypt_buf(slot);
byte *dst_frame = slot->crypt_buf;
+ const bool full_crc32 = space->full_crc32();
+
+ if (full_crc32) {
+ /* Write LSN for the full crc32 checksum before
+ encryption. Because lsn is one of the input for encryption. */
+ mach_write_to_8(src_frame + FIL_PAGE_LSN,
+ bpage->newest_modification);
+ if (!page_compressed) {
+ mach_write_to_4(
+ src_frame + srv_page_size - FIL_PAGE_FCRC32_END_LSN,
+ (ulint) bpage->newest_modification);
+ }
+ }
if (!page_compressed) {
not_compressed:
@@ -7490,26 +7525,38 @@ not_compressed:
bpage->real_size = srv_page_size;
slot->out_buf = dst_frame = tmp;
- ut_d(fil_page_type_validate(tmp));
+ ut_d(fil_page_type_validate(space, tmp));
} else {
ut_ad(space->purpose != FIL_TYPE_TEMPORARY);
/* First we compress the page content */
buf_tmp_reserve_compression_buf(slot);
byte* tmp = slot->comp_buf;
ulint out_len = fil_page_compress(
- src_frame, tmp,
- fsp_flags_get_page_compression_level(space->flags),
+ src_frame, tmp, space->flags,
fil_space_get_block_size(space, bpage->id.page_no()),
encrypted);
+
if (!out_len) {
goto not_compressed;
}
bpage->real_size = out_len;
+ if (full_crc32) {
+ ut_d(bool compressed = false);
+ out_len = buf_page_full_crc32_size(tmp,
+#ifdef UNIV_DEBUG
+ &compressed,
+#else
+ NULL,
+#endif
+ NULL);
+ ut_ad(compressed);
+ }
+
/* Workaround for MDEV-15527. */
memset(tmp + out_len, 0 , srv_page_size - out_len);
- ut_d(fil_page_type_validate(tmp));
+ ut_d(fil_page_type_validate(space, tmp));
if (encrypted) {
/* And then we encrypt the page content */
@@ -7520,10 +7567,17 @@ not_compressed:
dst_frame);
}
+ if (full_crc32) {
+ compile_time_assert(FIL_PAGE_FCRC32_CHECKSUM == 4);
+ mach_write_to_4(tmp + out_len - 4,
+ ut_crc32(tmp, out_len - 4));
+ ut_ad(!buf_page_is_corrupted(true, tmp, space->flags));
+ }
+
slot->out_buf = dst_frame = tmp;
}
- ut_d(fil_page_type_validate(dst_frame));
+ ut_d(fil_page_type_validate(space, dst_frame));
// return dst_frame which will be written
return dst_frame;
@@ -7537,7 +7591,7 @@ bool
buf_page_should_punch_hole(
const buf_page_t* bpage)
{
- return (bpage->real_size != bpage->size.physical());
+ return bpage->real_size != bpage->physical_size();
}
/**
@@ -7550,6 +7604,6 @@ buf_page_get_trim_length(
const buf_page_t* bpage,
ulint write_length)
{
- return (bpage->size.physical() - write_length);
+ return bpage->physical_size() - write_length;
}
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/buf/buf0checksum.cc b/storage/innobase/buf/buf0checksum.cc
index 70ad5ed600b..2b2a74dd736 100644
--- a/storage/innobase/buf/buf0checksum.cc
+++ b/storage/innobase/buf/buf0checksum.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 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
@@ -39,35 +39,6 @@ ha_innodb.cc:12251: error: cannot convert 'srv_checksum_algorithm_t*' to
'long unsigned int*' in initialization */
ulong srv_checksum_algorithm = SRV_CHECKSUM_ALGORITHM_INNODB;
-#ifdef INNODB_BUG_ENDIAN_CRC32
-/** Calculate the CRC32 checksum of a page. The value is stored to the page
-when it is written to a file and also checked for a match when reading from
-the file. Note that we must be careful to calculate the same value on all
-architectures.
-@param[in] page buffer page (srv_page_size bytes)
-@param[in] bug_endian whether to use big endian byteorder
-when converting byte strings to integers, for bug-compatibility with
-big-endian architecture running MySQL 5.6, MariaDB 10.0 or MariaDB 10.1
-@return CRC-32C */
-uint32_t buf_calc_page_crc32(const byte* page, bool bug_endian)
-{
- return bug_endian
- ? ut_crc32_legacy_big_endian(
- page + FIL_PAGE_OFFSET,
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- - FIL_PAGE_OFFSET)
- ^ ut_crc32_legacy_big_endian(page + FIL_PAGE_DATA,
- srv_page_size
- - (FIL_PAGE_DATA
- + FIL_PAGE_END_LSN_OLD_CHKSUM))
- : ut_crc32(page + FIL_PAGE_OFFSET,
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- - FIL_PAGE_OFFSET)
- ^ ut_crc32(page + FIL_PAGE_DATA,
- srv_page_size
- - (FIL_PAGE_DATA + FIL_PAGE_END_LSN_OLD_CHKSUM));
-}
-#else
/** Calculate the CRC32 checksum of a page. The value is stored to the page
when it is written to a file and also checked for a match when reading from
the file. Note that we must be careful to calculate the same value on all
@@ -88,7 +59,6 @@ uint32_t buf_calc_page_crc32(const byte* page)
srv_page_size
- (FIL_PAGE_DATA + FIL_PAGE_END_LSN_OLD_CHKSUM));
}
-#endif
/** Calculate a checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value on
@@ -151,6 +121,10 @@ buf_checksum_algorithm_name(srv_checksum_algorithm_t algo)
return("none");
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
return("strict_none");
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ return("full_crc32");
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
+ return("strict_full_crc32");
}
ut_error;
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index c32deffd80c..f9b5b30c364 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -87,7 +87,7 @@ buf_dblwr_get(
buf_block_t* block;
block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
@@ -368,7 +368,7 @@ buf_dblwr_init_or_load_pages(
byte* doublewrite;
byte* unaligned_read_buf;
ibool reset_space_ids = FALSE;
- recv_dblwr_t& recv_dblwr = recv_sys->dblwr;
+ recv_dblwr_t& recv_dblwr = recv_sys.dblwr;
/* We do the file i/o past the buffer pool */
@@ -473,6 +473,7 @@ buf_dblwr_init_or_load_pages(
page = buf;
for (ulint i = 0; i < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 2; i++) {
+
if (reset_space_ids) {
ulint source_page_no;
@@ -532,7 +533,7 @@ buf_dblwr_process()
ulint page_no_dblwr = 0;
byte* read_buf;
byte* unaligned_read_buf;
- recv_dblwr_t& recv_dblwr = recv_sys->dblwr;
+ recv_dblwr_t& recv_dblwr = recv_sys.dblwr;
if (!buf_dblwr) {
return;
@@ -565,12 +566,9 @@ buf_dblwr_process()
if (page_no >= space->size) {
- /* Do not report the warning if the tablespace
- is scheduled for truncation or was truncated
- and we have parsed an MLOG_TRUNCATE record. */
- if (!srv_is_tablespace_truncated(space_id)
- && !srv_was_tablespace_truncated(space)
- && !srv_is_undo_tablespace(space_id)) {
+ /* Do not report the warning for undo
+ tablespaces, because they can be truncated in place. */
+ if (!srv_is_undo_tablespace(space_id)) {
ib::warn() << "A copy of page " << page_id
<< " in the doublewrite buffer slot "
<< page_no_dblwr
@@ -579,13 +577,13 @@ buf_dblwr_process()
continue;
}
- const page_size_t page_size(space->flags);
- ut_ad(!buf_is_zeroes(span<const byte>(page,
- page_size.physical())));
+ const ulint physical_size = space->physical_size();
+ const ulint zip_size = space->zip_size();
+ ut_ad(!buf_is_zeroes(span<const byte>(page, physical_size)));
/* We want to ensure that for partial reads the
unread portion of the page is NUL. */
- memset(read_buf, 0x0, page_size.physical());
+ memset(read_buf, 0x0, physical_size);
IORequest request;
@@ -594,8 +592,8 @@ buf_dblwr_process()
/* Read in the actual page from the file */
dberr_t err = fil_io(
request, true,
- page_id, page_size,
- 0, page_size.physical(), read_buf, NULL);
+ page_id, zip_size,
+ 0, physical_size, read_buf, NULL);
if (err != DB_SUCCESS) {
ib::warn()
@@ -605,9 +603,10 @@ buf_dblwr_process()
}
const bool is_all_zero = buf_is_zeroes(
- span<const byte>(read_buf, page_size.physical()));
+ span<const byte>(read_buf, physical_size));
const bool expect_encrypted = space->crypt_data
&& space->crypt_data->type != CRYPT_SCHEME_UNENCRYPTED;
+ bool is_corrupted = false;
if (is_all_zero) {
/* We will check if the copy in the
@@ -617,19 +616,22 @@ buf_dblwr_process()
} else {
/* Decompress the page before
validating the checksum. */
- ulint decomp = fil_page_decompress(buf, read_buf);
- if (!decomp || (decomp != srv_page_size
- && page_size.is_compressed())) {
+ ulint decomp = fil_page_decompress(buf, read_buf,
+ space->flags);
+ if (!decomp || (zip_size && decomp != srv_page_size)) {
goto bad;
}
- if (expect_encrypted && mach_read_from_4(
- read_buf
- + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
- ? fil_space_verify_crypt_checksum(read_buf,
- page_size)
- : !buf_page_is_corrupted(true, read_buf,
- page_size, space)) {
+ if (expect_encrypted
+ && buf_page_get_key_version(read_buf, space->flags)) {
+ is_corrupted = !buf_page_verify_crypt_checksum(
+ read_buf, space->flags);
+ } else {
+ is_corrupted = buf_page_is_corrupted(
+ true, read_buf, space->flags);
+ }
+
+ if (!is_corrupted) {
/* The page is good; there is no need
to consult the doublewrite buffer. */
continue;
@@ -643,16 +645,21 @@ bad:
<< " from the doublewrite buffer.";
}
- ulint decomp = fil_page_decompress(buf, page);
- if (!decomp || (decomp != srv_page_size
- && page_size.is_compressed())) {
+ ulint decomp = fil_page_decompress(buf, page, space->flags);
+ if (!decomp || (zip_size && decomp != srv_page_size)) {
continue;
}
- if (expect_encrypted && mach_read_from_4(
- page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
- ? !fil_space_verify_crypt_checksum(page, page_size)
- : buf_page_is_corrupted(true, page, page_size, space)) {
+ if (expect_encrypted
+ && buf_page_get_key_version(read_buf, space->flags)) {
+ is_corrupted = !buf_page_verify_crypt_checksum(
+ page, space->flags);
+ } else {
+ is_corrupted = buf_page_is_corrupted(
+ true, page, space->flags);
+ }
+
+ if (is_corrupted) {
/* Theoretically we could have another good
copy for this page in the doublewrite
buffer. If not, we will report a fatal error
@@ -664,7 +671,7 @@ bad:
if (page_no == 0) {
/* Check the FSP_SPACE_FLAGS. */
ulint flags = fsp_header_get_flags(page);
- if (!fsp_flags_is_valid(flags, space_id)
+ if (!fil_space_t::is_valid_flags(flags, space_id)
&& fsp_flags_convert_from_101(flags)
== ULINT_UNDEFINED) {
ib::warn() << "Ignoring a doublewrite copy"
@@ -681,8 +688,8 @@ bad:
IORequest write_request(IORequest::WRITE);
- fil_io(write_request, true, page_id, page_size,
- 0, page_size.physical(),
+ fil_io(write_request, true, page_id, zip_size,
+ 0, physical_size,
const_cast<byte*>(page), NULL);
ib::info() << "Recovered page " << page_id
@@ -786,40 +793,42 @@ buf_dblwr_update(
}
}
-/********************************************************************//**
-Check the LSN values on the page. */
-static
-void
-buf_dblwr_check_page_lsn(
-/*=====================*/
- const page_t* page) /*!< in: page to check */
+#ifdef UNIV_DEBUG
+/** Check the LSN values on the page.
+@param[in] page page to check
+@param[in] s tablespace */
+static void buf_dblwr_check_page_lsn(const page_t* page, const fil_space_t& s)
{
- ibool page_compressed = (mach_read_from_2(page+FIL_PAGE_TYPE) == FIL_PAGE_PAGE_COMPRESSED);
- uint key_version = mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
-
/* Ignore page compressed or encrypted pages */
- if (page_compressed || key_version) {
+ if (s.is_compressed()
+ || buf_page_get_key_version(page, s.flags)) {
return;
}
- if (memcmp(page + (FIL_PAGE_LSN + 4),
- page + (srv_page_size
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4),
- 4)) {
-
- const ulint lsn1 = mach_read_from_4(
- page + FIL_PAGE_LSN + 4);
- const ulint lsn2 = mach_read_from_4(
- page + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM
- + 4);
-
- ib::error() << "The page to be written seems corrupt!"
+ const unsigned lsn1 = mach_read_from_4(page + FIL_PAGE_LSN + 4),
+ lsn2 = mach_read_from_4(page + srv_page_size
+ - (s.full_crc32()
+ ? FIL_PAGE_FCRC32_END_LSN
+ : FIL_PAGE_END_LSN_OLD_CHKSUM - 4));
+ if (UNIV_UNLIKELY(lsn1 != lsn2)) {
+ ib::error() << "The page to be written to "
+ << s.chain.start->name <<
+ " seems corrupt!"
" The low 4 bytes of LSN fields do not match"
" (" << lsn1 << " != " << lsn2 << ")!"
" Noticed in the buffer pool.";
}
}
+static void buf_dblwr_check_page_lsn(const buf_page_t& b, const byte* page)
+{
+ if (fil_space_t* space = fil_space_acquire_for_io(b.id.space())) {
+ buf_dblwr_check_page_lsn(page, *space);
+ space->release_for_io();
+ }
+}
+#endif /* UNIV_DEBUG */
+
/********************************************************************//**
Asserts when a corrupt block is find during writing out data to the
disk. */
@@ -829,7 +838,7 @@ buf_dblwr_assert_on_corrupt_block(
/*==============================*/
const buf_block_t* block) /*!< in: block to check */
{
- buf_page_print(block->frame, univ_page_size);
+ buf_page_print(block->frame);
ib::fatal() << "Apparent corruption of an index page "
<< block->page.id
@@ -919,14 +928,14 @@ buf_dblwr_write_block_to_datafile(
void * frame = buf_page_get_frame(bpage);
if (bpage->zip.data != NULL) {
- ut_ad(bpage->size.is_compressed());
+ ut_ad(bpage->zip_size());
- fil_io(request, sync, bpage->id, bpage->size, 0,
- bpage->size.physical(),
+ fil_io(request, sync, bpage->id, bpage->zip_size(), 0,
+ bpage->zip_size(),
(void*) frame,
(void*) bpage);
} else {
- ut_ad(!bpage->size.is_compressed());
+ ut_ad(!bpage->zip_size());
/* Our IO API is common for both reads and writes and is
therefore geared towards a non-const parameter. */
@@ -935,11 +944,10 @@ buf_dblwr_write_block_to_datafile(
const_cast<buf_page_t*>(bpage));
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
- buf_dblwr_check_page_lsn(block->frame);
-
+ ut_d(buf_dblwr_check_page_lsn(block->page, block->frame));
fil_io(request,
- sync, bpage->id, bpage->size, 0, bpage->real_size,
- frame, block);
+ sync, bpage->id, bpage->zip_size(), 0, bpage->real_size,
+ frame, block);
}
}
@@ -1030,10 +1038,7 @@ try_again:
/* Check that the actual page in the buffer pool is
not corrupt and the LSN values are sane. */
buf_dblwr_check_block(block);
-
- /* Check that the page as written to the doublewrite
- buffer has sane LSN values. */
- buf_dblwr_check_page_lsn(write_buf + len2);
+ ut_d(buf_dblwr_check_page_lsn(block->page, write_buf + len2));
}
/* Write out the first block of the doublewrite buffer */
@@ -1041,7 +1046,7 @@ try_again:
buf_dblwr->first_free) << srv_page_size_shift;
fil_io(IORequestWrite, true,
- page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), univ_page_size,
+ page_id_t(TRX_SYS_SPACE, buf_dblwr->block1), 0,
0, len, (void*) write_buf, NULL);
if (buf_dblwr->first_free <= TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
@@ -1057,7 +1062,7 @@ try_again:
+ (TRX_SYS_DOUBLEWRITE_BLOCK_SIZE << srv_page_size_shift);
fil_io(IORequestWrite, true,
- page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), univ_page_size,
+ page_id_t(TRX_SYS_SPACE, buf_dblwr->block2), 0,
0, len, (void*) write_buf, NULL);
flush:
@@ -1143,21 +1148,16 @@ try_again:
encryption and/or page compression */
void * frame = buf_page_get_frame(bpage);
- if (bpage->size.is_compressed()) {
- UNIV_MEM_ASSERT_RW(bpage->zip.data, bpage->size.physical());
+ if (auto zip_size = bpage->zip_size()) {
+ UNIV_MEM_ASSERT_RW(bpage->zip.data, zip_size);
/* Copy the compressed page and clear the rest. */
-
- memcpy(p, frame, bpage->size.physical());
-
- memset(p + bpage->size.physical(), 0x0,
- srv_page_size - bpage->size.physical());
+ memcpy(p, frame, zip_size);
+ memset(p + zip_size, 0x0, srv_page_size - zip_size);
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
- UNIV_MEM_ASSERT_RW(frame,
- bpage->size.logical());
-
- memcpy(p, frame, bpage->size.logical());
+ UNIV_MEM_ASSERT_RW(frame, srv_page_size);
+ memcpy(p, frame, srv_page_size);
}
buf_dblwr->buf_block_arr[buf_dblwr->first_free] = bpage;
@@ -1219,8 +1219,8 @@ buf_dblwr_write_single_page(
/* Check that the page as written to the doublewrite
buffer has sane LSN values. */
if (!bpage->zip.data) {
- buf_dblwr_check_page_lsn(
- ((buf_block_t*) bpage)->frame);
+ ut_d(buf_dblwr_check_page_lsn(
+ *bpage, ((buf_block_t*) bpage)->frame));
}
}
@@ -1279,18 +1279,18 @@ retry:
encryption and/or page compression */
void * frame = buf_page_get_frame(bpage);
- if (bpage->size.is_compressed()) {
+ if (auto zip_size = bpage->zip_size()) {
memcpy(buf_dblwr->write_buf + srv_page_size * i,
- frame, bpage->size.physical());
+ frame, zip_size);
memset(buf_dblwr->write_buf + srv_page_size * i
- + bpage->size.physical(), 0x0,
- srv_page_size - bpage->size.physical());
+ + zip_size, 0x0,
+ srv_page_size - zip_size);
fil_io(IORequestWrite,
true,
page_id_t(TRX_SYS_SPACE, offset),
- univ_page_size,
+ 0,
0,
srv_page_size,
(void *)(buf_dblwr->write_buf + srv_page_size * i),
@@ -1301,7 +1301,7 @@ retry:
fil_io(IORequestWrite,
true,
page_id_t(TRX_SYS_SPACE, offset),
- univ_page_size,
+ 0,
0,
srv_page_size,
(void*) frame,
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index 487f044ec18..25e92158623 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -672,7 +672,7 @@ buf_load()
so all pages from a given tablespace are consecutive. */
ulint cur_space_id = BUF_DUMP_SPACE(dump[0]);
fil_space_t* space = fil_space_acquire_silent(cur_space_id);
- page_size_t page_size(space ? space->flags : 0);
+ ulint zip_size = space ? space->zip_size() : 0;
/* JAN: TODO: MySQL 5.7 PSI
#ifdef HAVE_PSI_STAGE_INTERFACE
@@ -703,9 +703,7 @@ buf_load()
space = fil_space_acquire_silent(cur_space_id);
if (space != NULL) {
- const page_size_t cur_page_size(
- space->flags);
- page_size.copy_from(cur_page_size);
+ zip_size = space->zip_size();
}
}
@@ -720,7 +718,7 @@ buf_load()
buf_read_page_background(
page_id_t(this_space_id, BUF_DUMP_PAGE(dump[i])),
- page_size, true);
+ zip_size, true);
if (i % 64 == 63) {
os_aio_simulated_wake_handler_threads();
@@ -822,7 +820,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
if (srv_buffer_pool_load_at_startup) {
#ifdef WITH_WSREP
- if (!wsrep_recovery) {
+ if (!get_wsrep_recovery()) {
#endif /* WITH_WSREP */
buf_load();
#ifdef WITH_WSREP
@@ -856,7 +854,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
"Dumping of buffer pool not started"
" as load was incomplete");
#ifdef WITH_WSREP
- } else if (wsrep_recovery) {
+ } else if (get_wsrep_recovery()) {
#endif /* WITH_WSREP */
} else {
buf_dump(FALSE/* do complete dump at shutdown */);
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index b116ca919fd..7d1edaa647d 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -211,7 +211,7 @@ incr_flush_list_size_in_bytes(
{
ut_ad(buf_flush_list_mutex_own(buf_pool));
- buf_pool->stat.flush_list_bytes += block->page.size.physical();
+ buf_pool->stat.flush_list_bytes += block->physical_size();
ut_ad(buf_pool->stat.flush_list_bytes <= buf_pool->curr_pool_size);
}
@@ -427,137 +427,44 @@ buf_flush_insert_into_flush_list(
ut_ad(buf_page_mutex_own(block));
buf_flush_list_mutex_enter(buf_pool);
-
- ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL)
- || (UT_LIST_GET_FIRST(buf_pool->flush_list)->oldest_modification
- <= lsn));
-
- /* If we are in the recovery then we need to update the flush
- red-black tree as well. */
- if (buf_pool->flush_rbt != NULL) {
- buf_flush_list_mutex_exit(buf_pool);
- buf_flush_insert_sorted_into_flush_list(buf_pool, block, lsn);
- return;
- }
-
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(!block->page.in_flush_list);
-
ut_d(block->page.in_flush_list = TRUE);
+ ut_ad(!block->page.oldest_modification);
block->page.oldest_modification = lsn;
-
- UT_LIST_ADD_FIRST(buf_pool->flush_list, &block->page);
-
+ UNIV_MEM_ASSERT_RW(block->page.zip.data
+ ? block->page.zip.data : block->frame,
+ block->physical_size());
incr_flush_list_size_in_bytes(block, buf_pool);
-#ifdef UNIV_DEBUG_VALGRIND
- void* p;
-
- if (block->page.size.is_compressed()) {
- p = block->page.zip.data;
- } else {
- p = block->frame;
- }
-
- UNIV_MEM_ASSERT_RW(p, block->page.size.physical());
-#endif /* UNIV_DEBUG_VALGRIND */
-
-#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- ut_a(buf_flush_validate_skip(buf_pool));
-#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
-
- buf_flush_list_mutex_exit(buf_pool);
-}
-
-/********************************************************************//**
-Inserts a modified block into the flush list in the right sorted position.
-This function is used by recovery, because there the modifications do not
-necessarily come in the order of lsn's. */
-void
-buf_flush_insert_sorted_into_flush_list(
-/*====================================*/
- buf_pool_t* buf_pool, /*!< in: buffer pool instance */
- buf_block_t* block, /*!< in/out: block which is modified */
- lsn_t lsn) /*!< in: oldest modification */
-{
- buf_page_t* prev_b;
- buf_page_t* b;
-
- ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE);
- ut_ad(!buf_pool_mutex_own(buf_pool));
- ut_ad(log_flush_order_mutex_own());
- ut_ad(buf_page_mutex_own(block));
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
-
- buf_flush_list_mutex_enter(buf_pool);
-
- /* The field in_LRU_list is protected by buf_pool->mutex, which
- we are not holding. However, while a block is in the flush
- list, it is dirty and cannot be discarded, not from the
- page_hash or from the LRU list. At most, the uncompressed
- page frame of a compressed block may be discarded or created
- (copying the block->page to or from a buf_page_t that is
- dynamically allocated from buf_buddy_alloc()). Because those
- transitions hold block->mutex and the flush list mutex (via
- buf_flush_relocate_on_flush_list()), there is no possibility
- of a race condition in the assertions below. */
- ut_ad(block->page.in_LRU_list);
- ut_ad(block->page.in_page_hash);
- /* buf_buddy_block_register() will take a block in the
- BUF_BLOCK_MEMORY state, not a file page. */
- ut_ad(!block->page.in_zip_hash);
-
- ut_ad(!block->page.in_flush_list);
- ut_d(block->page.in_flush_list = TRUE);
- block->page.oldest_modification = lsn;
-
-#ifdef UNIV_DEBUG_VALGRIND
- void* p;
-
- if (block->page.size.is_compressed()) {
- p = block->page.zip.data;
- } else {
- p = block->frame;
- }
-
- UNIV_MEM_ASSERT_RW(p, block->page.size.physical());
-#endif /* UNIV_DEBUG_VALGRIND */
-
- prev_b = NULL;
-
- /* For the most part when this function is called the flush_rbt
- should not be NULL. In a very rare boundary case it is possible
- that the flush_rbt has already been freed by the recovery thread
- before the last page was hooked up in the flush_list by the
- io-handler thread. In that case we'll just do a simple
- linear search in the else block. */
- if (buf_pool->flush_rbt != NULL) {
-
- prev_b = buf_flush_insert_in_flush_rbt(&block->page);
-
- } else {
-
- b = UT_LIST_GET_FIRST(buf_pool->flush_list);
-
- while (b != NULL && b->oldest_modification
- > block->page.oldest_modification) {
-
- ut_ad(b->in_flush_list);
- prev_b = b;
- b = UT_LIST_GET_NEXT(list, b);
+ if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
+ ut_ad(srv_shutdown_state != SRV_SHUTDOWN_FLUSH_PHASE);
+ /* The field in_LRU_list is protected by buf_pool->mutex, which
+ we are not holding. However, while a block is in the flush
+ list, it is dirty and cannot be discarded, not from the
+ page_hash or from the LRU list. At most, the uncompressed
+ page frame of a compressed block may be discarded or created
+ (copying the block->page to or from a buf_page_t that is
+ dynamically allocated from buf_buddy_alloc()). Because those
+ transitions hold block->mutex and the flush list mutex (via
+ buf_flush_relocate_on_flush_list()), there is no possibility
+ of a race condition in the assertions below. */
+ ut_ad(block->page.in_LRU_list);
+ ut_ad(block->page.in_page_hash);
+ /* buf_buddy_block_register() will take a block in the
+ BUF_BLOCK_MEMORY state, not a file page. */
+ ut_ad(!block->page.in_zip_hash);
+
+ if (buf_page_t* prev_b =
+ buf_flush_insert_in_flush_rbt(&block->page)) {
+ UT_LIST_INSERT_AFTER(buf_pool->flush_list, prev_b, &block->page);
+ goto func_exit;
}
}
- if (prev_b == NULL) {
- UT_LIST_ADD_FIRST(buf_pool->flush_list, &block->page);
- } else {
- UT_LIST_INSERT_AFTER(buf_pool->flush_list, prev_b, &block->page);
- }
-
- incr_flush_list_size_in_bytes(block, buf_pool);
-
+ UT_LIST_ADD_FIRST(buf_pool->flush_list, &block->page);
+func_exit:
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
- ut_a(buf_flush_validate_low(buf_pool));
+ ut_a(buf_flush_validate_skip(buf_pool));
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
buf_flush_list_mutex_exit(buf_pool);
@@ -686,7 +593,7 @@ buf_flush_remove(
}
/* If the flush_rbt is active then delete from there as well. */
- if (buf_pool->flush_rbt != NULL) {
+ if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
buf_flush_delete_from_flush_rbt(bpage);
}
@@ -694,7 +601,7 @@ buf_flush_remove(
because we assert on in_flush_list in comparison function. */
ut_d(bpage->in_flush_list = FALSE);
- buf_pool->stat.flush_list_bytes -= bpage->size.physical();
+ buf_pool->stat.flush_list_bytes -= bpage->physical_size();
bpage->oldest_modification = 0;
@@ -754,7 +661,7 @@ buf_flush_relocate_on_flush_list(
/* If recovery is active we must swap the control blocks in
the flush_rbt as well. */
- if (buf_pool->flush_rbt != NULL) {
+ if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
buf_flush_delete_from_flush_rbt(bpage);
prev_b = buf_flush_insert_in_flush_rbt(dpage);
}
@@ -821,9 +728,9 @@ void buf_flush_write_complete(buf_page_t* bpage, bool dblwr)
/** Calculate the checksum of a page from compressed table and update
the page.
-@param[in,out] page page to update
-@param[in] size compressed page size
-@param[in] lsn LSN to stamp on the page */
+@param[in,out] page page to update
+@param[in] size compressed page size
+@param[in] lsn LSN to stamp on the page */
void
buf_flush_update_zip_checksum(
buf_frame_t* page,
@@ -840,31 +747,50 @@ buf_flush_update_zip_checksum(
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
}
+/** Assign the full crc32 checksum for non-compressed page.
+@param[in,out] page page to be updated */
+void buf_flush_assign_full_crc32_checksum(byte* page)
+{
+ ut_d(bool compressed = false);
+ ut_d(bool corrupted = false);
+ ut_d(const uint size = buf_page_full_crc32_size(page, &compressed,
+ &corrupted));
+ ut_ad(!compressed);
+ ut_ad(!corrupted);
+ ut_ad(size == uint(srv_page_size));
+ const ulint payload = srv_page_size - FIL_PAGE_FCRC32_CHECKSUM;
+ mach_write_to_4(page + payload, ut_crc32(page, payload));
+}
+
/** Initialize a page for writing to the tablespace.
-@param[in] block buffer block; NULL if bypassing the buffer pool
-@param[in,out] page page frame
-@param[in,out] page_zip_ compressed page, or NULL if uncompressed
-@param[in] newest_lsn newest modification LSN to the page */
+@param[in] block buffer block; NULL if bypassing
+ the buffer pool
+@param[in,out] page page frame
+@param[in,out] page_zip_ compressed page, or NULL if
+ uncompressed
+@param[in] newest_lsn newest modification LSN to the page
+@param[in] use_full_checksum whether tablespace uses full checksum */
void
buf_flush_init_for_writing(
const buf_block_t* block,
byte* page,
void* page_zip_,
- lsn_t newest_lsn)
+ lsn_t newest_lsn,
+ bool use_full_checksum)
{
+ if (block != NULL && block->frame != page) {
+ /* If page is encrypted in full crc32 format then
+ checksum stored already as a part of fil_encrypt_buf() */
+ ut_ad(use_full_checksum);
+ return;
+ }
+
ut_ad(block == NULL || block->frame == page);
ut_ad(block == NULL || page_zip_ == NULL
|| &block->page.zip == page_zip_);
ut_ad(!block || newest_lsn);
ut_ad(page);
-#if 0 /* MDEV-15528 TODO: reinstate this check */
- /* innodb_immediate_scrub_data_uncompressed=ON would cause
- fsp_init_file_page() to be called on freed pages, and thus
- cause them to be written as almost-all-zeroed.
- In MDEV-15528 we should change that implement an option to
- make freed pages appear all-zero, bypassing this code. */
ut_ad(!newest_lsn || fil_page_get_type(page));
-#endif
if (page_zip_) {
page_zip_des_t* page_zip;
@@ -909,8 +835,14 @@ buf_flush_init_for_writing(
/* Write the newest modification lsn to the page header and trailer */
mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn);
- mach_write_to_8(page + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM,
- newest_lsn);
+ if (use_full_checksum) {
+ mach_write_to_4(page + srv_page_size - FIL_PAGE_FCRC32_END_LSN,
+ static_cast<uint32_t>(newest_lsn));
+ return buf_flush_assign_full_crc32_checksum(page);
+ } else {
+ mach_write_to_8(page + srv_page_size - FIL_PAGE_END_LSN_OLD_CHKSUM,
+ newest_lsn);
+ }
if (block && srv_page_size == 16384) {
/* The page type could be garbage in old files
@@ -988,6 +920,8 @@ buf_flush_init_for_writing(
be calculated after storing the new formula checksum. */
checksum = buf_calc_page_old_checksum(page);
break;
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
/* In other cases we write the same checksum to both fields. */
@@ -1030,7 +964,10 @@ buf_flush_write_block_low(
|| space->purpose == FIL_TYPE_TABLESPACE);
ut_ad((space->purpose == FIL_TYPE_TEMPORARY)
== (space == fil_system.temp_space));
+
page_t* frame = NULL;
+ const bool full_crc32 = space->full_crc32();
+
#ifdef UNIV_DEBUG
buf_pool_t* buf_pool = buf_pool_from_bpage(bpage);
ut_ad(!buf_pool_mutex_own(buf_pool));
@@ -1074,7 +1011,7 @@ buf_flush_write_block_low(
mach_write_to_8(frame + FIL_PAGE_LSN,
bpage->newest_modification);
- ut_a(page_zip_verify_checksum(frame, bpage->size.physical()));
+ ut_a(page_zip_verify_checksum(frame, bpage->zip_size()));
break;
case BUF_BLOCK_FILE_PAGE:
frame = bpage->zip.data;
@@ -1082,15 +1019,23 @@ buf_flush_write_block_low(
frame = ((buf_block_t*) bpage)->frame;
}
+ byte* page = reinterpret_cast<const buf_block_t*>(bpage)->frame;
+
+ if (full_crc32) {
+ page = buf_page_encrypt(space, bpage, page);
+ frame = page;
+ }
+
buf_flush_init_for_writing(
- reinterpret_cast<const buf_block_t*>(bpage),
- reinterpret_cast<const buf_block_t*>(bpage)->frame,
+ reinterpret_cast<const buf_block_t*>(bpage), page,
bpage->zip.data ? &bpage->zip : NULL,
- bpage->newest_modification);
+ bpage->newest_modification, full_crc32);
break;
}
- frame = buf_page_encrypt_before_write(space, bpage, frame);
+ if (!full_crc32) {
+ frame = buf_page_encrypt(space, bpage, frame);
+ }
ut_ad(space->purpose == FIL_TYPE_TABLESPACE
|| space->atomic_write_supported);
@@ -1101,7 +1046,8 @@ buf_flush_write_block_low(
/* TODO: pass the tablespace to fil_io() */
fil_io(request,
- sync, bpage->id, bpage->size, 0, bpage->size.physical(),
+ sync, bpage->id, bpage->zip_size(), 0,
+ bpage->physical_size(),
frame, bpage);
} else {
ut_ad(!srv_read_only_mode);
@@ -1362,9 +1308,13 @@ buf_flush_try_neighbors(
buf_pool_t* buf_pool = buf_pool_get(page_id);
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST);
+ fil_space_t* space = fil_space_acquire_for_io(page_id.space());
+ if (!space) {
+ return 0;
+ }
if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN
- || srv_flush_neighbors == 0) {
+ || !srv_flush_neighbors || !space->is_rotational()) {
/* If there is little space or neighbor flushing is
not enabled then just flush the victim. */
low = page_id.page_no();
@@ -1419,9 +1369,8 @@ buf_flush_try_neighbors(
}
}
- const ulint space_size = fil_space_get_size(page_id.space());
- if (high > space_size) {
- high = space_size;
+ if (high > space->size) {
+ high = space->size;
}
DBUG_PRINT("ib_buf", ("flush %u:%u..%u",
@@ -1498,6 +1447,8 @@ buf_flush_try_neighbors(
buf_pool_mutex_exit(buf_pool);
}
+ space->release_for_io();
+
if (count > 1) {
MONITOR_INC_VALUE_CUMULATIVE(
MONITOR_FLUSH_NEIGHBOR_TOTAL_PAGE,
@@ -3082,7 +3033,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
" See the man page of setpriority().";
}
/* Signal that setpriority() has been attempted. */
- os_event_set(recv_sys->flush_end);
+ os_event_set(recv_sys.flush_end);
#endif /* UNIV_LINUX */
do {
@@ -3090,13 +3041,13 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
ulint n_flushed_lru = 0;
ulint n_flushed_list = 0;
- os_event_wait(recv_sys->flush_start);
+ os_event_wait(recv_sys.flush_start);
if (!recv_writer_thread_active) {
break;
}
- switch (recv_sys->flush_type) {
+ switch (recv_sys.flush_type) {
case BUF_FLUSH_LRU:
/* Flush pages from end of LRU if required */
pc_request(0, LSN_MAX);
@@ -3117,8 +3068,8 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
ut_ad(0);
}
- os_event_reset(recv_sys->flush_start);
- os_event_set(recv_sys->flush_end);
+ os_event_reset(recv_sys.flush_start);
+ os_event_set(recv_sys.flush_end);
} while (recv_writer_thread_active);
os_event_wait(buf_flush_event);
@@ -3603,7 +3554,7 @@ buf_flush_validate_low(
/* If we are in recovery mode i.e.: flush_rbt != NULL
then each block in the flush_list must also be present
in the flush_rbt. */
- if (buf_pool->flush_rbt != NULL) {
+ if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
rnode = rbt_first(buf_pool->flush_rbt);
}
@@ -3624,7 +3575,7 @@ buf_flush_validate_low(
|| buf_page_get_state(bpage) == BUF_BLOCK_REMOVE_HASH);
ut_a(om > 0);
- if (buf_pool->flush_rbt != NULL) {
+ if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
buf_page_t** prpage;
ut_a(rnode != NULL);
diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc
index 17583eb3399..f2a475e2046 100644
--- a/storage/innobase/buf/buf0lru.cc
+++ b/storage/innobase/buf/buf0lru.cc
@@ -168,7 +168,7 @@ incr_LRU_size_in_bytes(
{
ut_ad(buf_pool_mutex_own(buf_pool));
- buf_pool->stat.LRU_bytes += bpage->size.physical();
+ buf_pool->stat.LRU_bytes += bpage->physical_size();
ut_ad(buf_pool->stat.LRU_bytes <= buf_pool->curr_pool_size);
}
@@ -1393,7 +1393,7 @@ buf_LRU_remove_block(
UT_LIST_REMOVE(buf_pool->LRU, bpage);
ut_d(bpage->in_LRU_list = FALSE);
- buf_pool->stat.LRU_bytes -= bpage->size.physical();
+ buf_pool->stat.LRU_bytes -= bpage->physical_size();
buf_unzip_LRU_remove_block_if_needed(bpage);
@@ -1661,9 +1661,9 @@ func_exit:
? BUF_BLOCK_ZIP_DIRTY
: BUF_BLOCK_ZIP_PAGE;
- ut_ad(b->size.is_compressed());
+ ut_ad(b->zip_size());
- UNIV_MEM_DESC(b->zip.data, b->size.physical());
+ UNIV_MEM_DESC(b->zip.data, b->zip_size());
/* The fields in_page_hash and in_LRU_list of
the to-be-freed block descriptor should have
@@ -1742,10 +1742,6 @@ func_exit:
page_zip_set_size(&bpage->zip, 0);
- bpage->size.copy_from(page_size_t(bpage->size.logical(),
- bpage->size.logical(),
- false));
-
mutex_exit(block_mutex);
/* Prevent buf_page_get_gen() from
@@ -1785,11 +1781,11 @@ func_exit:
buf_pool->page_hash, thus inaccessible by any
other thread. */
- ut_ad(b->size.is_compressed());
+ ut_ad(b->zip_size());
const uint32_t checksum = page_zip_calc_checksum(
b->zip.data,
- b->size.physical(),
+ b->zip_size(),
static_cast<srv_checksum_algorithm_t>(
srv_checksum_algorithm));
@@ -1856,19 +1852,14 @@ buf_LRU_block_free_non_file_page(
buf_page_mutex_exit(block);
buf_pool_mutex_exit_forbid(buf_pool);
- ut_ad(block->page.size.is_compressed());
+ ut_ad(block->zip_size());
- buf_buddy_free(buf_pool, data, block->page.size.physical());
+ buf_buddy_free(buf_pool, data, block->zip_size());
buf_pool_mutex_exit_allow(buf_pool);
buf_page_mutex_enter(block);
page_zip_set_size(&block->page.zip, 0);
-
- block->page.size.copy_from(
- page_size_t(block->page.size.logical(),
- block->page.size.logical(),
- false));
}
if (buf_pool->curr_size < buf_pool->old_size
@@ -1939,7 +1930,7 @@ buf_LRU_block_remove_hashed(
const page_t* page = ((buf_block_t*) bpage)->frame;
ut_a(!zip || bpage->oldest_modification == 0);
- ut_ad(bpage->size.is_compressed());
+ ut_ad(bpage->zip_size());
switch (fil_page_get_type(page)) {
case FIL_PAGE_TYPE_ALLOCATED:
@@ -1954,7 +1945,7 @@ buf_LRU_block_remove_hashed(
to the compressed page, which will
be preserved. */
memcpy(bpage->zip.data, page,
- bpage->size.physical());
+ bpage->zip_size());
}
break;
case FIL_PAGE_TYPE_ZBLOB:
@@ -1971,14 +1962,13 @@ buf_LRU_block_remove_hashed(
default:
ib::error() << "The compressed page to be"
" evicted seems corrupt:";
- ut_print_buf(stderr, page,
- bpage->size.logical());
+ ut_print_buf(stderr, page, srv_page_size);
ib::error() << "Possibly older version of"
" the page:";
ut_print_buf(stderr, bpage->zip.data,
- bpage->size.physical());
+ bpage->zip_size());
putc('\n', stderr);
ut_error;
}
@@ -1988,10 +1978,7 @@ buf_LRU_block_remove_hashed(
/* fall through */
case BUF_BLOCK_ZIP_PAGE:
ut_a(bpage->oldest_modification == 0);
- if (bpage->size.is_compressed()) {
- UNIV_MEM_ASSERT_W(bpage->zip.data,
- bpage->size.physical());
- }
+ UNIV_MEM_ASSERT_W(bpage->zip.data, bpage->zip_size());
break;
case BUF_BLOCK_POOL_WATCH:
case BUF_BLOCK_ZIP_DIRTY:
@@ -2007,25 +1994,16 @@ buf_LRU_block_remove_hashed(
if (bpage != hashed_bpage) {
ib::error() << "Page " << bpage->id
<< " not found in the hash table";
-
-#ifdef UNIV_DEBUG
-
-
ib::error()
+#ifdef UNIV_DEBUG
<< "in_page_hash:" << bpage->in_page_hash
<< " in_zip_hash:" << bpage->in_zip_hash
- // << " in_free_list:"<< bpage->in_fee_list
<< " in_flush_list:" << bpage->in_flush_list
<< " in_LRU_list:" << bpage->in_LRU_list
+#endif
<< " zip.data:" << bpage->zip.data
- << " zip_size:" << bpage->size.logical()
- << " page_state:" << buf_page_get_state(bpage);
-#else
- ib::error()
- << " zip.data:" << bpage->zip.data
- << " zip_size:" << bpage->size.logical()
+ << " zip_size:" << bpage->zip_size()
<< " page_state:" << buf_page_get_state(bpage);
-#endif
if (hashed_bpage) {
@@ -2059,7 +2037,7 @@ buf_LRU_block_remove_hashed(
ut_ad(!bpage->in_flush_list);
ut_ad(!bpage->in_LRU_list);
ut_a(bpage->zip.data);
- ut_a(bpage->size.is_compressed());
+ ut_a(bpage->zip.ssize);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
UT_LIST_REMOVE(buf_pool->zip_clean, bpage);
@@ -2069,8 +2047,7 @@ buf_LRU_block_remove_hashed(
rw_lock_x_unlock(hash_lock);
buf_pool_mutex_exit_forbid(buf_pool);
- buf_buddy_free(buf_pool, bpage->zip.data,
- bpage->size.physical());
+ buf_buddy_free(buf_pool, bpage->zip.data, bpage->zip_size());
buf_pool_mutex_exit_allow(buf_pool);
buf_page_free_descriptor(bpage);
@@ -2117,16 +2094,11 @@ buf_LRU_block_remove_hashed(
ut_ad(!bpage->in_LRU_list);
buf_pool_mutex_exit_forbid(buf_pool);
- buf_buddy_free(buf_pool, data, bpage->size.physical());
+ buf_buddy_free(buf_pool, data, bpage->zip_size());
buf_pool_mutex_exit_allow(buf_pool);
page_zip_set_size(&bpage->zip, 0);
-
- bpage->size.copy_from(
- page_size_t(bpage->size.logical(),
- bpage->size.logical(),
- false));
}
return(true);
@@ -2185,7 +2157,7 @@ void buf_LRU_free_one_page(buf_page_t* bpage, page_id_t old_page_id)
rw_lock_x_lock(hash_lock);
- while (buf_block_get_fix(bpage) > 0) {
+ while (bpage->buf_fix_count > 0) {
/* Wait for other threads to release the fix count
before releasing the bpage from LRU list. */
}
@@ -2465,7 +2437,7 @@ buf_LRU_print_instance(
if (bpage->buf_fix_count) {
fprintf(stderr, "buffix count %u ",
- bpage->buf_fix_count);
+ uint32_t(bpage->buf_fix_count));
}
if (buf_page_get_io_fix(bpage)) {
@@ -2490,7 +2462,7 @@ buf_LRU_print_instance(
fprintf(stderr, "\ntype %u size " ULINTPF
" index id " IB_ID_FMT "\n",
fil_page_get_type(frame),
- bpage->size.physical(),
+ bpage->zip_size(),
btr_page_get_index_id(frame));
break;
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index 7877087dd4a..33ccd6688ae 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -96,15 +96,14 @@ buffer buf_pool if it is not already there, in which case does nothing.
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
flag is cleared and the x-lock released by an i/o-handler thread.
-@param[out] err DB_SUCCESS, DB_TABLESPACE_DELETED or
- DB_TABLESPACE_TRUNCATED if we are trying
- to read from a non-existent tablespace, a
- tablespace which is just now being dropped,
- or a tablespace which is truncated
+@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED
+ if we are trying
+ to read from a non-existent tablespace
@param[in] sync true if synchronous aio is desired
@param[in] type IO type, SIMULATED, IGNORE_MISSING
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...,
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] unzip true=request uncompressed page
@param[in] ignore_missing_space true=ignore missing space when reading
@return 1 if a read request was queued, 0 if the page already resided
@@ -119,7 +118,7 @@ buf_read_page_low(
ulint type,
ulint mode,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
bool unzip,
bool ignore_missing_space = false)
{
@@ -135,7 +134,7 @@ buf_read_page_low(
return(0);
}
- if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
+ if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) {
/* Trx sys header is so low in the latching order that we play
safe and do not leave the i/o-completion to an asynchronous
@@ -150,7 +149,7 @@ buf_read_page_low(
or is being dropped; if we succeed in initing the page in the buffer
pool for read, then DISCARD cannot proceed until the read has
completed */
- bpage = buf_page_init_for_read(err, mode, page_id, page_size, unzip);
+ bpage = buf_page_init_for_read(err, mode, page_id, zip_size, unzip);
if (bpage == NULL) {
@@ -158,7 +157,7 @@ buf_read_page_low(
}
DBUG_LOG("ib_buf",
- "read page " << page_id << " size=" << page_size.physical()
+ "read page " << page_id << " zip_size=" << zip_size
<< " unzip=" << unzip << ',' << (sync ? "sync" : "async"));
ut_ad(buf_page_in_file(bpage));
@@ -169,7 +168,7 @@ buf_read_page_low(
void* dst;
- if (page_size.is_compressed()) {
+ if (zip_size) {
dst = bpage->zip.data;
} else {
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
@@ -180,7 +179,8 @@ buf_read_page_low(
IORequest request(type | IORequest::READ);
*err = fil_io(
- request, sync, page_id, page_size, 0, page_size.physical(),
+ request, sync, page_id, zip_size, 0,
+ zip_size ? zip_size : srv_page_size,
dst, bpage, ignore_missing_space);
if (sync) {
@@ -188,20 +188,8 @@ buf_read_page_low(
}
if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
- if (*err == DB_TABLESPACE_TRUNCATED) {
- /* Remove the page which is outside the
- truncated tablespace bounds when recovering
- from a crash happened during a truncation */
- buf_read_page_handle_error(bpage);
- if (recv_recovery_is_on()) {
- mutex_enter(&recv_sys->mutex);
- ut_ad(recv_sys->n_addrs > 0);
- recv_sys->n_addrs--;
- mutex_exit(&recv_sys->mutex);
- }
- return(0);
- } else if (IORequest::ignore_missing(type)
- || *err == DB_TABLESPACE_DELETED) {
+ if (IORequest::ignore_missing(type)
+ || *err == DB_TABLESPACE_DELETED) {
buf_read_page_handle_error(bpage);
return(0);
}
@@ -233,16 +221,13 @@ performed by ibuf routines, a situation which could result in a deadlock if
the OS does not support asynchronous i/o.
@param[in] page_id page id of a page which the current thread
wants to access
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether we are inside ibuf routine
@return number of page read requests issued; NOTE that if we read ibuf
pages, it may happen that the page at the given page number does not
get read even if we return a positive value! */
ulint
-buf_read_ahead_random(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf)
+buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf)
{
buf_pool_t* buf_pool = buf_pool_get(page_id);
ulint recent_blocks = 0;
@@ -264,7 +249,7 @@ buf_read_ahead_random(
return(0);
}
- if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
+ if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
@@ -279,14 +264,14 @@ buf_read_ahead_random(
high = (page_id.page_no() / buf_read_ahead_random_area + 1)
* buf_read_ahead_random_area;
- /* Remember the tablespace version before we ask the tablespace size
- below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
+ /* If DISCARD + IMPORT changes the actual .ibd file meanwhile, we
do not try to read outside the bounds of the tablespace! */
if (fil_space_t* space = fil_space_acquire(page_id.space())) {
#ifdef UNIV_DEBUG
if (srv_file_per_table) {
ulint size = 0;
+ const ulint physical_size = space->physical_size();
for (const fil_node_t* node =
UT_LIST_GET_FIRST(space->chain);
@@ -294,7 +279,7 @@ buf_read_ahead_random(
node = UT_LIST_GET_NEXT(chain, node)) {
size += ulint(os_file_get_size(node->handle)
- / page_size.physical());
+ / physical_size);
}
ut_ad(size == space->size);
@@ -347,12 +332,7 @@ buf_read_ahead_random(
read_ahead:
/* Read all the suitable blocks within the area */
- if (inside_ibuf) {
- ibuf_mode = BUF_READ_IBUF_PAGES_ONLY;
- } else {
- ibuf_mode = BUF_READ_ANY_PAGE;
- }
-
+ ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
count = 0;
for (i = low; i < high; i++) {
@@ -361,16 +341,15 @@ read_ahead:
const page_id_t cur_page_id(page_id.space(), i);
- if (!ibuf_bitmap_page(cur_page_id, page_size)) {
+ if (!ibuf_bitmap_page(cur_page_id, zip_size)) {
count += buf_read_page_low(
&err, false,
IORequest::DO_NOT_WAKE,
ibuf_mode,
- cur_page_id, page_size, false);
+ cur_page_id, zip_size, false);
switch (err) {
case DB_SUCCESS:
- case DB_TABLESPACE_TRUNCATED:
case DB_ERROR:
break;
case DB_TABLESPACE_DELETED:
@@ -412,16 +391,13 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@retval DB_SUCCESS if the page was read and is not corrupted,
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted,
@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but
after decryption normal page checksum does not match.
@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */
-dberr_t
-buf_read_page(
- const page_id_t page_id,
- const page_size_t& page_size)
+dberr_t buf_read_page(const page_id_t page_id, ulint zip_size)
{
ulint count;
dberr_t err = DB_SUCCESS;
@@ -434,7 +410,7 @@ buf_read_page(
count = buf_read_page_low(
&err, true,
- 0, BUF_READ_ANY_PAGE, page_id, page_size, false);
+ 0, BUF_READ_ANY_PAGE, page_id, zip_size, false);
srv_stats.buf_pool_reads.add(count);
@@ -454,13 +430,10 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] sync true if synchronous aio is desired */
void
-buf_read_page_background(
- const page_id_t page_id,
- const page_size_t& page_size,
- bool sync)
+buf_read_page_background(const page_id_t page_id, ulint zip_size, bool sync)
{
ulint count;
dberr_t err;
@@ -469,11 +442,10 @@ buf_read_page_background(
&err, sync,
IORequest::DO_NOT_WAKE | IORequest::IGNORE_MISSING,
BUF_READ_ANY_PAGE,
- page_id, page_size, false);
+ page_id, zip_size, false);
switch (err) {
case DB_SUCCESS:
- case DB_TABLESPACE_TRUNCATED:
case DB_ERROR:
break;
case DB_TABLESPACE_DELETED:
@@ -525,14 +497,11 @@ NOTE 3: the calling thread must want access to the page given: this rule is
set to prevent unintended read-aheads performed by ibuf routines, a situation
which could result in a deadlock if the OS does not support asynchronous io.
@param[in] page_id page id; see NOTE 3 above
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether if we are inside ibuf routine
@return number of page read requests issued */
ulint
-buf_read_ahead_linear(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf)
+buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf)
{
buf_pool_t* buf_pool = buf_pool_get(page_id);
buf_page_t* bpage;
@@ -571,7 +540,7 @@ buf_read_ahead_linear(
return(0);
}
- if (ibuf_bitmap_page(page_id, page_size) || trx_sys_hdr_page(page_id)) {
+ if (ibuf_bitmap_page(page_id, zip_size) || trx_sys_hdr_page(page_id)) {
/* If it is an ibuf bitmap page or trx sys hdr, we do
no read-ahead, as that could break the ibuf page access
@@ -732,9 +701,7 @@ buf_read_ahead_linear(
/* If we got this far, read-ahead can be sensible: do it */
- ulint ibuf_mode;
-
- ibuf_mode = inside_ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
+ ulint ibuf_mode = ibuf ? BUF_READ_IBUF_PAGES_ONLY : BUF_READ_ANY_PAGE;
/* Since Windows XP seems to schedule the i/o handler thread
very eagerly, and consequently it does not wait for the
@@ -748,15 +715,14 @@ buf_read_ahead_linear(
const page_id_t cur_page_id(page_id.space(), i);
- if (!ibuf_bitmap_page(cur_page_id, page_size)) {
+ if (!ibuf_bitmap_page(cur_page_id, zip_size)) {
count += buf_read_page_low(
&err, false,
IORequest::DO_NOT_WAKE,
- ibuf_mode, cur_page_id, page_size, false);
+ ibuf_mode, cur_page_id, zip_size, false);
switch (err) {
case DB_SUCCESS:
- case DB_TABLESPACE_TRUNCATED:
case DB_TABLESPACE_DELETED:
case DB_ERROR:
break;
@@ -860,11 +826,11 @@ next:
sync && (i + 1 == n_stored),
0,
BUF_READ_ANY_PAGE, page_id,
- page_size_t(space->flags), true);
+ space->zip_size(),
+ true, true /* ignore_missing_space */);
switch(err) {
case DB_SUCCESS:
- case DB_TABLESPACE_TRUNCATED:
case DB_ERROR:
break;
case DB_TABLESPACE_DELETED:
@@ -916,7 +882,7 @@ buf_read_recv_pages(
fil_space_open_if_needed(space);
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
for (ulint i = 0; i < n_stored; i++) {
buf_pool_t* buf_pool;
@@ -953,13 +919,13 @@ buf_read_recv_pages(
&err, true,
0,
BUF_READ_ANY_PAGE,
- cur_page_id, page_size, true);
+ cur_page_id, zip_size, true);
} else {
buf_read_page_low(
&err, false,
IORequest::DO_NOT_WAKE,
BUF_READ_ANY_PAGE,
- cur_page_id, page_size, true);
+ cur_page_id, zip_size, true);
}
if (err == DB_DECRYPTION_FAILED || err == DB_PAGE_CORRUPTED) {
diff --git a/storage/innobase/data/data0data.cc b/storage/innobase/data/data0data.cc
index b8ced460e58..7cc9c2bc09e 100644
--- a/storage/innobase/data/data0data.cc
+++ b/storage/innobase/data/data0data.cc
@@ -58,7 +58,12 @@ void dtuple_t::trim(const dict_index_t& index)
for (; i > index.n_core_fields; i--) {
const dfield_t* dfield = dtuple_get_nth_field(this, i - 1);
const dict_col_t* col = dict_index_get_nth_col(&index, i - 1);
- ut_ad(col->is_instant());
+
+ if (col->is_dropped()) {
+ continue;
+ }
+
+ ut_ad(col->is_added());
ulint len = dfield_get_len(dfield);
if (len != col->def_val.len) {
break;
@@ -594,7 +599,6 @@ dtuple_convert_big_rec(
mem_heap_t* heap;
big_rec_t* vector;
dfield_t* dfield;
- dict_field_t* ifield;
ulint size;
ulint n_fields;
ulint local_prefix_len;
@@ -603,7 +607,14 @@ dtuple_convert_big_rec(
return(NULL);
}
- const ulint local_len = index->table->get_overflow_field_local_len();
+ if (!index->table->space) {
+ return NULL;
+ }
+
+ ulint local_len = index->table->get_overflow_field_local_len();
+ const auto zip_size = index->table->space->zip_size();
+
+ ut_ad(index->n_uniq > 0);
ut_a(dtuple_check_typed_no_assert(entry));
@@ -626,24 +637,42 @@ dtuple_convert_big_rec(
stored externally */
n_fields = 0;
+ ulint longest_i;
+
+ const bool mblob = entry->is_alter_metadata();
+ ut_ad(entry->n_fields >= index->first_user_field() + mblob);
+ ut_ad(entry->n_fields - mblob <= index->n_fields);
+
+ if (mblob) {
+ longest_i = index->first_user_field();
+ dfield = dtuple_get_nth_field(entry, longest_i);
+ local_len = BTR_EXTERN_FIELD_REF_SIZE;
+ ut_ad(!dfield_is_ext(dfield));
+ goto ext_write;
+ }
+
+ if (!dict_table_has_atomic_blobs(index->table)) {
+ /* up to MySQL 5.1: store a 768-byte prefix locally */
+ local_len = BTR_EXTERN_FIELD_REF_SIZE
+ + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
+ } else {
+ /* new-format table: do not store any BLOB prefix locally */
+ local_len = BTR_EXTERN_FIELD_REF_SIZE;
+ }
while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry,
*n_ext),
- dict_table_is_comp(index->table),
+ index->table->not_redundant(),
dict_index_get_n_fields(index),
- dict_table_page_size(index->table))) {
-
- ulint i;
- ulint longest = 0;
- ulint longest_i = ULINT_MAX;
- byte* data;
-
- for (i = dict_index_get_n_unique_in_tree(index);
- i < dtuple_get_n_fields(entry); i++) {
+ zip_size)) {
+ longest_i = 0;
+ for (ulint i = index->first_user_field(), longest = 0;
+ i + mblob < entry->n_fields; i++) {
ulint savings;
+ dfield = dtuple_get_nth_field(entry, i + mblob);
- dfield = dtuple_get_nth_field(entry, i);
- ifield = dict_index_get_nth_field(index, i);
+ const dict_field_t* ifield = dict_index_get_nth_field(
+ index, i);
/* Skip fixed-length, NULL, externally stored,
or short columns */
@@ -685,7 +714,7 @@ skip_field:
continue;
}
- if (!longest) {
+ if (!longest_i) {
/* Cannot shorten more */
mem_heap_free(heap);
@@ -698,9 +727,8 @@ skip_field:
We store the first bytes locally to the record. Then
we can calculate all ordering fields in all indexes
from locally stored data. */
-
dfield = dtuple_get_nth_field(entry, longest_i);
- ifield = dict_index_get_nth_field(index, longest_i);
+ext_write:
local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE;
vector->append(
@@ -711,7 +739,8 @@ skip_field:
+ local_prefix_len));
/* Allocate the locally stored part of the column. */
- data = static_cast<byte*>(mem_heap_alloc(heap, local_len));
+ byte* data = static_cast<byte*>(
+ mem_heap_alloc(heap, local_len));
/* Copy the local prefix. */
memcpy(data, dfield_get_data(dfield), local_prefix_len);
@@ -725,7 +754,6 @@ skip_field:
UNIV_MEM_ALLOC(data + local_prefix_len,
BTR_EXTERN_FIELD_REF_SIZE);
#endif
-
dfield_set_data(dfield, data, local_len);
dfield_set_ext(dfield);
diff --git a/storage/innobase/data/data0type.cc b/storage/innobase/data/data0type.cc
index 896d1240340..7de4cc026d1 100644
--- a/storage/innobase/data/data0type.cc
+++ b/storage/innobase/data/data0type.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, 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
@@ -24,7 +24,8 @@ Data types
Created 1/16/1996 Heikki Tuuri
*******************************************************/
-#include "data0type.h"
+#include "dict0mem.h"
+#include "my_sys.h"
/** The DB_TRX_ID,DB_ROLL_PTR values for "no history is available" */
const byte reset_trx_id[DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN] = {
@@ -79,67 +80,6 @@ dtype_get_at_most_n_mbchars(
}
/*********************************************************************//**
-Checks if a data main type is a string type. Also a BLOB is considered a
-string type.
-@return TRUE if string type */
-ibool
-dtype_is_string_type(
-/*=================*/
- ulint mtype) /*!< in: InnoDB main data type code: DATA_CHAR, ... */
-{
- if (mtype <= DATA_BLOB
- || mtype == DATA_MYSQL
- || mtype == DATA_VARMYSQL) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*********************************************************************//**
-Checks if a type is a binary string type. Note that for tables created with
-< 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. For
-those DATA_BLOB columns this function currently returns FALSE.
-@return TRUE if binary string type */
-ibool
-dtype_is_binary_string_type(
-/*========================*/
- ulint mtype, /*!< in: main data type */
- ulint prtype) /*!< in: precise type */
-{
- if ((mtype == DATA_FIXBINARY)
- || (mtype == DATA_BINARY)
- || (mtype == DATA_BLOB && (prtype & DATA_BINARY_TYPE))) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*********************************************************************//**
-Checks if a type is a non-binary string type. That is, dtype_is_string_type is
-TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created
-with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column.
-For those DATA_BLOB columns this function currently returns TRUE.
-@return TRUE if non-binary string type */
-ibool
-dtype_is_non_binary_string_type(
-/*============================*/
- ulint mtype, /*!< in: main data type */
- ulint prtype) /*!< in: precise type */
-{
- if (dtype_is_string_type(mtype) == TRUE
- && dtype_is_binary_string_type(mtype, prtype) == FALSE) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*********************************************************************//**
Validates a data type structure.
@return TRUE if ok */
ibool
diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc
index 87a2fe3f03f..0055ca6ef17 100644
--- a/storage/innobase/dict/dict0boot.cc
+++ b/storage/innobase/dict/dict0boot.cc
@@ -47,7 +47,7 @@ dict_hdr_get(
dict_hdr_t* header;
block = buf_page_get(page_id_t(DICT_HDR_SPACE, DICT_HDR_PAGE_NO),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
header = DICT_HDR + buf_block_get_frame(block);
buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
@@ -64,52 +64,14 @@ dict_hdr_get_new_id(
(not assigned if NULL) */
index_id_t* index_id, /*!< out: index id
(not assigned if NULL) */
- ulint* space_id, /*!< out: space id
+ ulint* space_id) /*!< out: space id
(not assigned if NULL) */
- const dict_table_t* table, /*!< in: table */
- bool disable_redo) /*!< in: if true and table
- object is NULL
- then disable-redo */
{
dict_hdr_t* dict_hdr;
ib_id_t id;
mtr_t mtr;
mtr_start(&mtr);
- if (table) {
- if (table->is_temporary()) {
- mtr.set_log_mode(MTR_LOG_NO_REDO);
- }
- } else if (disable_redo) {
- /* In non-read-only mode we need to ensure that space-id header
- page is written to disk else if page is removed from buffer
- cache and re-loaded it would assign temporary tablespace id
- to another tablespace.
- This is not a case with read-only mode as there is no new object
- that is created except temporary tablespace. */
- mtr.set_log_mode(srv_read_only_mode
- ? MTR_LOG_NONE : MTR_LOG_NO_REDO);
- }
-
- /* Server started and let's say space-id = x
- - table created with file-per-table
- - space-id = x + 1
- - crash
- Case 1: If it was redo logged then we know that it will be
- restored to x + 1
- Case 2: if not redo-logged
- Header will have the old space-id = x
- This is OK because on restart there is no object with
- space id = x + 1
- Case 3:
- space-id = x (on start)
- space-id = x+1 (temp-table allocation) - no redo logging
- space-id = x+2 (non-temp-table allocation), this get's
- redo logged.
- If there is a crash there will be only 2 entries
- x (original) and x+2 (new) and disk hdr will be updated
- to reflect x + 2 entry.
- We cannot allocate the same space id to different objects. */
dict_hdr = dict_hdr_get(&mtr);
if (table_id) {
@@ -148,9 +110,9 @@ dict_hdr_flush_row_id(void)
row_id_t id;
mtr_t mtr;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
- id = dict_sys->row_id;
+ id = dict_sys.row_id;
mtr_start(&mtr);
@@ -210,7 +172,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_TABLES_ID,
- dict_ind_redundant, NULL, mtr);
+ dict_ind_redundant, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -221,7 +183,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE,
fil_system.sys_space, DICT_TABLE_IDS_ID,
- dict_ind_redundant, NULL, mtr);
+ dict_ind_redundant, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -232,7 +194,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_COLUMNS_ID,
- dict_ind_redundant, NULL, mtr);
+ dict_ind_redundant, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -243,7 +205,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_INDEXES_ID,
- dict_ind_redundant, NULL, mtr);
+ dict_ind_redundant, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -254,7 +216,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
fil_system.sys_space, DICT_FIELDS_ID,
- dict_ind_redundant, NULL, mtr);
+ dict_ind_redundant, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -302,11 +264,11 @@ dict_boot(void)
mtr_start(&mtr);
/* Create the hash tables etc. */
- dict_init();
+ dict_sys.create();
heap = mem_heap_create(450);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
/* Get the dictionary header */
dict_hdr = dict_hdr_get(&mtr);
@@ -321,7 +283,7 @@ dict_boot(void)
..._MARGIN, it will immediately be updated to the disk-based
header. */
- dict_sys->row_id = DICT_HDR_ROW_ID_WRITE_MARGIN
+ dict_sys.row_id = DICT_HDR_ROW_ID_WRITE_MARGIN
+ ut_uint64_align_up(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID),
DICT_HDR_ROW_ID_WRITE_MARGIN);
@@ -350,7 +312,7 @@ dict_boot(void)
dict_table_add_system_columns(table, heap);
table->add_to_cache();
- dict_sys->sys_tables = table;
+ dict_sys.sys_tables = table;
mem_heap_empty(heap);
index = dict_mem_index_create(table, "CLUST_IND",
@@ -391,7 +353,7 @@ dict_boot(void)
dict_table_add_system_columns(table, heap);
table->add_to_cache();
- dict_sys->sys_columns = table;
+ dict_sys.sys_columns = table;
mem_heap_empty(heap);
index = dict_mem_index_create(table, "CLUST_IND",
@@ -434,7 +396,7 @@ dict_boot(void)
dict_table_get_nth_col(table, DICT_COL__SYS_INDEXES__MERGE_THRESHOLD)
->def_val.len = UNIV_SQL_NULL;
table->add_to_cache();
- dict_sys->sys_indexes = table;
+ dict_sys.sys_indexes = table;
mem_heap_empty(heap);
index = dict_mem_index_create(table, "CLUST_IND",
@@ -463,7 +425,7 @@ dict_boot(void)
dict_table_add_system_columns(table, heap);
table->add_to_cache();
- dict_sys->sys_fields = table;
+ dict_sys.sys_fields = table;
mem_heap_free(heap);
index = dict_mem_index_create(table, "CLUST_IND",
@@ -511,14 +473,14 @@ dict_boot(void)
if (err == DB_SUCCESS) {
/* Load definitions of other indexes on system tables */
- dict_load_sys_table(dict_sys->sys_tables);
- dict_load_sys_table(dict_sys->sys_columns);
- dict_load_sys_table(dict_sys->sys_indexes);
- dict_load_sys_table(dict_sys->sys_fields);
+ dict_load_sys_table(dict_sys.sys_tables);
+ dict_load_sys_table(dict_sys.sys_columns);
+ dict_load_sys_table(dict_sys.sys_indexes);
+ dict_load_sys_table(dict_sys.sys_fields);
}
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return(err);
}
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 581be6a85c1..aa7913b3cbe 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -56,7 +56,6 @@ dict_create_sys_tables_tuple(
which the memory for the built
tuple is allocated */
{
- dict_table_t* sys_tables;
dtuple_t* entry;
dfield_t* dfield;
byte* ptr;
@@ -67,11 +66,9 @@ dict_create_sys_tables_tuple(
ut_ad(heap);
ut_ad(table->n_cols >= DATA_N_SYS_COLS);
- sys_tables = dict_sys->sys_tables;
-
entry = dtuple_create(heap, 8 + DATA_N_SYS_COLS);
- dict_table_copy_types(entry, sys_tables);
+ dict_table_copy_types(entry, dict_sys.sys_tables);
/* 0: NAME -----------------------------*/
dfield = dtuple_get_nth_field(
@@ -169,7 +166,6 @@ dict_create_sys_columns_tuple(
which the memory for the built
tuple is allocated */
{
- dict_table_t* sys_columns;
dtuple_t* entry;
const dict_col_t* column;
dfield_t* dfield;
@@ -193,11 +189,9 @@ dict_create_sys_columns_tuple(
ut_ad(!column->is_virtual());
}
- sys_columns = dict_sys->sys_columns;
-
entry = dtuple_create(heap, 7 + DATA_N_SYS_COLS);
- dict_table_copy_types(entry, sys_columns);
+ dict_table_copy_types(entry, dict_sys.sys_columns);
/* 0: TABLE_ID -----------------------*/
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_COLUMNS__TABLE_ID);
@@ -288,7 +282,6 @@ dict_create_sys_virtual_tuple(
ulint b_col_n,
mem_heap_t* heap)
{
- dict_table_t* sys_virtual;
dtuple_t* entry;
const dict_col_t* base_column;
dfield_t* dfield;
@@ -301,12 +294,10 @@ dict_create_sys_virtual_tuple(
dict_v_col_t* v_col = dict_table_get_nth_v_col(table, v_col_n);
base_column = v_col->base_col[b_col_n];
- sys_virtual = dict_sys->sys_virtual;
-
entry = dtuple_create(heap, DICT_NUM_COLS__SYS_VIRTUAL
+ DATA_N_SYS_COLS);
- dict_table_copy_types(entry, sys_virtual);
+ dict_table_copy_types(entry, dict_sys.sys_virtual);
/* 0: TABLE_ID -----------------------*/
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_VIRTUAL__TABLE_ID);
@@ -350,12 +341,14 @@ dict_build_table_def_step(
que_thr_t* thr, /*!< in: query thread */
tab_node_t* node) /*!< in: table create node */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
dict_table_t* table = node->table;
+ trx_t* trx = thr_get_trx(thr);
ut_ad(!table->is_temporary());
ut_ad(!table->space);
ut_ad(table->space_id == ULINT_UNDEFINED);
- dict_table_assign_new_id(table, thr_get_trx(thr));
+ dict_hdr_get_new_id(&table->id, NULL, NULL);
+ trx->table_id = table->id;
/* Always set this bit for all new created tables */
DICT_TF2_FLAG_SET(table, DICT_TF2_FTS_AUX_HEX_NAME);
@@ -368,8 +361,6 @@ dict_build_table_def_step(
ut_ad(DICT_TF_GET_ZIP_SSIZE(table->flags) == 0
|| dict_table_has_atomic_blobs(table));
- trx_t* trx = thr_get_trx(thr);
- ut_ad(trx->table_id);
mtr_t mtr;
trx_undo_t* undo = trx->rsegs.m_redo.undo;
if (undo && !undo->table_id
@@ -397,7 +388,7 @@ dict_build_table_def_step(
}
/* Get a new tablespace ID */
ulint space_id;
- dict_hdr_get_new_id(NULL, NULL, &space_id, table, false);
+ dict_hdr_get_new_id(NULL, NULL, &space_id);
DBUG_EXECUTE_IF(
"ib_create_table_fail_out_of_space_ids",
@@ -484,24 +475,21 @@ dict_create_sys_indexes_tuple(
which the memory for the built
tuple is allocated */
{
- dict_table_t* sys_indexes;
dtuple_t* entry;
dfield_t* dfield;
byte* ptr;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(index);
ut_ad(index->table->space || index->table->file_unreadable);
ut_ad(!index->table->space
|| index->table->space->id == index->table->space_id);
ut_ad(heap);
- sys_indexes = dict_sys->sys_indexes;
-
entry = dtuple_create(
heap, DICT_NUM_COLS__SYS_INDEXES + DATA_N_SYS_COLS);
- dict_table_copy_types(entry, sys_indexes);
+ dict_table_copy_types(entry, dict_sys.sys_indexes);
/* 0: TABLE_ID -----------------------*/
dfield = dtuple_get_nth_field(
@@ -605,7 +593,6 @@ dict_create_sys_fields_tuple(
which the memory for the built
tuple is allocated */
{
- dict_table_t* sys_fields;
dtuple_t* entry;
dict_field_t* field;
dfield_t* dfield;
@@ -625,11 +612,9 @@ dict_create_sys_fields_tuple(
field = dict_index_get_nth_field(index, fld_no);
- sys_fields = dict_sys->sys_fields;
-
entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
- dict_table_copy_types(entry, sys_fields);
+ dict_table_copy_types(entry, dict_sys.sys_fields);
/* 0: INDEX_ID -----------------------*/
dfield = dtuple_get_nth_field(entry, DICT_COL__SYS_FIELDS__INDEX_ID);
@@ -724,7 +709,7 @@ dict_build_index_def_step(
dtuple_t* row;
trx_t* trx;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
trx = thr_get_trx(thr);
@@ -745,7 +730,7 @@ dict_build_index_def_step(
ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
|| dict_index_is_clust(index));
- dict_hdr_get_new_id(NULL, &index->id, NULL, table, false);
+ dict_hdr_get_new_id(NULL, &index->id, NULL);
/* Inherit the space id from the table; we store all indexes of a
table in the same tablespace */
@@ -775,7 +760,7 @@ dict_build_index_def(
dict_index_t* index, /*!< in/out: index */
trx_t* trx) /*!< in/out: InnoDB transaction handle */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (trx->table_id == 0) {
/* Record only the first table id. */
@@ -785,7 +770,7 @@ dict_build_index_def(
ut_ad((UT_LIST_GET_LEN(table->indexes) > 0)
|| dict_index_is_clust(index));
- dict_hdr_get_new_id(NULL, &index->id, NULL, table, false);
+ dict_hdr_get_new_id(NULL, &index->id, NULL);
/* Note that the index was created by this transaction. */
index->trx_id = trx->id;
@@ -821,15 +806,12 @@ dict_create_index_tree_step(
mtr_t mtr;
btr_pcur_t pcur;
dict_index_t* index;
- dict_table_t* sys_indexes;
dtuple_t* search_tuple;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
index = node->index;
- sys_indexes = dict_sys->sys_indexes;
-
if (index->type == DICT_FTS) {
/* FTS index does not need an index tree */
return(DB_SUCCESS);
@@ -843,7 +825,7 @@ dict_create_index_tree_step(
search_tuple = dict_create_search_tuple(node->ind_row, node->heap);
- btr_pcur_open(UT_LIST_GET_FIRST(sys_indexes->indexes),
+ btr_pcur_open(UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes),
search_tuple, PAGE_CUR_L, BTR_MODIFY_LEAF,
&pcur, &mtr);
@@ -859,7 +841,7 @@ dict_create_index_tree_step(
node->page_no = btr_create(
index->type, index->table->space,
- index->id, index, NULL, &mtr);
+ index->id, index, &mtr);
if (node->page_no == FIL_NULL) {
err = DB_OUT_OF_FILE_SPACE;
@@ -896,7 +878,7 @@ dict_create_index_tree_in_mem(
{
mtr_t mtr;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(!(index->type & DICT_FTS));
mtr_start(&mtr);
@@ -908,7 +890,7 @@ dict_create_index_tree_in_mem(
ut_ad(!(index->table->flags2 & DICT_TF2_DISCARDED));
index->page = btr_create(index->type, index->table->space,
- index->id, index, NULL, &mtr);
+ index->id, index, &mtr);
mtr_commit(&mtr);
index->trx_id = trx->id;
@@ -920,16 +902,14 @@ dict_create_index_tree_in_mem(
@param[in,out] rec SYS_INDEXES record
@param[in,out] pcur persistent cursor on rec
@param[in,out] trx dictionary transaction
-@param[in,out] mtr mini-transaction
-@return whether freeing the B-tree was attempted */
-bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
+@param[in,out] mtr mini-transaction */
+void dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
{
- const byte* ptr;
- ulint len;
- ulint root_page_no;
+ byte* ptr;
+ ulint len;
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
+ ut_ad(mutex_own(&dict_sys.mutex));
+ ut_a(!dict_table_is_comp(dict_sys.sys_indexes));
ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
@@ -937,15 +917,15 @@ bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
btr_pcur_store_position(pcur, mtr);
- root_page_no = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
+ const uint32_t root_page_no = mach_read_from_4(ptr);
if (root_page_no == FIL_NULL) {
/* The tree has already been freed */
-
- return(false);
+ return;
}
- mlog_write_ulint(const_cast<byte*>(ptr), FIL_NULL, MLOG_4BYTES, mtr);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mlog_memset(ptr, 4, 0xff, mtr);
ptr = rec_get_nth_field_old(
rec, DICT_FLD__SYS_INDEXES__SPACE, &len);
@@ -958,7 +938,7 @@ bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
&& trx_get_dict_operation(trx) == TRX_DICT_OP_TABLE) {
/* We are about to delete the entire .ibd file;
do not bother to free pages inside it. */
- return false;
+ return;
}
ptr = rec_get_nth_field_old(
@@ -966,109 +946,16 @@ bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
ut_ad(len == 8);
- bool found;
- const page_size_t page_size(fil_space_get_page_size(space_id,
- &found));
-
- if (!found) {
- /* It is a single table tablespace and the .ibd file is
- missing: do nothing */
-
- return(false);
- }
-
- /* If tablespace is scheduled for truncate, do not try to drop
- the indexes in that tablespace. There is a truncate fixup action
- which will take care of it. */
- if (srv_is_tablespace_truncated(space_id)) {
- return(false);
- }
-
- btr_free_if_exists(page_id_t(space_id, root_page_no), page_size,
- mach_read_from_8(ptr), mtr);
-
- return(true);
-}
-
-/*******************************************************************//**
-Recreate the index tree associated with a row in SYS_INDEXES table.
-@return new root page number, or FIL_NULL on failure */
-ulint
-dict_recreate_index_tree(
-/*=====================*/
- const dict_table_t*
- table, /*!< in/out: the table the index belongs to */
- btr_pcur_t* pcur, /*!< in/out: persistent cursor pointing to
- record in the clustered index of
- SYS_INDEXES table. The cursor may be
- repositioned in this call. */
- mtr_t* mtr) /*!< in/out: mtr having the latch
- on the record page. */
-{
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_a(!dict_table_is_comp(dict_sys->sys_indexes));
- ut_ad(!table->space || table->space->id == table->space_id);
-
- ulint len;
- const rec_t* rec = btr_pcur_get_rec(pcur);
-
- const byte* ptr = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_INDEXES__PAGE_NO, &len);
-
- ut_ad(len == 4);
-
- ut_ad(table->space_id == mach_read_from_4(
- rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__SPACE,
- &len)));
- ut_ad(len == 4);
-
- if (!table->space) {
- /* It is a single table tablespae and the .ibd file is
- missing: do nothing. */
-
- ib::warn()
- << "Trying to TRUNCATE a missing .ibd file of table "
- << table->name << "!";
-
- return(FIL_NULL);
- }
-
- ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__TYPE, &len);
- ut_ad(len == 4);
- ulint type = mach_read_from_4(ptr);
-
- ptr = rec_get_nth_field_old(rec, DICT_FLD__SYS_INDEXES__ID, &len);
- ut_ad(len == 8);
- index_id_t index_id = mach_read_from_8(ptr);
-
- /* We will need to commit the mini-transaction in order to avoid
- deadlocks in the btr_create() call, because otherwise we would
- be freeing and allocating pages in the same mini-transaction. */
- btr_pcur_store_position(pcur, mtr);
- mtr_commit(mtr);
-
- mtr_start(mtr);
- mtr->set_named_space(table->space);
- btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, mtr);
-
- /* Find the index corresponding to this SYS_INDEXES record. */
- for (dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
- index != NULL;
- index = UT_LIST_GET_NEXT(indexes, index)) {
- if (index->id == index_id) {
- ulint root_page_no = (index->type & DICT_FTS)
- ? FIL_NULL
- : btr_create(type, table->space,
- index_id, index, NULL, mtr);
- index->page = unsigned(root_page_no);
- return root_page_no;
+ if (fil_space_t* s = fil_space_acquire_silent(space_id)) {
+ /* Ensure that the tablespace file exists
+ in order to avoid a crash in buf_page_get_gen(). */
+ if (s->size || fil_space_get_size(space_id)) {
+ btr_free_if_exists(page_id_t(space_id, root_page_no),
+ s->zip_size(),
+ mach_read_from_8(ptr), mtr);
}
+ s->release();
}
-
- ib::error() << "Failed to create index with index id " << index_id
- << " of table " << table->name;
-
- return(FIL_NULL);
}
/*********************************************************************//**
@@ -1097,15 +984,15 @@ tab_create_graph_create(
node->mode = mode;
node->key_id = key_id;
- node->tab_def = ins_node_create(INS_DIRECT, dict_sys->sys_tables,
+ node->tab_def = ins_node_create(INS_DIRECT, dict_sys.sys_tables,
heap);
node->tab_def->common.parent = node;
- node->col_def = ins_node_create(INS_DIRECT, dict_sys->sys_columns,
+ node->col_def = ins_node_create(INS_DIRECT, dict_sys.sys_columns,
heap);
node->col_def->common.parent = node;
- node->v_col_def = ins_node_create(INS_DIRECT, dict_sys->sys_virtual,
+ node->v_col_def = ins_node_create(INS_DIRECT, dict_sys.sys_virtual,
heap);
node->v_col_def->common.parent = node;
@@ -1144,11 +1031,11 @@ ind_create_graph_create(
node->heap = mem_heap_create(256);
node->ind_def = ins_node_create(INS_DIRECT,
- dict_sys->sys_indexes, heap);
+ dict_sys.sys_indexes, heap);
node->ind_def->common.parent = node;
node->field_def = ins_node_create(INS_DIRECT,
- dict_sys->sys_fields, heap);
+ dict_sys.sys_fields, heap);
node->field_def->common.parent = node;
return(node);
@@ -1167,7 +1054,7 @@ dict_create_table_step(
trx_t* trx;
ut_ad(thr);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
trx = thr_get_trx(thr);
@@ -1248,7 +1135,8 @@ dict_create_table_step(
ut_ad(node->col_no == v_col->v_pos);
dict_build_v_col_def_step(node);
- if (node->base_col_no < v_col->num_base - 1) {
+ if (node->base_col_no
+ < unsigned{v_col->num_base} - 1) {
/* move on to next base column */
node->base_col_no++;
} else {
@@ -1309,7 +1197,7 @@ dict_create_index_step(
trx_t* trx;
ut_ad(thr);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
trx = thr_get_trx(thr);
@@ -1467,7 +1355,7 @@ dict_check_if_system_table_exists(
ut_a(srv_get_active_thread_type() == SRV_NONE);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
sys_table = dict_table_get_low(tablename);
@@ -1485,7 +1373,7 @@ dict_check_if_system_table_exists(
dict_table_prevent_eviction(sys_table);
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return(error);
}
@@ -1654,9 +1542,9 @@ dict_create_or_check_sys_virtual()
"SYS_VIRTUAL", DICT_NUM_FIELDS__SYS_VIRTUAL + 1, 1);
if (err == DB_SUCCESS) {
- mutex_enter(&dict_sys->mutex);
- dict_sys->sys_virtual = dict_table_get_low("SYS_VIRTUAL");
- mutex_exit(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
+ dict_sys.sys_virtual = dict_table_get_low("SYS_VIRTUAL");
+ mutex_exit(&dict_sys.mutex);
return(DB_SUCCESS);
}
@@ -1730,9 +1618,9 @@ dict_create_or_check_sys_virtual()
dberr_t sys_virtual_err = dict_check_if_system_table_exists(
"SYS_VIRTUAL", DICT_NUM_FIELDS__SYS_VIRTUAL + 1, 1);
ut_a(sys_virtual_err == DB_SUCCESS);
- mutex_enter(&dict_sys->mutex);
- dict_sys->sys_virtual = dict_table_get_low("SYS_VIRTUAL");
- mutex_exit(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
+ dict_sys.sys_virtual = dict_table_get_low("SYS_VIRTUAL");
+ mutex_exit(&dict_sys.mutex);
return(err);
}
@@ -2129,7 +2017,7 @@ dict_create_add_foreigns_to_dictionary(
dict_foreign_t* foreign;
dberr_t error;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (NULL == dict_table_get_low("SYS_FOREIGN")) {
@@ -2139,6 +2027,8 @@ dict_create_add_foreigns_to_dictionary(
return(DB_ERROR);
}
+ error = DB_SUCCESS;
+
for (dict_foreign_set::const_iterator it = local_fk_set.begin();
it != local_fk_set.end();
++it) {
@@ -2150,12 +2040,11 @@ dict_create_add_foreigns_to_dictionary(
table->name.m_name, foreign, trx);
if (error != DB_SUCCESS) {
-
- return(error);
+ break;
}
}
- return(DB_SUCCESS);
+ return error;
}
/****************************************************************//**
@@ -2344,15 +2233,3 @@ dict_replace_tablespace_in_dictionary(
return(error);
}
-
-/** Assign a new table ID and put it into the table cache and the transaction.
-@param[in,out] table Table that needs an ID
-@param[in,out] trx Transaction */
-void
-dict_table_assign_new_id(
- dict_table_t* table,
- trx_t* trx)
-{
- dict_hdr_get_new_id(&table->id, NULL, NULL, table, false);
- trx->table_id = table->id;
-}
diff --git a/storage/innobase/dict/dict0defrag_bg.cc b/storage/innobase/dict/dict0defrag_bg.cc
index 7c6f5d75b5d..7e61e298ac6 100644
--- a/storage/innobase/dict/dict0defrag_bg.cc
+++ b/storage/innobase/dict/dict0defrag_bg.cc
@@ -151,7 +151,7 @@ dict_stats_defrag_pool_del(
{
ut_a((table && !index) || (!table && index));
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
mutex_enter(&defrag_pool_mutex);
@@ -193,7 +193,7 @@ dict_stats_process_entry_from_defrag_pool()
dict_table_t* table;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
/* If the table is no longer cached, we've already lost the in
memory stats so there's nothing really to write to disk. */
@@ -208,11 +208,11 @@ dict_stats_process_entry_from_defrag_pool()
if (table) {
dict_table_close(table, TRUE, FALSE);
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return;
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
dict_stats_save_defrag_stats(index);
dict_table_close(table, FALSE, FALSE);
}
@@ -243,8 +243,7 @@ dict_stats_save_defrag_summary(
return DB_SUCCESS;
}
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
ret = dict_stats_save_index_stat(index, time(NULL), "n_pages_freed",
index->stat_defrag_n_pages_freed,
@@ -253,8 +252,7 @@ dict_stats_save_defrag_summary(
" last defragmentation run.",
NULL);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
return (ret);
}
@@ -294,9 +292,7 @@ dict_stats_save_defrag_stats(
return DB_SUCCESS;
}
- rw_lock_x_lock(&dict_operation_lock);
-
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
ret = dict_stats_save_index_stat(index, now, "n_page_split",
index->stat_defrag_n_page_split,
NULL,
@@ -326,8 +322,6 @@ dict_stats_save_defrag_stats(
NULL);
end:
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
-
- return (ret);
+ dict_sys_unlock();
+ return ret;
}
diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc
index a0f2b5f3972..947fce1ae3a 100644
--- a/storage/innobase/dict/dict0dict.cc
+++ b/storage/innobase/dict/dict0dict.cc
@@ -60,7 +60,6 @@ extern uint ibuf_debug;
#include "lock0lock.h"
#include "mach0data.h"
#include "mem0mem.h"
-#include "os0once.h"
#include "page0page.h"
#include "page0zip.h"
#include "pars0pars.h"
@@ -80,17 +79,7 @@ extern uint ibuf_debug;
#include <algorithm>
/** the dictionary system */
-dict_sys_t* dict_sys = NULL;
-
-/** @brief the data dictionary rw-latch protecting dict_sys
-
-table create, drop, etc. reserve this in X-mode; implicit or
-backround operations purge, rollback, foreign key checks reserve this
-in S-mode; we cannot trust that MySQL protects implicit or background
-operations a table drop since MySQL does not know of them; therefore
-we need this; NOTE: a transaction which reserves this must keep book
-on the mode in trx_t::dict_operation_lock_mode */
-rw_lock_t dict_operation_lock;
+dict_sys_t dict_sys;
/** Percentage of compression failures that are allowed in a single
round */
@@ -173,22 +162,6 @@ static
ibool
dict_lru_validate(void);
/*===================*/
-/**********************************************************************//**
-Check if table is in the dictionary table LRU list.
-@return TRUE if table found */
-static
-ibool
-dict_lru_find_table(
-/*================*/
- const dict_table_t* find_table); /*!< in: table to find */
-/**********************************************************************//**
-Check if a table exists in the dict table non-LRU list.
-@return TRUE if table found */
-static
-ibool
-dict_non_lru_find_table(
-/*====================*/
- const dict_table_t* find_table); /*!< in: table to find */
#endif /* UNIV_DEBUG */
/* Stream for storing detailed information about the latest foreign key
@@ -247,158 +220,24 @@ dict_get_db_name_len(
return ulint(s - name);
}
-/** Reserve the dictionary system mutex. */
-void
-dict_mutex_enter_for_mysql_func(const char *file, unsigned line)
-{
- mutex_enter_loc(&dict_sys->mutex, file, line);
-}
-
-/********************************************************************//**
-Releases the dictionary system mutex for MySQL. */
-void
-dict_mutex_exit_for_mysql(void)
-/*===========================*/
-{
- mutex_exit(&dict_sys->mutex);
-}
-
-/** Allocate and init a dict_table_t's stats latch.
-This function must not be called concurrently on the same table object.
-@param[in,out] table_void table whose stats latch to create */
-static
-void
-dict_table_stats_latch_alloc(
- void* table_void)
-{
- dict_table_t* table = static_cast<dict_table_t*>(table_void);
-
- /* Note: rw_lock_create() will call the constructor */
-
- table->stats_latch = static_cast<rw_lock_t*>(
- ut_malloc_nokey(sizeof(rw_lock_t)));
-
- ut_a(table->stats_latch != NULL);
-
- rw_lock_create(dict_table_stats_key, table->stats_latch,
- SYNC_INDEX_TREE);
-}
-
-/** Deinit and free a dict_table_t's stats latch.
-This function must not be called concurrently on the same table object.
-@param[in,out] table table whose stats latch to free */
-static
-void
-dict_table_stats_latch_free(
- dict_table_t* table)
+/** Open a persistent table.
+@param[in] table_id persistent table identifier
+@param[in] ignore_err errors to ignore
+@param[in] cached_only whether to skip loading
+@return persistent table
+@retval NULL if not found */
+static dict_table_t* dict_table_open_on_id_low(
+ table_id_t table_id,
+ dict_err_ignore_t ignore_err,
+ bool cached_only)
{
- rw_lock_free(table->stats_latch);
- ut_free(table->stats_latch);
-}
+ dict_table_t* table = dict_sys.get_table(table_id);
-/** Create a dict_table_t's stats latch or delay for lazy creation.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose stats latch to create
-@param[in] enabled if false then the latch is disabled
-and dict_table_stats_lock()/unlock() become noop on this table. */
-void
-dict_table_stats_latch_create(
- dict_table_t* table,
- bool enabled)
-{
- if (!enabled) {
- table->stats_latch = NULL;
- table->stats_latch_created = os_once::DONE;
- return;
+ if (!table && !cached_only) {
+ table = dict_load_table_on_id(table_id, ignore_err);
}
- /* We create this lazily the first time it is used. */
- table->stats_latch = NULL;
- table->stats_latch_created = os_once::NEVER_DONE;
-}
-
-/** Destroy a dict_table_t's stats latch.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose stats latch to destroy */
-void
-dict_table_stats_latch_destroy(
- dict_table_t* table)
-{
- if (table->stats_latch_created == os_once::DONE
- && table->stats_latch != NULL) {
-
- dict_table_stats_latch_free(table);
- }
-}
-
-/** Lock the appropriate latch to protect a given table's statistics.
-@param[in] table table whose stats to lock
-@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
-void
-dict_table_stats_lock(
- dict_table_t* table,
- ulint latch_mode)
-{
- ut_ad(table != NULL);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- os_once::do_or_wait_for_done(
- &table->stats_latch_created,
- dict_table_stats_latch_alloc, table);
-
- if (table->stats_latch == NULL) {
- /* This is a dummy table object that is private in the current
- thread and is not shared between multiple threads, thus we
- skip any locking. */
- return;
- }
-
- switch (latch_mode) {
- case RW_S_LATCH:
- rw_lock_s_lock(table->stats_latch);
- break;
- case RW_X_LATCH:
- rw_lock_x_lock(table->stats_latch);
- break;
- case RW_NO_LATCH:
- /* fall through */
- default:
- ut_error;
- }
-}
-
-/** Unlock the latch that has been locked by dict_table_stats_lock().
-@param[in] table table whose stats to unlock
-@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
-void
-dict_table_stats_unlock(
- dict_table_t* table,
- ulint latch_mode)
-{
- ut_ad(table != NULL);
- ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
-
- if (table->stats_latch == NULL) {
- /* This is a dummy table object that is private in the current
- thread and is not shared between multiple threads, thus we
- skip any locking. */
- return;
- }
-
- switch (latch_mode) {
- case RW_S_LATCH:
- rw_lock_s_unlock(table->stats_latch);
- break;
- case RW_X_LATCH:
- rw_lock_x_unlock(table->stats_latch);
- break;
- case RW_NO_LATCH:
- /* fall through */
- default:
- ut_error;
- }
+ return table;
}
/**********************************************************************//**
@@ -411,7 +250,7 @@ dict_table_try_drop_aborted(
dict_table_t* table, /*!< in: table, or NULL if it
needs to be looked up again */
table_id_t table_id, /*!< in: table identifier */
- int32 ref_count) /*!< in: expected table->n_ref_count */
+ uint32_t ref_count) /*!< in: expected table->n_ref_count */
{
trx_t* trx;
@@ -444,7 +283,7 @@ dict_table_try_drop_aborted(
/**********************************************************************//**
When opening a table,
try to drop any indexes after an aborted index creation.
-Release the dict_sys->mutex. */
+Release the dict_sys.mutex. */
static
void
dict_table_try_drop_aborted_and_mutex_exit(
@@ -464,11 +303,11 @@ dict_table_try_drop_aborted_and_mutex_exit(
was aborted. */
table_id_t table_id = table->id;
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
dict_table_try_drop_aborted(table, table_id, 1);
} else {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
}
@@ -484,10 +323,10 @@ dict_table_close(
index creation */
{
if (!dict_locked) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_a(table->get_ref_count() > 0);
const bool last_handle = table->release();
@@ -506,14 +345,7 @@ dict_table_close(
MONITOR_DEC(MONITOR_TABLE_REFERENCE);
ut_ad(dict_lru_validate());
-
-#ifdef UNIV_DEBUG
- if (table->can_be_evicted) {
- ut_ad(dict_lru_find_table(table));
- } else {
- ut_ad(dict_non_lru_find_table(table));
- }
-#endif /* UNIV_DEBUG */
+ ut_ad(dict_sys.find(table));
if (!dict_locked) {
table_id_t table_id = table->id;
@@ -521,7 +353,7 @@ dict_table_close(
&& table->drop_aborted
&& dict_table_get_first_index(table);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
/* dict_table_try_drop_aborted() can generate undo logs.
So it should be avoided after shutdown of background
@@ -534,9 +366,9 @@ dict_table_close(
/********************************************************************//**
Closes the only open handle to a table and drops a table while assuring
-that dict_sys->mutex is held the whole time. This assures that the table
+that dict_sys.mutex is held the whole time. This assures that the table
is not evicted after the close when the count of open handles goes to zero.
-Because dict_sys->mutex is held, we do not need to call
+Because dict_sys.mutex is held, we do not need to call
dict_table_prevent_eviction(). */
void
dict_table_close_and_drop(
@@ -546,8 +378,7 @@ dict_table_close_and_drop(
{
dberr_t err = DB_SUCCESS;
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
ut_ad(trx->dict_operation != TRX_DICT_OP_NONE);
ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE));
@@ -734,61 +565,6 @@ dict_table_get_nth_v_col_mysql(
return(dict_table_get_nth_v_col(table, i));
}
-/** Allocate and init the autoinc latch of a given table.
-This function must not be called concurrently on the same table object.
-@param[in,out] table_void table whose autoinc latch to create */
-static
-void
-dict_table_autoinc_alloc(
- void* table_void)
-{
- dict_table_t* table = static_cast<dict_table_t*>(table_void);
- table->autoinc_mutex = UT_NEW_NOKEY(ib_mutex_t());
- ut_a(table->autoinc_mutex != NULL);
- mutex_create(LATCH_ID_AUTOINC, table->autoinc_mutex);
-}
-
-/** Allocate and init the zip_pad_mutex of a given index.
-This function must not be called concurrently on the same index object.
-@param[in,out] index_void index whose zip_pad_mutex to create */
-static
-void
-dict_index_zip_pad_alloc(
- void* index_void)
-{
- dict_index_t* index = static_cast<dict_index_t*>(index_void);
- index->zip_pad.mutex = UT_NEW_NOKEY(SysMutex());
- ut_a(index->zip_pad.mutex != NULL);
- mutex_create(LATCH_ID_ZIP_PAD_MUTEX, index->zip_pad.mutex);
-}
-
-/********************************************************************//**
-Acquire the autoinc lock. */
-void
-dict_table_autoinc_lock(
-/*====================*/
- dict_table_t* table) /*!< in/out: table */
-{
- os_once::do_or_wait_for_done(
- &table->autoinc_mutex_created,
- dict_table_autoinc_alloc, table);
-
- mutex_enter(table->autoinc_mutex);
-}
-
-/** Acquire the zip_pad_mutex latch.
-@param[in,out] index the index whose zip_pad_mutex to acquire.*/
-static
-void
-dict_index_zip_pad_lock(
- dict_index_t* index)
-{
- os_once::do_or_wait_for_done(
- &index->zip_pad.mutex_created,
- dict_index_zip_pad_alloc, index);
-
- mutex_enter(index->zip_pad.mutex);
-}
/** Get all the FTS indexes on a table.
@param[in] table table
@@ -815,16 +591,6 @@ dict_table_get_all_fts_indexes(
return(ib_vector_size(indexes));
}
-/********************************************************************//**
-Release the autoinc lock. */
-void
-dict_table_autoinc_unlock(
-/*======================*/
- dict_table_t* table) /*!< in/out: table */
-{
- mutex_exit(table->autoinc_mutex);
-}
-
/** Looks for column n in an index.
@param[in] index index
@param[in] n column number
@@ -882,47 +648,29 @@ dict_index_get_nth_col_or_prefix_pos(
return(ULINT_UNDEFINED);
}
-/** Returns TRUE if the index contains a column or a prefix of that column.
-@param[in] index index
+/** Check if the index contains a column or a prefix of that column.
@param[in] n column number
@param[in] is_virtual whether it is a virtual col
-@return TRUE if contains the column or its prefix */
-bool
-dict_index_contains_col_or_prefix(
- const dict_index_t* index,
- ulint n,
- bool is_virtual)
+@return whether the index contains the column or its prefix */
+bool dict_index_t::contains_col_or_prefix(ulint n, bool is_virtual) const
{
- const dict_field_t* field;
- const dict_col_t* col;
- ulint pos;
- ulint n_fields;
+ ut_ad(magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(index);
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
-
- if (dict_index_is_clust(index)) {
+ if (is_primary()) {
return(!is_virtual);
}
- if (is_virtual) {
- col = &dict_table_get_nth_v_col(index->table, n)->m_col;
- } else {
- col = dict_table_get_nth_col(index->table, n);
- }
-
- n_fields = dict_index_get_n_fields(index);
-
- for (pos = 0; pos < n_fields; pos++) {
- field = dict_index_get_nth_field(index, pos);
-
- if (col == field->col) {
+ const dict_col_t* col = is_virtual
+ ? &dict_table_get_nth_v_col(table, n)->m_col
+ : dict_table_get_nth_col(table, n);
- return(true);
+ for (ulint pos = 0; pos < n_fields; pos++) {
+ if (col == fields[pos].col) {
+ return true;
}
}
- return(false);
+ return false;
}
/********************************************************************//**
@@ -991,10 +739,10 @@ dict_table_open_on_id(
dict_table_t* table;
if (!dict_locked) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
table = dict_table_open_on_id_low(
table_id,
@@ -1004,13 +752,7 @@ dict_table_open_on_id(
table_op == DICT_TABLE_OP_OPEN_ONLY_IF_CACHED);
if (table != NULL) {
-
- if (table->can_be_evicted) {
- dict_move_to_mru(table);
- }
-
- table->acquire();
-
+ dict_sys.acquire(table);
MONITOR_INC(MONITOR_TABLE_REFERENCE);
}
@@ -1070,56 +812,46 @@ dict_table_col_in_clustered_key(
return(FALSE);
}
-/**********************************************************************//**
-Inits the data dictionary module. */
-void
-dict_init(void)
-/*===========*/
+/** Initialise the data dictionary cache. */
+void dict_sys_t::create()
{
- dict_sys = static_cast<dict_sys_t*>(ut_zalloc_nokey(sizeof(*dict_sys)));
-
- UT_LIST_INIT(dict_sys->table_LRU, &dict_table_t::table_LRU);
- UT_LIST_INIT(dict_sys->table_non_LRU, &dict_table_t::table_LRU);
+ ut_ad(this == &dict_sys);
+ ut_ad(!is_initialised());
+ m_initialised= true;
+ UT_LIST_INIT(table_LRU, &dict_table_t::table_LRU);
+ UT_LIST_INIT(table_non_LRU, &dict_table_t::table_LRU);
- mutex_create(LATCH_ID_DICT_SYS, &dict_sys->mutex);
+ mutex_create(LATCH_ID_DICT_SYS, &mutex);
- dict_sys->table_hash = hash_create(
- buf_pool_get_curr_size()
- / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE));
+ const ulint hash_size = buf_pool_get_curr_size()
+ / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE);
- dict_sys->table_id_hash = hash_create(
- buf_pool_get_curr_size()
- / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE));
+ table_hash= hash_create(hash_size);
+ table_id_hash= hash_create(hash_size);
+ temp_id_hash= hash_create(hash_size);
- rw_lock_create(dict_operation_lock_key,
- &dict_operation_lock, SYNC_DICT_OPERATION);
+ rw_lock_create(dict_operation_lock_key, &latch, SYNC_DICT_OPERATION);
- if (!srv_read_only_mode) {
- dict_foreign_err_file = os_file_create_tmpfile();
- ut_a(dict_foreign_err_file);
- }
+ if (!srv_read_only_mode)
+ {
+ dict_foreign_err_file= os_file_create_tmpfile();
+ ut_a(dict_foreign_err_file);
+ }
- mutex_create(LATCH_ID_DICT_FOREIGN_ERR, &dict_foreign_err_mutex);
+ mutex_create(LATCH_ID_DICT_FOREIGN_ERR, &dict_foreign_err_mutex);
}
-/**********************************************************************//**
-Move to the most recently used segment of the LRU list. */
-void
-dict_move_to_mru(
-/*=============*/
- dict_table_t* table) /*!< in: table to move to MRU */
+/** Acquire a reference to a cached table. */
+inline void dict_sys_t::acquire(dict_table_t* table)
{
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(dict_lru_validate());
- ut_ad(dict_lru_find_table(table));
-
- ut_a(table->can_be_evicted);
-
- UT_LIST_REMOVE(dict_sys->table_LRU, table);
-
- UT_LIST_ADD_FIRST(dict_sys->table_LRU, table);
-
- ut_ad(dict_lru_validate());
+ ut_ad(dict_sys.find(table));
+ if (table->can_be_evicted)
+ {
+ UT_LIST_REMOVE(dict_sys.table_LRU, table);
+ UT_LIST_ADD_FIRST(dict_sys.table_LRU, table);
+ }
+
+ table->acquire();
}
/**********************************************************************//**
@@ -1145,11 +877,11 @@ dict_table_open_on_name(
DBUG_PRINT("dict_table_open_on_name", ("table: '%s'", table_name));
if (!dict_locked) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
ut_ad(table_name);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
table = dict_table_check_if_in_cache_low(table_name);
@@ -1165,7 +897,7 @@ dict_table_open_on_name(
if (!(ignore_err & ~DICT_ERR_IGNORE_FK_NOKEY)
&& !table->is_readable()) {
/* Make life easy for drop table. */
- dict_table_prevent_eviction(table);
+ dict_sys.prevent_eviction(table);
if (table->corrupted) {
@@ -1173,31 +905,22 @@ dict_table_open_on_name(
<< " is corrupted. Please "
"drop the table and recreate.";
if (!dict_locked) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
DBUG_RETURN(NULL);
}
- if (table->can_be_evicted) {
- dict_move_to_mru(table);
- }
-
- table->acquire();
+ dict_sys.acquire(table);
if (!dict_locked) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
DBUG_RETURN(table);
}
- if (table->can_be_evicted) {
- dict_move_to_mru(table);
- }
-
- table->acquire();
-
+ dict_sys.acquire(table);
MONITOR_INC(MONITOR_TABLE_REFERENCE);
}
@@ -1248,65 +971,64 @@ dict_table_add_system_columns(
}
/** Add the table definition to the data dictionary cache */
-void
-dict_table_t::add_to_cache()
+void dict_table_t::add_to_cache()
{
- ut_ad(dict_lru_validate());
- ut_ad(mutex_own(&dict_sys->mutex));
-
cached = TRUE;
- ulint fold = ut_fold_string(name.m_name);
- ulint id_fold = ut_fold_ull(id);
+ dict_sys.add(this);
+}
+
+/** Add a table definition to the data dictionary cache */
+inline void dict_sys_t::add(dict_table_t* table)
+{
+ ut_ad(!find(table));
+
+ ulint fold = ut_fold_string(table->name.m_name);
+
+ mutex_create(LATCH_ID_AUTOINC, &table->autoinc_mutex);
/* Look for a table with the same name: error if such exists */
{
dict_table_t* table2;
- HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
+ HASH_SEARCH(name_hash, table_hash, fold,
dict_table_t*, table2, ut_ad(table2->cached),
- !strcmp(table2->name.m_name, name.m_name));
+ !strcmp(table2->name.m_name, table->name.m_name));
ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different name */
- HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
+ HASH_SEARCH_ALL(name_hash, table_hash,
dict_table_t*, table2, ut_ad(table2->cached),
- table2 == this);
+ table2 == table);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
}
+ HASH_INSERT(dict_table_t, name_hash, table_hash, fold, table);
/* Look for a table with the same id: error if such exists */
+ hash_table_t* id_hash = table->is_temporary()
+ ? temp_id_hash : table_id_hash;
+ const ulint id_fold = ut_fold_ull(table->id);
{
dict_table_t* table2;
- HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
+ HASH_SEARCH(id_hash, id_hash, id_fold,
dict_table_t*, table2, ut_ad(table2->cached),
- table2->id == id);
+ table2->id == table->id);
ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different id */
- HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
+ HASH_SEARCH_ALL(id_hash, id_hash,
dict_table_t*, table2, ut_ad(table2->cached),
- table2 == this);
+ table2 == table);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
- }
-
- /* Add table to hash table of tables */
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
- this);
-
- /* Add table to hash table of tables based on table id */
- HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash, id_fold,
- this);
- if (can_be_evicted) {
- UT_LIST_ADD_FIRST(dict_sys->table_LRU, this);
- } else {
- UT_LIST_ADD_FIRST(dict_sys->table_non_LRU, this);
+ HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, table);
}
+ UT_LIST_ADD_FIRST(table->can_be_evicted ? table_LRU : table_non_LRU,
+ table);
ut_ad(dict_lru_validate());
}
@@ -1319,9 +1041,7 @@ dict_table_can_be_evicted(
/*======================*/
dict_table_t* table) /*!< in: table to test */
{
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
-
+ ut_d(dict_sys.assert_locked());
ut_a(table->can_be_evicted);
ut_a(table->foreign_set.empty());
ut_a(table->referenced_set.empty());
@@ -1387,11 +1107,10 @@ dict_make_room_in_cache(
ut_a(pct_check > 0);
ut_a(pct_check <= 100);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
ut_ad(dict_lru_validate());
- i = len = UT_LIST_GET_LEN(dict_sys->table_LRU);
+ i = len = UT_LIST_GET_LEN(dict_sys.table_LRU);
if (len < max_tables) {
return(0);
@@ -1405,7 +1124,7 @@ dict_make_room_in_cache(
/* Find a suitable candidate to evict from the cache. Don't scan the
entire LRU list. Only scan pct_check list entries. */
- for (table = UT_LIST_GET_LAST(dict_sys->table_LRU);
+ for (table = UT_LIST_GET_LAST(dict_sys.table_LRU);
table != NULL
&& i > check_up_to
&& (len - n_evicted) > max_tables;
@@ -1417,7 +1136,7 @@ dict_make_room_in_cache(
if (dict_table_can_be_evicted(table)) {
ut_ad(!table->fts);
- dict_table_remove_from_cache_low(table, TRUE);
+ dict_sys.remove(table, true);
++n_evicted;
}
@@ -1428,25 +1147,6 @@ dict_make_room_in_cache(
return(n_evicted);
}
-/**********************************************************************//**
-Move a table to the non-LRU list from the LRU list. */
-void
-dict_table_move_from_lru_to_non_lru(
-/*================================*/
- dict_table_t* table) /*!< in: table to move from LRU to non-LRU */
-{
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(dict_lru_find_table(table));
-
- ut_a(table->can_be_evicted);
-
- UT_LIST_REMOVE(dict_sys->table_LRU, table);
-
- UT_LIST_ADD_LAST(dict_sys->table_non_LRU, table);
-
- table->can_be_evicted = FALSE;
-}
-
/** Looks for an index with the given id given a table instance.
@param[in] table table instance
@param[in] id index id
@@ -1482,14 +1182,11 @@ dict_index_find_on_id_low(
/*======================*/
index_id_t id) /*!< in: index id */
{
- dict_table_t* table;
+ if (!dict_sys.is_initialised()) return NULL;
- /* This can happen if the system tablespace is the wrong page size */
- if (dict_sys == NULL) {
- return(NULL);
- }
+ dict_table_t* table;
- for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
+ for (table = UT_LIST_GET_FIRST(dict_sys.table_LRU);
table != NULL;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
@@ -1500,7 +1197,7 @@ dict_index_find_on_id_low(
}
}
- for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU);
+ for (table = UT_LIST_GET_FIRST(dict_sys.table_non_LRU);
table != NULL;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
@@ -1553,7 +1250,7 @@ dict_table_rename_in_cache(
char old_name[MAX_FULL_NAME_LEN + 1];
os_file_type_t ftype;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* store the old/current name to an automatic variable */
ut_a(strlen(table->name.m_name) < sizeof old_name);
@@ -1563,7 +1260,7 @@ dict_table_rename_in_cache(
/* Look for a table with the same name: error if such exists */
dict_table_t* table2;
- HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
+ HASH_SEARCH(name_hash, dict_sys.table_hash, fold,
dict_table_t*, table2, ut_ad(table2->cached),
(ut_strcmp(table2->name.m_name, new_name) == 0));
DBUG_EXECUTE_IF("dict_table_rename_in_cache_failure",
@@ -1657,7 +1354,7 @@ dict_table_rename_in_cache(
}
/* Remove table from the hash tables of tables */
- HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
+ HASH_DELETE(dict_table_t, name_hash, dict_sys.table_hash,
ut_fold_string(old_name), table);
if (strlen(new_name) > strlen(table->name.m_name)) {
@@ -1672,7 +1369,7 @@ dict_table_rename_in_cache(
strcpy(table->name.m_name, new_name);
/* Add table to hash table of tables */
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
+ HASH_INSERT(dict_table_t, name_hash, dict_sys.table_hash, fold,
table);
if (!rename_also_foreigns) {
@@ -1934,28 +1631,26 @@ dict_table_change_id_in_cache(
dict_table_t* table, /*!< in/out: table object already in cache */
table_id_t new_id) /*!< in: new id to set */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
+ ut_ad(!table->is_temporary());
/* Remove the table from the hash table of id's */
- HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
+ HASH_DELETE(dict_table_t, id_hash, dict_sys.table_id_hash,
ut_fold_ull(table->id), table);
table->id = new_id;
/* Add the table back to the hash table */
- HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
+ HASH_INSERT(dict_table_t, id_hash, dict_sys.table_id_hash,
ut_fold_ull(table->id), table);
}
-/**********************************************************************//**
-Removes a table object from the dictionary cache. */
-void
-dict_table_remove_from_cache_low(
-/*=============================*/
- dict_table_t* table, /*!< in, own: table */
- ibool lru_evict) /*!< in: TRUE if table being evicted
- to make room in the table LRU list */
+/** Evict a table definition from the InnoDB data dictionary cache.
+@param[in,out] table cached table definition to be evicted
+@param[in] lru whether this is part of least-recently-used eviction
+@param[in] keep whether to keep (not free) the object */
+void dict_sys_t::remove(dict_table_t* table, bool lru, bool keep)
{
dict_foreign_t* foreign;
dict_index_t* index;
@@ -1963,7 +1658,7 @@ dict_table_remove_from_cache_low(
ut_ad(dict_lru_validate());
ut_a(table->get_ref_count() == 0);
ut_a(table->n_rec_locks == 0);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(find(table));
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
/* Remove the foreign constraints from the cache */
@@ -1987,37 +1682,33 @@ dict_table_remove_from_cache_low(
index != NULL;
index = UT_LIST_GET_LAST(table->indexes)) {
- dict_index_remove_from_cache_low(table, index, lru_evict);
+ dict_index_remove_from_cache_low(table, index, lru);
}
/* Remove table from the hash tables of tables */
- HASH_DELETE(dict_table_t, name_hash, dict_sys->table_hash,
+ HASH_DELETE(dict_table_t, name_hash, table_hash,
ut_fold_string(table->name.m_name), table);
- HASH_DELETE(dict_table_t, id_hash, dict_sys->table_id_hash,
- ut_fold_ull(table->id), table);
+ hash_table_t* id_hash = table->is_temporary()
+ ? temp_id_hash : table_id_hash;
+ const ulint id_fold = ut_fold_ull(table->id);
+ HASH_DELETE(dict_table_t, id_hash, id_hash, id_fold, table);
/* Remove table from LRU or non-LRU list. */
if (table->can_be_evicted) {
- ut_ad(dict_lru_find_table(table));
- UT_LIST_REMOVE(dict_sys->table_LRU, table);
+ UT_LIST_REMOVE(table_LRU, table);
} else {
- ut_ad(dict_non_lru_find_table(table));
- UT_LIST_REMOVE(dict_sys->table_non_LRU, table);
+ UT_LIST_REMOVE(table_non_LRU, table);
}
- ut_ad(dict_lru_validate());
-
- if (lru_evict && table->drop_aborted) {
+ if (lru && table->drop_aborted) {
/* When evicting the table definition,
drop the orphan indexes from the data dictionary
and free the index pages. */
trx_t* trx = trx_create();
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
-
+ ut_d(dict_sys.assert_locked());
/* Mimic row_mysql_lock_data_dictionary(). */
trx->dict_operation_lock_mode = RW_X_LATCH;
@@ -2034,17 +1725,11 @@ dict_table_remove_from_cache_low(
UT_DELETE(table->vc_templ);
}
- dict_mem_table_free(table);
-}
+ mutex_free(&table->autoinc_mutex);
-/**********************************************************************//**
-Removes a table object from the dictionary cache. */
-void
-dict_table_remove_from_cache(
-/*=========================*/
- dict_table_t* table) /*!< in, own: table */
-{
- dict_table_remove_from_cache_low(table, FALSE);
+ if (!keep) {
+ dict_mem_table_free(table);
+ }
}
/****************************************************************//**
@@ -2072,44 +1757,6 @@ dict_col_name_is_reserved(
return(FALSE);
}
-/** Clears the virtual column's index list before index is
-being freed.
-@param[in] index Index being freed */
-void dict_index_remove_from_v_col_list(dict_index_t* index)
-{
- /* Index is not completely formed */
- if (!index->cached) {
- return;
- }
- if (dict_index_has_virtual(index)) {
- const dict_col_t* col;
- const dict_v_col_t* vcol;
-
- for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
- col = dict_index_get_nth_col(index, i);
- if (col->is_virtual()) {
- vcol = reinterpret_cast<const dict_v_col_t*>(
- col);
- /* This could be NULL, when we do add
- virtual column, add index together. We do not
- need to track this virtual column's index */
- if (vcol->v_indexes == NULL) {
- continue;
- }
- dict_v_idx_list::iterator it;
- for (it = vcol->v_indexes->begin();
- it != vcol->v_indexes->end(); ++it) {
- dict_v_idx_t v_index = *it;
- if (v_index.index == index) {
- vcol->v_indexes->erase(it);
- break;
- }
- }
- }
- }
- }
-}
-
/** Adds an index to the dictionary cache, with possible indexing newly
added column.
@param[in,out] index index; NOTE! The index memory
@@ -2127,7 +1774,7 @@ dict_index_add_to_cache(
ulint n_ord;
ulint i;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(index->n_def == index->n_fields);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(!dict_index_is_online_ddl(index));
@@ -2192,6 +1839,8 @@ dict_index_add_to_cache(
> field->col->max_prefix) {
/* Set the max_prefix value based on the
prefix_len. */
+ ut_ad(field->col->is_binary()
+ || field->prefix_len % field->col->mbmaxlen == 0);
field->col->max_prefix = field->prefix_len;
}
ut_ad(field->col->ord_part == 1);
@@ -2257,7 +1906,7 @@ dict_index_remove_from_cache_low(
ut_ad(table && index);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* No need to acquire the dict_index_t::lock here because
there can't be any active operations on this index (or table). */
@@ -2339,7 +1988,7 @@ dict_index_find_cols(
const dict_table_t* table = index->table;
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
for (ulint i = 0; i < index->n_fields; i++) {
ulint j;
@@ -2437,18 +2086,9 @@ dict_index_add_col(
if (col->is_virtual()) {
dict_v_col_t* v_col = reinterpret_cast<dict_v_col_t*>(col);
-
- /* When v_col->v_indexes==NULL,
- ha_innobase::commit_inplace_alter_table(commit=true)
- will evict and reload the table definition, and
- v_col->v_indexes will not be NULL for the new table. */
- if (v_col->v_indexes != NULL) {
- /* Register the index with the virtual column index
- list */
- v_col->v_indexes->push_back(
- dict_v_idx_t(index, index->n_def));
- }
-
+ /* Register the index with the virtual column index list */
+ v_col->n_v_indexes++;
+ v_col->v_indexes.push_front(dict_v_idx_t(index, index->n_def));
col_name = dict_table_get_v_col_name_mysql(
table, dict_col_get_no(col));
} else {
@@ -2616,7 +2256,7 @@ dict_index_build_internal_clust(
ut_ad(dict_index_is_clust(index));
ut_ad(!dict_index_is_ibuf(index));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* Create a new index object with certainly enough fields */
new_index = dict_mem_index_create(index->table, index->name,
@@ -2768,7 +2408,7 @@ dict_index_build_internal_non_clust(
ut_ad(table && index);
ut_ad(!dict_index_is_clust(index));
ut_ad(!dict_index_is_ibuf(index));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* The clustered index should be the first in the list of indexes */
clust_index = UT_LIST_GET_FIRST(table->indexes);
@@ -2862,7 +2502,7 @@ dict_index_build_internal_fts(
dict_index_t* new_index;
ut_ad(index->type == DICT_FTS);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* Create a new index */
new_index = dict_mem_index_create(index->table, index->name,
@@ -2931,7 +2571,7 @@ dict_foreign_remove_from_cache(
/*===========================*/
dict_foreign_t* foreign) /*!< in, own: foreign constraint */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_a(foreign);
if (foreign->referenced_table != NULL) {
@@ -2956,7 +2596,7 @@ dict_foreign_find(
dict_table_t* table, /*!< in: table object */
dict_foreign_t* foreign) /*!< in: foreign constraint */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(dict_foreign_set_validate(table->foreign_set));
ut_ad(dict_foreign_set_validate(table->referenced_set));
@@ -3010,7 +2650,7 @@ dict_foreign_find_index(
/*!< out: index where error
happened */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (error) {
*error = FK_INDEX_NOT_FOUND;
@@ -3108,7 +2748,7 @@ dict_foreign_add_to_cache(
DBUG_ENTER("dict_foreign_add_to_cache");
DBUG_PRINT("dict_foreign_add_to_cache", ("id: %s", foreign->id));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
for_table = dict_table_check_if_in_cache_low(
foreign->foreign_table_name_lookup);
@@ -3222,11 +2862,11 @@ dict_foreign_add_to_cache(
list. Otherwise it will be evicted from the cache. */
if (ref_table != NULL) {
- dict_table_prevent_eviction(ref_table);
+ dict_sys.prevent_eviction(ref_table);
}
if (for_table != NULL) {
- dict_table_prevent_eviction(for_table);
+ dict_sys.prevent_eviction(for_table);
}
ut_ad(dict_lru_validate());
@@ -4016,7 +3656,7 @@ dict_create_foreign_constraints_low(
char create_name[MAX_TABLE_NAME_LEN + 1];
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
table = dict_table_get_low(name);
/* First check if we are actually doing an ALTER TABLE, and in that
@@ -4929,7 +4569,7 @@ dict_foreign_parse_drop_constraints(
ptr = str;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
loop:
ptr = dict_scan_to(ptr, "DROP");
@@ -5031,14 +4671,14 @@ syntax_error:
/**********************************************************************//**
Returns an index object if it is found in the dictionary cache.
-Assumes that dict_sys->mutex is already being held.
+Assumes that dict_sys.mutex is already being held.
@return index, NULL if not found */
dict_index_t*
dict_index_get_if_in_cache_low(
/*===========================*/
index_id_t index_id) /*!< in: index id */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
return(dict_index_find_on_id_low(index_id));
}
@@ -5054,15 +4694,15 @@ dict_index_get_if_in_cache(
{
dict_index_t* index;
- if (dict_sys == NULL) {
+ if (!dict_sys.is_initialised()) {
return(NULL);
}
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
index = dict_index_get_if_in_cache_low(index_id);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return(index);
}
@@ -5153,46 +4793,6 @@ dict_index_build_node_ptr(
return(tuple);
}
-/**********************************************************************//**
-Copies an initial segment of a physical record, long enough to specify an
-index entry uniquely.
-@return pointer to the prefix record */
-rec_t*
-dict_index_copy_rec_order_prefix(
-/*=============================*/
- const dict_index_t* index, /*!< in: index */
- const rec_t* rec, /*!< in: record for which to
- copy prefix */
- ulint* n_fields,/*!< out: number of fields copied */
- byte** buf, /*!< in/out: memory buffer for the
- copied prefix, or NULL */
- ulint* buf_size)/*!< in/out: buffer size */
-{
- ulint n;
-
- UNIV_PREFETCH_R(rec);
-
- if (dict_index_is_ibuf(index)) {
- ut_ad(!dict_table_is_comp(index->table));
- n = rec_get_n_fields_old(rec);
- } else {
- if (page_rec_is_leaf(rec)) {
- n = dict_index_get_n_unique_in_tree(index);
- } else if (dict_index_is_spatial(index)) {
- ut_ad(dict_index_get_n_unique_in_tree_nonleaf(index)
- == DICT_INDEX_SPATIAL_NODEPTR_SIZE);
- /* For R-tree, we have to compare
- the child page numbers as well. */
- n = DICT_INDEX_SPATIAL_NODEPTR_SIZE + 1;
- } else {
- n = dict_index_get_n_unique_in_tree(index);
- }
- }
-
- *n_fields = n;
- return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
-}
-
/** Convert a physical record into a search tuple.
@param[in] rec index record (not necessarily in an index page)
@param[in] index index
@@ -5385,7 +4985,7 @@ dict_print_info_on_foreign_keys(
dict_foreign_t* foreign;
std::string str;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
for (dict_foreign_set::iterator it = table->foreign_set.begin();
it != table->foreign_set.end();
@@ -5452,12 +5052,12 @@ dict_print_info_on_foreign_keys(
}
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return str;
}
/** Given a space_id of a file-per-table tablespace, search the
-dict_sys->table_LRU list and return the dict_table_t* pointer for it.
+dict_sys.table_LRU list and return the dict_table_t* pointer for it.
@param space tablespace
@return table if found, NULL if not */
static
@@ -5470,13 +5070,13 @@ dict_find_single_table_by_space(const fil_space_t* space)
ut_ad(space->id > 0);
- if (dict_sys == NULL) {
+ if (!dict_sys.is_initialised()) {
/* This could happen when it's in redo processing. */
return(NULL);
}
- table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
- num_item = UT_LIST_GET_LEN(dict_sys->table_LRU);
+ table = UT_LIST_GET_FIRST(dict_sys.table_LRU);
+ num_item = UT_LIST_GET_LEN(dict_sys.table_LRU);
/* This function intentionally does not acquire mutex as it is used
by error handling code in deep call stack as last means to avoid
@@ -5550,9 +5150,9 @@ dict_set_corrupted(
row_mysql_lock_data_dictionary(trx);
}
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
- ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+ ut_ad(mutex_own(&dict_sys.mutex));
+ ut_ad(!dict_table_is_comp(dict_sys.sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys.sys_indexes));
ut_ad(!sync_check_iterate(dict_sync_check()));
/* Mark the table as corrupted only if the clustered index
@@ -5580,7 +5180,7 @@ dict_set_corrupted(
mtr_start(&mtr);
index->type |= DICT_CORRUPT;
- sys_index = UT_LIST_GET_FIRST(dict_sys->sys_indexes->indexes);
+ sys_index = UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes);
/* Find the index row in SYS_INDEXES */
tuple = dtuple_create(heap, 2);
@@ -5640,9 +5240,9 @@ dict_set_corrupted_index_cache_only(
{
ut_ad(index != NULL);
ut_ad(index->table != NULL);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
- ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+ ut_ad(mutex_own(&dict_sys.mutex));
+ ut_ad(!dict_table_is_comp(dict_sys.sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys.sys_indexes));
/* Mark the table as corrupted only if the clustered index
is corrupted */
@@ -5670,11 +5270,10 @@ dict_index_set_merge_threshold(
btr_cur_t cursor;
ut_ad(index != NULL);
- ut_ad(!dict_table_is_comp(dict_sys->sys_tables));
- ut_ad(!dict_table_is_comp(dict_sys->sys_indexes));
+ ut_ad(!dict_table_is_comp(dict_sys.sys_tables));
+ ut_ad(!dict_table_is_comp(dict_sys.sys_indexes));
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&(dict_sys->mutex));
+ dict_sys_lock();
heap = mem_heap_create(sizeof(dtuple_t) + 2 * (sizeof(dfield_t)
+ sizeof(que_fork_t) + sizeof(upd_node_t)
@@ -5682,7 +5281,7 @@ dict_index_set_merge_threshold(
mtr_start(&mtr);
- sys_index = UT_LIST_GET_FIRST(dict_sys->sys_indexes->indexes);
+ sys_index = UT_LIST_GET_FIRST(dict_sys.sys_indexes->indexes);
/* Find the index row in SYS_INDEXES */
tuple = dtuple_create(heap, 2);
@@ -5722,8 +5321,7 @@ dict_index_set_merge_threshold(
mtr_commit(&mtr);
mem_heap_free(heap);
- mutex_exit(&(dict_sys->mutex));
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
}
#ifdef UNIV_DEBUG
@@ -5754,14 +5352,14 @@ void
dict_set_merge_threshold_all_debug(
uint merge_threshold_all)
{
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
dict_set_merge_threshold_list_debug(
- &dict_sys->table_LRU, merge_threshold_all);
+ &dict_sys.table_LRU, merge_threshold_all);
dict_set_merge_threshold_list_debug(
- &dict_sys->table_non_LRU, merge_threshold_all);
+ &dict_sys.table_non_LRU, merge_threshold_all);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
#endif /* UNIV_DEBUG */
@@ -5907,7 +5505,7 @@ dict_table_check_for_dup_indexes(
const dict_index_t* index1;
const dict_index_t* index2;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* The primary index _must_ exist */
ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
@@ -5984,7 +5582,7 @@ dict_table_schema_check(
dict_table_t* table;
ulint i;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
table = dict_table_get_low(req_schema->table_name);
@@ -6228,107 +5826,96 @@ dict_fs2utf8(
}
}
-/** Resize the hash tables besed on the current buffer pool size. */
-void
-dict_resize()
+/** Resize the hash tables based on the current buffer pool size. */
+void dict_sys_t::resize()
{
- dict_table_t* table;
-
- mutex_enter(&dict_sys->mutex);
-
- /* all table entries are in table_LRU and table_non_LRU lists */
- hash_table_free(dict_sys->table_hash);
- hash_table_free(dict_sys->table_id_hash);
-
- dict_sys->table_hash = hash_create(
- buf_pool_get_curr_size()
- / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE));
-
- dict_sys->table_id_hash = hash_create(
- buf_pool_get_curr_size()
- / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE));
-
- for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU); table;
- table = UT_LIST_GET_NEXT(table_LRU, table)) {
- ulint fold = ut_fold_string(table->name.m_name);
- ulint id_fold = ut_fold_ull(table->id);
-
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash,
- fold, table);
-
- HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
- id_fold, table);
- }
-
- for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU); table;
- table = UT_LIST_GET_NEXT(table_LRU, table)) {
- ulint fold = ut_fold_string(table->name.m_name);
- ulint id_fold = ut_fold_ull(table->id);
-
- HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash,
- fold, table);
-
- HASH_INSERT(dict_table_t, id_hash, dict_sys->table_id_hash,
- id_fold, table);
- }
-
- mutex_exit(&dict_sys->mutex);
+ ut_ad(this == &dict_sys);
+ ut_ad(is_initialised());
+ mutex_enter(&mutex);
+
+ /* all table entries are in table_LRU and table_non_LRU lists */
+ hash_table_free(table_hash);
+ hash_table_free(table_id_hash);
+ hash_table_free(temp_id_hash);
+
+ const ulint hash_size = buf_pool_get_curr_size()
+ / (DICT_POOL_PER_TABLE_HASH * UNIV_WORD_SIZE);
+ table_hash = hash_create(hash_size);
+ table_id_hash = hash_create(hash_size);
+ temp_id_hash = hash_create(hash_size);
+
+ for (dict_table_t* table= UT_LIST_GET_FIRST(table_LRU); table;
+ table= UT_LIST_GET_NEXT(table_LRU, table))
+ {
+ ut_ad(!table->is_temporary());
+ ulint fold= ut_fold_string(table->name.m_name);
+ ulint id_fold= ut_fold_ull(table->id);
+
+ HASH_INSERT(dict_table_t, name_hash, table_hash, fold, table);
+ HASH_INSERT(dict_table_t, id_hash, table_id_hash, id_fold, table);
+ }
+
+ for (dict_table_t* table = UT_LIST_GET_FIRST(table_non_LRU); table;
+ table = UT_LIST_GET_NEXT(table_LRU, table)) {
+ ulint fold = ut_fold_string(table->name.m_name);
+ ulint id_fold = ut_fold_ull(table->id);
+
+ HASH_INSERT(dict_table_t, name_hash, table_hash, fold, table);
+
+ hash_table_t* id_hash = table->is_temporary()
+ ? temp_id_hash : table_id_hash;
+
+ HASH_INSERT(dict_table_t, id_hash, id_hash, id_fold, table);
+ }
+
+ mutex_exit(&mutex);
}
-/**********************************************************************//**
-Closes the data dictionary module. */
-void
-dict_close(void)
-/*============*/
+/** Close the data dictionary cache on shutdown. */
+void dict_sys_t::close()
{
- if (dict_sys == NULL) {
- /* This should only happen if a failure occurred
- during redo log processing. */
- return;
- }
-
- /* Acquire only because it's a pre-condition. */
- mutex_enter(&dict_sys->mutex);
-
- /* Free the hash elements. We don't remove them from the table
- because we are going to destroy the table anyway. */
- for (ulint i = 0; i < hash_get_n_cells(dict_sys->table_id_hash); i++) {
- dict_table_t* table;
+ ut_ad(this == &dict_sys);
+ if (!is_initialised()) return;
- table = static_cast<dict_table_t*>(
- HASH_GET_FIRST(dict_sys->table_hash, i));
+ mutex_enter(&mutex);
- while (table) {
- dict_table_t* prev_table = table;
+ /* Free the hash elements. We don't remove them from the table
+ because we are going to destroy the table anyway. */
+ for (ulint i = 0; i < hash_get_n_cells(table_hash); i++)
+ {
+ dict_table_t* table = static_cast<dict_table_t*>(HASH_GET_FIRST(table_hash,
+ i));
- table = static_cast<dict_table_t*>(
- HASH_GET_NEXT(name_hash, prev_table));
- ut_ad(prev_table->magic_n == DICT_TABLE_MAGIC_N);
- dict_table_remove_from_cache(prev_table);
- }
- }
+ while (table)
+ {
+ dict_table_t* prev_table = table;
+ table = static_cast<dict_table_t*>(HASH_GET_NEXT(name_hash, prev_table));
+ dict_sys.remove(prev_table);
+ }
+ }
- hash_table_free(dict_sys->table_hash);
+ hash_table_free(table_hash);
- /* The elements are the same instance as in dict_sys->table_hash,
- therefore we don't delete the individual elements. */
- hash_table_free(dict_sys->table_id_hash);
+ /* table_id_hash contains the same elements as in table_hash,
+ therefore we don't delete the individual elements. */
+ hash_table_free(table_id_hash);
- mutex_exit(&dict_sys->mutex);
- mutex_free(&dict_sys->mutex);
+ /* No temporary tables should exist at this point. */
+ hash_table_free(temp_id_hash);
- rw_lock_free(&dict_operation_lock);
+ mutex_exit(&mutex);
+ mutex_free(&mutex);
+ rw_lock_free(&latch);
- mutex_free(&dict_foreign_err_mutex);
+ mutex_free(&dict_foreign_err_mutex);
- if (dict_foreign_err_file) {
- fclose(dict_foreign_err_file);
- dict_foreign_err_file = NULL;
- }
+ if (dict_foreign_err_file)
+ {
+ fclose(dict_foreign_err_file);
+ dict_foreign_err_file = NULL;
+ }
- ut_free(dict_sys);
-
- dict_sys = NULL;
+ m_initialised= false;
}
#ifdef UNIV_DEBUG
@@ -6342,16 +5929,16 @@ dict_lru_validate(void)
{
dict_table_t* table;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
- for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
+ for (table = UT_LIST_GET_FIRST(dict_sys.table_LRU);
table != NULL;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
ut_a(table->can_be_evicted);
}
- for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU);
+ for (table = UT_LIST_GET_FIRST(dict_sys.table_non_LRU);
table != NULL;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
@@ -6360,62 +5947,6 @@ dict_lru_validate(void)
return(TRUE);
}
-
-/**********************************************************************//**
-Check if a table exists in the dict table LRU list.
-@return TRUE if table found in LRU list */
-static
-ibool
-dict_lru_find_table(
-/*================*/
- const dict_table_t* find_table) /*!< in: table to find */
-{
- dict_table_t* table;
-
- ut_ad(find_table != NULL);
- ut_ad(mutex_own(&dict_sys->mutex));
-
- for (table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
- table != NULL;
- table = UT_LIST_GET_NEXT(table_LRU, table)) {
-
- ut_a(table->can_be_evicted);
-
- if (table == find_table) {
- return(TRUE);
- }
- }
-
- return(FALSE);
-}
-
-/**********************************************************************//**
-Check if a table exists in the dict table non-LRU list.
-@return TRUE if table found in non-LRU list */
-static
-ibool
-dict_non_lru_find_table(
-/*====================*/
- const dict_table_t* find_table) /*!< in: table to find */
-{
- dict_table_t* table;
-
- ut_ad(find_table != NULL);
- ut_ad(mutex_own(&dict_sys->mutex));
-
- for (table = UT_LIST_GET_FIRST(dict_sys->table_non_LRU);
- table != NULL;
- table = UT_LIST_GET_NEXT(table_LRU, table)) {
-
- ut_a(!table->can_be_evicted);
-
- if (table == find_table) {
- return(TRUE);
- }
- }
-
- return(FALSE);
-}
#endif /* UNIV_DEBUG */
/*********************************************************************//**
Check an index to see whether its first fields are the columns in the array,
@@ -6539,6 +6070,7 @@ dict_index_zip_pad_update(
ulint fail_pct;
ut_ad(info);
+ ut_ad(info->pad % ZIP_PAD_INCR == 0);
total = info->success + info->failure;
@@ -6563,17 +6095,16 @@ dict_index_zip_pad_update(
if (fail_pct > zip_threshold) {
/* Compression failures are more then user defined
threshold. Increase the pad size to reduce chances of
- compression failures. */
- ut_ad(info->pad % ZIP_PAD_INCR == 0);
+ compression failures.
- /* Only do increment if it won't increase padding
+ Only do increment if it won't increase padding
beyond max pad size. */
if (info->pad + ZIP_PAD_INCR
< (srv_page_size * zip_pad_max) / 100) {
/* Use atomics even though we have the mutex.
This is to ensure that we are able to read
info->pad atomically. */
- my_atomic_addlint(&info->pad, ZIP_PAD_INCR);
+ info->pad += ZIP_PAD_INCR;
MONITOR_INC(MONITOR_PAD_INCREMENTS);
}
@@ -6591,11 +6122,10 @@ dict_index_zip_pad_update(
if (info->n_rounds >= ZIP_PAD_SUCCESSFUL_ROUND_LIMIT
&& info->pad > 0) {
- ut_ad(info->pad % ZIP_PAD_INCR == 0);
/* Use atomics even though we have the mutex.
This is to ensure that we are able to read
info->pad atomically. */
- my_atomic_addlint(&info->pad, ulint(-ZIP_PAD_INCR));
+ info->pad -= ZIP_PAD_INCR;
info->n_rounds = 0;
@@ -6618,10 +6148,10 @@ dict_index_zip_success(
return;
}
- dict_index_zip_pad_lock(index);
+ mutex_enter(&index->zip_pad.mutex);
++index->zip_pad.success;
dict_index_zip_pad_update(&index->zip_pad, zip_threshold);
- dict_index_zip_pad_unlock(index);
+ mutex_exit(&index->zip_pad.mutex);
}
/*********************************************************************//**
@@ -6638,10 +6168,10 @@ dict_index_zip_failure(
return;
}
- dict_index_zip_pad_lock(index);
+ mutex_enter(&index->zip_pad.mutex);
++index->zip_pad.failure;
dict_index_zip_pad_update(&index->zip_pad, zip_threshold);
- dict_index_zip_pad_unlock(index);
+ mutex_exit(&index->zip_pad.mutex);
}
/*********************************************************************//**
@@ -6662,7 +6192,7 @@ dict_index_zip_pad_optimal_page_size(
return(srv_page_size);
}
- pad = my_atomic_loadlint(&index->zip_pad.pad);
+ pad = index->zip_pad.pad;
ut_ad(pad < srv_page_size);
sz = srv_page_size - pad;
@@ -6705,8 +6235,8 @@ ulint
dict_sys_get_size()
{
/* No mutex; this is a very crude approximation anyway */
- ulint size = UT_LIST_GET_LEN(dict_sys->table_LRU)
- + UT_LIST_GET_LEN(dict_sys->table_non_LRU);
+ ulint size = UT_LIST_GET_LEN(dict_sys.table_LRU)
+ + UT_LIST_GET_LEN(dict_sys.table_non_LRU);
size *= sizeof(dict_table_t)
+ sizeof(dict_index_t) * 2
+ (sizeof(dict_col_t) + sizeof(dict_field_t)) * 10
@@ -6728,8 +6258,7 @@ dict_space_is_empty(
mtr_t mtr;
bool found = false;
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
@@ -6750,8 +6279,7 @@ dict_space_is_empty(
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
return(!found);
}
@@ -6769,8 +6297,7 @@ dict_space_get_id(
ulint name_len = strlen(name);
ulint id = ULINT_UNDEFINED;
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
@@ -6799,68 +6326,7 @@ dict_space_get_id(
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
return(id);
}
-
-/** Determine the extent size (in pages) for the given table
-@param[in] table the table whose extent size is being
- calculated.
-@return extent size in pages (256, 128 or 64) */
-ulint
-dict_table_extent_size(
- const dict_table_t* table)
-{
- const ulint mb_1 = 1024 * 1024;
- const ulint mb_2 = 2 * mb_1;
- const ulint mb_4 = 4 * mb_1;
-
- page_size_t page_size = dict_table_page_size(table);
- ulint pages_in_extent = FSP_EXTENT_SIZE;
-
- if (page_size.is_compressed()) {
-
- ulint disk_page_size = page_size.physical();
-
- switch (disk_page_size) {
- case 1024:
- pages_in_extent = mb_1/1024;
- break;
- case 2048:
- pages_in_extent = mb_1/2048;
- break;
- case 4096:
- pages_in_extent = mb_1/4096;
- break;
- case 8192:
- pages_in_extent = mb_1/8192;
- break;
- case 16384:
- pages_in_extent = mb_1/16384;
- break;
- case 32768:
- pages_in_extent = mb_2/32768;
- break;
- case 65536:
- pages_in_extent = mb_4/65536;
- break;
- default:
- ut_ad(0);
- }
- }
-
- return(pages_in_extent);
-}
-
-size_t
-dict_table_t::get_overflow_field_local_len() const
-{
- if (dict_table_has_atomic_blobs(this)) {
- /* new-format table: do not store any BLOB prefix locally */
- return BTR_EXTERN_FIELD_REF_SIZE;
- }
- /* up to MySQL 5.1: store a 768-byte prefix locally */
- return BTR_EXTERN_FIELD_REF_SIZE + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
-}
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index d901d5f7f4c..2889f5d83c8 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -220,7 +220,7 @@ dict_get_first_table_name_in_db(
ulint len;
mtr_t mtr;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
heap = mem_heap_create(1000);
@@ -421,6 +421,8 @@ dict_process_sys_indexes_rec(
const char* err_msg;
byte* buf;
+ ut_d(index->is_dummy = true);
+ ut_d(index->in_instant_init = false);
buf = static_cast<byte*>(mem_heap_alloc(heap, 8));
/* Parse the record, and get "dict_index_t" struct filled */
@@ -801,7 +803,7 @@ dict_get_first_path(
char* filepath = NULL;
mem_heap_t* heap = mem_heap_create(1024);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
mtr_start(&mtr);
@@ -879,8 +881,7 @@ dict_update_filepath(
dberr_t err = DB_SUCCESS;
trx_t* trx;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
trx = trx_create();
trx->op_info = "update filepath";
@@ -947,8 +948,7 @@ dict_replace_tablespace_and_filepath(
DBUG_EXECUTE_IF("innodb_fail_to_update_tablespace_dict",
return(DB_INTERRUPTED););
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
ut_ad(filepath);
trx = trx_create();
@@ -982,7 +982,7 @@ dict_sys_tables_rec_check(
const byte* field;
ulint len;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (rec_get_deleted_flag(rec, 0)) {
return("delete-marked record in SYS_TABLES");
@@ -1345,8 +1345,7 @@ static ulint dict_check_sys_tables()
DBUG_ENTER("dict_check_sys_tables");
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
mtr_start(&mtr);
@@ -1482,15 +1481,13 @@ void dict_check_tablespaces_and_store_max_id()
DBUG_ENTER("dict_check_tablespaces_and_store_max_id");
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
/* Initialize the max space_id from sys header */
- mtr_start(&mtr);
- ulint max_space_id = mtr_read_ulint(
- dict_hdr_get(&mtr) + DICT_HDR_MAX_SPACE_ID,
- MLOG_4BYTES, &mtr);
- mtr_commit(&mtr);
+ mtr.start();
+ ulint max_space_id = mach_read_from_4(DICT_HDR_MAX_SPACE_ID
+ + dict_hdr_get(&mtr));
+ mtr.commit();
fil_set_max_space_id_if_bigger(max_space_id);
@@ -1500,8 +1497,7 @@ void dict_check_tablespaces_and_store_max_id()
max_space_id = dict_check_sys_tables();
fil_set_max_space_id_if_bigger(max_space_id);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
DBUG_VOID_RETURN;
}
@@ -1784,7 +1780,7 @@ dict_load_columns(
mtr_t mtr;
ulint n_skipped = 0;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
mtr_start(&mtr);
@@ -1901,7 +1897,7 @@ dict_load_virtual_one_col(
mtr_t mtr;
ulint skipped = 0;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (v_col->num_base == 0) {
return;
@@ -1940,7 +1936,7 @@ dict_load_virtual_one_col(
btr_pcur_open_on_user_rec(sys_virtual_index, tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, &pcur, &mtr);
- for (i = 0; i < v_col->num_base + skipped; i++) {
+ for (i = 0; i < unsigned{v_col->num_base} + skipped; i++) {
const char* err_msg;
ulint pos;
@@ -2134,7 +2130,7 @@ dict_load_fields(
mtr_t mtr;
dberr_t error;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
mtr_start(&mtr);
@@ -2365,7 +2361,7 @@ dict_load_indexes(
mtr_t mtr;
dberr_t error = DB_SUCCESS;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
mtr_start(&mtr);
@@ -2559,7 +2555,7 @@ corrupted:
goto corrupted;
} else if (dict_is_sys_table(table->id)
&& (dict_index_is_clust(index)
- || ((table == dict_sys->sys_tables)
+ || ((table == dict_sys.sys_tables)
&& !strcmp("ID_IND", index->name)))) {
/* The index was created in memory already at booting
@@ -2659,7 +2655,7 @@ dict_save_data_dir_path(
dict_table_t* table, /*!< in/out: table */
const char* filepath) /*!< in: filepath of tablespace */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_a(DICT_TF_HAS_DATA_DIR(table->flags));
ut_a(!table->data_dir_path);
@@ -2686,7 +2682,7 @@ dict_save_data_dir_path(
/** Make sure the data_dir_path is saved in dict_table_t if DATA DIRECTORY
was used. Try to read it from the fil_system first, then from SYS_DATAFILES.
@param[in] table Table object
-@param[in] dict_mutex_own true if dict_sys->mutex is owned already */
+@param[in] dict_mutex_own true if dict_sys.mutex is owned already */
void
dict_get_and_save_data_dir_path(
dict_table_t* table,
@@ -2743,7 +2739,7 @@ dict_table_t* dict_load_table(const char* name, dict_err_ignore_t ignore_err)
DBUG_ENTER("dict_load_table");
DBUG_PRINT("dict_load_table", ("loading table: '%s'", name));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
result = dict_table_check_if_in_cache_low(name);
@@ -2824,7 +2820,7 @@ dict_load_tablespace(
}
/* Try to open the tablespace. We set the 2nd param (fix_dict) to
- false because we do not have an x-lock on dict_operation_lock */
+ false because we do not have an x-lock on dict_sys.latch */
table->space = fil_ibd_open(
true, false, FIL_TYPE_TABLESPACE, table->space_id,
dict_tf_to_fsp_flags(table->flags),
@@ -2877,7 +2873,7 @@ dict_load_table_one(
DBUG_ENTER("dict_load_table_one");
DBUG_PRINT("dict_load_table_one", ("table: %s", name.m_name));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
heap = mem_heap_create(32000);
@@ -2976,7 +2972,7 @@ err_exit:
<< " failed, the table has"
" corrupted clustered indexes. Turn on"
" 'innodb_force_load_corrupted' to drop it";
- dict_table_remove_from_cache(table);
+ dict_sys.remove(table);
table = NULL;
goto func_exit;
} else {
@@ -2998,8 +2994,7 @@ corrupted:
dict_table_get_first_index(table)->page);
mtr.start();
buf_block_t* block = buf_page_get(
- page_id,
- dict_table_page_size(table),
+ page_id, table->space->zip_size(),
RW_S_LATCH, &mtr);
const bool corrupted = !block
|| page_get_space_id(block->frame)
@@ -3044,7 +3039,7 @@ corrupted:
" foreign key indexes. Turn off"
" 'foreign_key_checks' and try again.";
- dict_table_remove_from_cache(table);
+ dict_sys.remove(table);
table = NULL;
} else {
dict_mem_table_fill_foreign_vcol_set(table);
@@ -3060,7 +3055,7 @@ corrupted:
if (!srv_force_recovery
|| !index
|| !index->is_primary()) {
- dict_table_remove_from_cache(table);
+ dict_sys.remove(table);
table = NULL;
} else if (index->is_corrupted()
&& table->is_readable()) {
@@ -3093,7 +3088,7 @@ func_exit:
} else if (table->can_be_evicted) {
/* fts_optimize_thread is not started yet.
So make the table as non-evictable from cache. */
- dict_table_move_from_lru_to_non_lru(table);
+ dict_sys.prevent_eviction(table);
}
}
@@ -3125,7 +3120,7 @@ dict_load_table_on_id(
dict_table_t* table;
mtr_t mtr;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
table = NULL;
@@ -3136,7 +3131,7 @@ dict_load_table_on_id(
mtr_start(&mtr);
/*---------------------------------------------------*/
/* Get the secondary index based on ID for table SYS_TABLES */
- sys_tables = dict_sys->sys_tables;
+ sys_tables = dict_sys.sys_tables;
sys_table_ids = dict_table_get_next_index(
dict_table_get_first_index(sys_tables));
ut_ad(!dict_table_is_comp(sys_tables));
@@ -3210,7 +3205,7 @@ dict_load_sys_table(
{
mem_heap_t* heap;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
heap = mem_heap_create(1000);
@@ -3247,7 +3242,7 @@ dict_load_foreign_cols(
mtr_t mtr;
size_t id_len;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
id_len = strlen(foreign->id);
@@ -3394,7 +3389,7 @@ dict_load_foreign(
DBUG_PRINT("dict_load_foreign",
("id: '%s', check_recursive: %d", id, check_recursive));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
id_len = strlen(id);
@@ -3570,7 +3565,7 @@ dict_load_foreigns(
DBUG_ENTER("dict_load_foreigns");
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
sys_foreign = dict_table_get_low("SYS_FOREIGN");
@@ -3729,7 +3724,7 @@ dict_load_table_id_on_index_id(
bool found = false;
mtr_t mtr;
- ut_ad(mutex_own(&(dict_sys->mutex)));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* NOTE that the operation of this function is protected by
the dictionary mutex, and therefore no deadlocks can occur
diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc
index 425aa6c8270..c36a15b80a8 100644
--- a/storage/innobase/dict/dict0mem.cc
+++ b/storage/innobase/dict/dict0mem.cc
@@ -37,6 +37,7 @@ Created 1/8/1996 Heikki Tuuri
#include "lock0lock.h"
#include "sync0sync.h"
#include "row0row.h"
+#include "sql_string.h"
#include <iostream>
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
@@ -115,6 +116,14 @@ operator<<(
return(s << ut_get_name(NULL, table_name.m_name));
}
+bool dict_col_t::same_encoding(uint16_t a, uint16_t b)
+{
+ if (const CHARSET_INFO *acs= get_charset(a, MYF(MY_WME)))
+ if (const CHARSET_INFO *bcs= get_charset(b, MYF(MY_WME)))
+ return Charset(acs).same_encoding(bcs);
+ return false;
+}
+
/**********************************************************************//**
Creates a table memory object.
@return own: table object */
@@ -167,17 +176,13 @@ dict_mem_table_create(
mem_heap_alloc(heap, table->n_cols * sizeof(dict_col_t)));
table->v_cols = static_cast<dict_v_col_t*>(
mem_heap_alloc(heap, n_v_cols * sizeof(*table->v_cols)));
-
- /* true means that the stats latch will be enabled -
- dict_table_stats_lock() will not be noop. */
- dict_table_stats_latch_create(table, true);
+ for (ulint i = n_v_cols; i--; ) {
+ new (&table->v_cols[i]) dict_v_col_t();
+ }
table->autoinc_lock = static_cast<ib_lock_t*>(
mem_heap_alloc(heap, lock_get_size()));
- /* lazy creation of table autoinc latch */
- dict_table_autoinc_create_lazy(table);
-
/* If the table has an FTS index or we are in the process
of building one, create the table->fts */
if (dict_table_has_fts_index(table)
@@ -185,13 +190,14 @@ dict_mem_table_create(
|| DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_ADD_DOC_ID)) {
table->fts = fts_create(table);
table->fts->cache = fts_cache_create(table);
- } else {
- table->fts = NULL;
}
new(&table->foreign_set) dict_foreign_set();
new(&table->referenced_set) dict_foreign_set();
+ rw_lock_create(dict_table_stats_key, &table->stats_latch,
+ SYNC_INDEX_TREE);
+
return(table);
}
@@ -216,9 +222,7 @@ dict_mem_table_free(
}
}
- dict_table_autoinc_destroy(table);
dict_mem_table_free_foreign_vcol_set(table);
- dict_table_stats_latch_destroy(table);
table->foreign_set.~dict_foreign_set();
table->referenced_set.~dict_foreign_set();
@@ -229,15 +233,12 @@ dict_mem_table_free(
/* Clean up virtual index info structures that are registered
with virtual columns */
for (ulint i = 0; i < table->n_v_def; i++) {
- dict_v_col_t* vcol
- = dict_table_get_nth_v_col(table, i);
-
- UT_DELETE(vcol->v_indexes);
+ dict_table_get_nth_v_col(table, i)->~dict_v_col_t();
}
- if (table->s_cols != NULL) {
- UT_DELETE(table->s_cols);
- }
+ UT_DELETE(table->s_cols);
+
+ rw_lock_free(&table->stats_latch);
mem_heap_free(table->heap);
}
@@ -416,7 +417,8 @@ dict_mem_table_add_v_col(
v_col->num_base = num_base;
/* Initialize the index list for virtual columns */
- v_col->v_indexes = UT_NEW_NOKEY(dict_v_idx_list());
+ ut_ad(v_col->v_indexes.empty());
+ v_col->n_v_indexes = 0;
return(v_col);
}
@@ -450,7 +452,7 @@ dict_mem_table_add_s_col(
}
s_col.num_base = num_base;
- table->s_cols->push_back(s_col);
+ table->s_cols->push_front(s_col);
}
/**********************************************************************//**
@@ -526,6 +528,14 @@ dict_mem_table_col_rename_low(
= dict_index_get_nth_field(
index, i);
+ ut_ad(!field->name
+ == field->col->is_dropped());
+ if (!field->name) {
+ /* dropped columns lack a name */
+ ut_ad(index->is_instant());
+ continue;
+ }
+
/* if is_virtual and that in field->col does
not match, continue */
if ((!is_virtual) !=
@@ -710,6 +720,7 @@ dict_mem_fill_column_struct(
column->mbmaxlen = mbmaxlen;
column->def_val.data = NULL;
column->def_val.len = UNIV_SQL_DEFAULT;
+ ut_ad(!column->is_dropped());
}
/**********************************************************************//**
@@ -738,17 +749,15 @@ dict_mem_index_create(
dict_mem_fill_index_struct(index, heap, index_name, type, n_fields);
- dict_index_zip_pad_mutex_create_lazy(index);
+ mutex_create(LATCH_ID_ZIP_PAD_MUTEX, &index->zip_pad.mutex);
if (type & DICT_SPATIAL) {
mutex_create(LATCH_ID_RTR_SSN_MUTEX, &index->rtr_ssn.mutex);
- index->rtr_track = static_cast<rtr_info_track_t*>(
- mem_heap_alloc(
- heap,
- sizeof(*index->rtr_track)));
+ index->rtr_track = new
+ (mem_heap_alloc(heap, sizeof *index->rtr_track))
+ rtr_info_track_t();
mutex_create(LATCH_ID_RTR_ACTIVE_MUTEX,
&index->rtr_track->rtr_active_mutex);
- index->rtr_track->rtr_active = UT_NEW_NOKEY(rtr_info_active());
}
return(index);
@@ -856,11 +865,7 @@ dict_mem_fill_vcol_has_index(
continue;
}
- dict_v_idx_list::iterator it;
- for (it = v_col->v_indexes->begin();
- it != v_col->v_indexes->end(); ++it) {
- dict_v_idx_t v_idx = *it;
-
+ for (const auto& v_idx : v_col->v_indexes) {
if (v_idx.index != index) {
continue;
}
@@ -933,7 +938,7 @@ dict_mem_fill_vcol_set_for_base_col(
continue;
}
- for (ulint j = 0; j < v_col->num_base; j++) {
+ for (ulint j = 0; j < unsigned{v_col->num_base}; j++) {
if (strcmp(col_name, dict_table_get_col_name(
table,
v_col->base_col[j]->ind)) == 0) {
@@ -1054,25 +1059,18 @@ dict_mem_index_free(
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- dict_index_zip_pad_mutex_destroy(index);
+ mutex_free(&index->zip_pad.mutex);
if (dict_index_is_spatial(index)) {
- rtr_info_active::iterator it;
- rtr_info_t* rtr_info;
-
- for (it = index->rtr_track->rtr_active->begin();
- it != index->rtr_track->rtr_active->end(); ++it) {
- rtr_info = *it;
-
+ for (auto& rtr_info : index->rtr_track->rtr_active) {
rtr_info->index = NULL;
}
-
mutex_destroy(&index->rtr_ssn.mutex);
mutex_destroy(&index->rtr_track->rtr_active_mutex);
- UT_DELETE(index->rtr_track->rtr_active);
+ index->rtr_track->~rtr_info_track_t();
}
- dict_index_remove_from_v_col_list(index);
+ index->detach_columns();
mem_heap_free(index->heap);
}
@@ -1159,293 +1157,122 @@ operator<< (std::ostream& out, const dict_foreign_set& fk_set)
return(out);
}
-/** Adjust clustered index metadata for instant ADD COLUMN.
-@param[in] clustered index definition after instant ADD COLUMN */
-inline void dict_index_t::instant_add_field(const dict_index_t& instant)
+/** Reconstruct the clustered index fields. */
+inline void dict_index_t::reconstruct_fields()
{
DBUG_ASSERT(is_primary());
- DBUG_ASSERT(instant.is_primary());
- DBUG_ASSERT(!instant.is_instant());
- DBUG_ASSERT(n_def == n_fields);
- DBUG_ASSERT(instant.n_def == instant.n_fields);
-
- DBUG_ASSERT(type == instant.type);
- DBUG_ASSERT(trx_id_offset == instant.trx_id_offset);
- DBUG_ASSERT(n_user_defined_cols == instant.n_user_defined_cols);
- DBUG_ASSERT(n_uniq == instant.n_uniq);
- DBUG_ASSERT(instant.n_fields > n_fields);
- DBUG_ASSERT(instant.n_def > n_def);
- DBUG_ASSERT(instant.n_nullable >= n_nullable);
- DBUG_ASSERT(instant.n_core_fields >= n_core_fields);
- DBUG_ASSERT(instant.n_core_null_bytes >= n_core_null_bytes);
-
- n_fields = instant.n_fields;
- n_def = instant.n_def;
- n_nullable = instant.n_nullable;
- fields = static_cast<dict_field_t*>(
- mem_heap_dup(heap, instant.fields, n_fields * sizeof *fields));
-
- ut_d(unsigned n_null = 0);
-
- for (unsigned i = 0; i < n_fields; i++) {
- DBUG_ASSERT(fields[i].same(instant.fields[i]));
- const dict_col_t* icol = instant.fields[i].col;
- DBUG_ASSERT(!icol->is_virtual());
- dict_col_t* col = fields[i].col = &table->cols[
- icol - instant.table->cols];
- fields[i].name = col->name(*table);
- ut_d(n_null += col->is_nullable());
- }
- ut_ad(n_null == n_nullable);
-}
+ n_fields += table->instant->n_dropped;
+ n_def += table->instant->n_dropped;
-/** Adjust metadata for instant ADD COLUMN.
-@param[in] table table definition after instant ADD COLUMN */
-void dict_table_t::instant_add_column(const dict_table_t& table)
-{
- DBUG_ASSERT(!table.cached);
- DBUG_ASSERT(table.n_def == table.n_cols);
- DBUG_ASSERT(table.n_t_def == table.n_t_cols);
- DBUG_ASSERT(n_def == n_cols);
- DBUG_ASSERT(n_t_def == n_t_cols);
- DBUG_ASSERT(table.n_cols > n_cols);
- ut_ad(mutex_own(&dict_sys->mutex));
-
- const char* end = table.col_names;
- for (unsigned i = table.n_cols; i--; ) end += strlen(end) + 1;
-
- col_names = static_cast<char*>(
- mem_heap_dup(heap, table.col_names,
- ulint(end - table.col_names)));
- const dict_col_t* const old_cols = cols;
- const dict_col_t* const old_cols_end = cols + n_cols;
- cols = static_cast<dict_col_t*>(mem_heap_dup(heap, table.cols,
- table.n_cols
- * sizeof *cols));
-
- /* Preserve the default values of previously instantly
- added columns. */
- for (unsigned i = unsigned(n_cols) - DATA_N_SYS_COLS; i--; ) {
- cols[i].def_val = old_cols[i].def_val;
- }
+ const unsigned n_first = first_user_field();
+
+ dict_field_t* tfields = static_cast<dict_field_t*>(
+ mem_heap_zalloc(heap, n_fields * sizeof *fields));
+
+ memcpy(tfields, fields, n_first * sizeof *fields);
- /* Copy the new default values to this->heap. */
- for (unsigned i = n_cols; i < table.n_cols; i++) {
- dict_col_t& c = cols[i - DATA_N_SYS_COLS];
- DBUG_ASSERT(c.is_instant());
- if (c.def_val.len == 0) {
- c.def_val.data = field_ref_zero;
- } else if (const void*& d = c.def_val.data) {
- d = mem_heap_dup(heap, d, c.def_val.len);
+ n_nullable = 0;
+ ulint n_core_null = 0;
+ const bool comp = dict_table_is_comp(table);
+ const auto* field_map_it = table->instant->field_map;
+ for (unsigned i = n_first, j = 0; i < n_fields; ) {
+ dict_field_t& f = tfields[i++];
+ auto c = *field_map_it++;
+ if (c.is_dropped()) {
+ f.col = &table->instant->dropped[j++];
+ DBUG_ASSERT(f.col->is_dropped());
+ f.fixed_len = dict_col_get_fixed_size(f.col, comp);
} else {
- DBUG_ASSERT(c.def_val.len == UNIV_SQL_NULL);
+ DBUG_ASSERT(!c.is_not_null());
+ const auto old = std::find_if(
+ fields + n_first, fields + n_fields,
+ [c](const dict_field_t& o)
+ { return o.col->ind == c.ind(); });
+ ut_ad(old >= &fields[n_first]);
+ ut_ad(old < &fields[n_fields]);
+ DBUG_ASSERT(!old->prefix_len);
+ DBUG_ASSERT(old->col == &table->cols[c.ind()]);
+ f = *old;
}
- }
- const unsigned old_n_cols = n_cols;
- const unsigned n_add = unsigned(table.n_cols - n_cols);
-
- n_t_def += n_add;
- n_t_cols += n_add;
- n_cols = table.n_cols;
- n_def = n_cols;
-
- for (unsigned i = n_v_def; i--; ) {
- const dict_v_col_t& v = v_cols[i];
- for (ulint n = v.num_base; n--; ) {
- dict_col_t*& base = v.base_col[n];
- if (!base->is_virtual()) {
- DBUG_ASSERT(base >= old_cols);
- size_t n = size_t(base - old_cols);
- DBUG_ASSERT(n + DATA_N_SYS_COLS < old_n_cols);
- base = &cols[n];
- }
+ f.col->clear_instant();
+ if (f.col->is_nullable()) {
+ n_nullable++;
+ n_core_null += i <= n_core_fields;
}
}
- dict_index_t* index = dict_table_get_first_index(this);
-
- index->instant_add_field(*dict_table_get_first_index(&table));
-
- while ((index = dict_table_get_next_index(index)) != NULL) {
- for (unsigned i = 0; i < index->n_fields; i++) {
- dict_field_t& field = index->fields[i];
- if (field.col < old_cols
- || field.col >= old_cols_end) {
- DBUG_ASSERT(field.col->is_virtual());
- } else {
- /* Secondary indexes may contain user
- columns and DB_ROW_ID (if there is
- GEN_CLUST_INDEX instead of PRIMARY KEY),
- but not DB_TRX_ID,DB_ROLL_PTR. */
- DBUG_ASSERT(field.col >= old_cols);
- size_t n = size_t(field.col - old_cols);
- DBUG_ASSERT(n + DATA_N_SYS_COLS <= old_n_cols);
- if (n + DATA_N_SYS_COLS >= old_n_cols) {
- /* Replace DB_ROW_ID */
- n += n_add;
- }
- field.col = &cols[n];
- DBUG_ASSERT(!field.col->is_virtual());
- field.name = field.col->name(*this);
- }
- }
- }
+ fields = tfields;
+ n_core_null_bytes = UT_BITS_IN_BYTES(n_core_null);
}
-/** Roll back instant_add_column().
-@param[in] old_n_cols original n_cols
-@param[in] old_cols original cols
-@param[in] old_col_names original col_names */
-void
-dict_table_t::rollback_instant(
- unsigned old_n_cols,
- dict_col_t* old_cols,
- const char* old_col_names)
+/** Reconstruct dropped or reordered columns.
+@param[in] metadata data from serialise_columns()
+@param[in] len length of the metadata, in bytes
+@return whether parsing the metadata failed */
+bool dict_table_t::deserialise_columns(const byte* metadata, ulint len)
{
- ut_ad(mutex_own(&dict_sys->mutex));
- dict_index_t* index = indexes.start;
- /* index->is_instant() does not necessarily hold here, because
- the table may have been emptied */
- DBUG_ASSERT(old_n_cols >= DATA_N_SYS_COLS);
- DBUG_ASSERT(n_cols >= old_n_cols);
- DBUG_ASSERT(n_cols == n_def);
- DBUG_ASSERT(index->n_def == index->n_fields);
-
- const unsigned n_remove = n_cols - old_n_cols;
-
- for (unsigned i = index->n_fields - n_remove; i < index->n_fields;
- i++) {
- if (index->fields[i].col->is_nullable()) {
- index->n_nullable--;
- }
- }
+ DBUG_ASSERT(!instant);
- index->n_fields -= n_remove;
- index->n_def = index->n_fields;
- if (index->n_core_fields > index->n_fields) {
- index->n_core_fields = index->n_fields;
- index->n_core_null_bytes
- = UT_BITS_IN_BYTES(unsigned(index->n_nullable));
- }
+ unsigned num_non_pk_fields = mach_read_from_4(metadata);
+ metadata += 4;
- const dict_col_t* const new_cols = cols;
- const dict_col_t* const new_cols_end = cols + n_cols;
-
- cols = old_cols;
- col_names = old_col_names;
- n_cols = old_n_cols;
- n_def = old_n_cols;
- n_t_def -= n_remove;
- n_t_cols -= n_remove;
-
- for (unsigned i = n_v_def; i--; ) {
- const dict_v_col_t& v = v_cols[i];
- for (ulint n = v.num_base; n--; ) {
- dict_col_t*& base = v.base_col[n];
- if (!base->is_virtual()) {
- base = &cols[base - new_cols];
- }
- }
+ if (num_non_pk_fields >= REC_MAX_N_FIELDS - 3) {
+ return true;
}
- do {
- for (unsigned i = 0; i < index->n_fields; i++) {
- dict_field_t& field = index->fields[i];
- if (field.col < new_cols
- || field.col >= new_cols_end) {
- DBUG_ASSERT(field.col->is_virtual());
- } else {
- DBUG_ASSERT(field.col >= new_cols);
- size_t n = size_t(field.col - new_cols);
- DBUG_ASSERT(n <= n_cols);
- if (n + DATA_N_SYS_COLS >= n_cols) {
- n -= n_remove;
- }
- field.col = &cols[n];
- DBUG_ASSERT(!field.col->is_virtual());
- field.name = field.col->name(*this);
- }
- }
- } while ((index = dict_table_get_next_index(index)) != NULL);
-}
+ dict_index_t* index = UT_LIST_GET_FIRST(indexes);
-/** Trim the instantly added columns when an insert into SYS_COLUMNS
-is rolled back during ALTER TABLE or recovery.
-@param[in] n number of surviving non-system columns */
-void dict_table_t::rollback_instant(unsigned n)
-{
- ut_ad(mutex_own(&dict_sys->mutex));
- dict_index_t* index = indexes.start;
- DBUG_ASSERT(index->is_instant());
- DBUG_ASSERT(index->n_def == index->n_fields);
- DBUG_ASSERT(n_cols == n_def);
- DBUG_ASSERT(n >= index->n_uniq);
- DBUG_ASSERT(n_cols > n + DATA_N_SYS_COLS);
- const unsigned n_remove = n_cols - n - DATA_N_SYS_COLS;
-
- char* names = const_cast<char*>(dict_table_get_col_name(this, n));
- const char* sys = names;
- for (unsigned i = n_remove; i--; ) {
- sys += strlen(sys) + 1;
+ if (num_non_pk_fields < unsigned(index->n_fields)
+ - index->first_user_field()) {
+ return true;
}
- static const char system[] = "DB_ROW_ID\0DB_TRX_ID\0DB_ROLL_PTR";
- DBUG_ASSERT(!memcmp(sys, system, sizeof system));
- for (unsigned i = index->n_fields - n_remove; i < index->n_fields;
- i++) {
- if (index->fields[i].col->is_nullable()) {
- index->n_nullable--;
+
+ field_map_element_t* field_map = static_cast<field_map_element_t*>(
+ mem_heap_alloc(heap,
+ num_non_pk_fields * sizeof *field_map));
+
+ unsigned n_dropped_cols = 0;
+
+ for (unsigned i = 0; i < num_non_pk_fields; i++) {
+ auto c = field_map[i] = mach_read_from_2(metadata);
+ metadata += 2;
+
+ if (field_map[i].is_dropped()) {
+ if (c.ind() > DICT_MAX_FIXED_COL_LEN + 1) {
+ return true;
+ }
+ n_dropped_cols++;
+ } else if (c >= n_cols) {
+ return true;
}
}
- index->n_fields -= n_remove;
- index->n_def = index->n_fields;
- memmove(names, sys, sizeof system);
- memmove(cols + n, cols + n_cols - DATA_N_SYS_COLS,
- DATA_N_SYS_COLS * sizeof *cols);
- n_cols -= n_remove;
- n_def = n_cols;
- n_t_cols -= n_remove;
- n_t_def -= n_remove;
-
- for (unsigned i = DATA_N_SYS_COLS; i--; ) {
- cols[n_cols - i].ind--;
- }
- if (dict_index_is_auto_gen_clust(index)) {
- DBUG_ASSERT(index->n_uniq == 1);
- dict_field_t* field = index->fields;
- field->name = sys;
- field->col = dict_table_get_sys_col(this, DATA_ROW_ID);
- field++;
- field->name = sys + sizeof "DB_ROW_ID";
- field->col = dict_table_get_sys_col(this, DATA_TRX_ID);
- field++;
- field->name = sys + sizeof "DB_ROW_ID\0DB_TRX_ID";
- field->col = dict_table_get_sys_col(this, DATA_ROLL_PTR);
-
- /* Replace the DB_ROW_ID column in secondary indexes. */
- while ((index = dict_table_get_next_index(index)) != NULL) {
- field = &index->fields[index->n_fields - 1];
- DBUG_ASSERT(field->col->mtype == DATA_SYS);
- DBUG_ASSERT(field->col->prtype
- == DATA_NOT_NULL + DATA_TRX_ID);
- field->col--;
- field->name = sys;
+ dict_col_t* dropped_cols = static_cast<dict_col_t*>(mem_heap_zalloc(
+ heap, n_dropped_cols * sizeof(dict_col_t)));
+ instant = new (mem_heap_alloc(heap, sizeof *instant)) dict_instant_t();
+ instant->n_dropped = n_dropped_cols;
+ instant->dropped = dropped_cols;
+ instant->field_map = field_map;
+
+ dict_col_t* col = dropped_cols;
+ for (unsigned i = 0; i < num_non_pk_fields; i++) {
+ if (field_map[i].is_dropped()) {
+ auto fixed_len = field_map[i].ind();
+ DBUG_ASSERT(fixed_len <= DICT_MAX_FIXED_COL_LEN + 1);
+ (col++)->set_dropped(field_map[i].is_not_null(),
+ fixed_len == 1,
+ fixed_len > 1 ? fixed_len - 1
+ : 0);
}
-
- return;
}
+ DBUG_ASSERT(col == &dropped_cols[n_dropped_cols]);
- dict_field_t* field = &index->fields[index->n_uniq];
- field->name = sys + sizeof "DB_ROW_ID";
- field->col = dict_table_get_sys_col(this, DATA_TRX_ID);
- field++;
- field->name = sys + sizeof "DB_ROW_ID\0DB_TRX_ID";
- field->col = dict_table_get_sys_col(this, DATA_ROLL_PTR);
+ UT_LIST_GET_FIRST(indexes)->reconstruct_fields();
+ return false;
}
-
/** Check if record in clustered index is historical row.
@param[in] rec clustered row
@param[in] offsets offsets
diff --git a/storage/innobase/dict/dict0stats.cc b/storage/innobase/dict/dict0stats.cc
index f60d574d3b9..c420d7a3c14 100644
--- a/storage/innobase/dict/dict0stats.cc
+++ b/storage/innobase/dict/dict0stats.cc
@@ -33,6 +33,7 @@ Created Jan 06, 2010 Vasil Dimov
#include "pars0pars.h"
#include <mysql_com.h>
#include "btr0btr.h"
+#include "sync0sync.h"
#include <algorithm>
#include <map>
@@ -167,7 +168,7 @@ bool
dict_stats_persistent_storage_check(
/*================================*/
bool caller_has_dict_sys_mutex) /*!< in: true if the caller
- owns dict_sys->mutex */
+ owns dict_sys.mutex */
{
/* definition for the table TABLE_STATS_NAME */
dict_col_meta_t table_stats_columns[] = {
@@ -235,10 +236,10 @@ dict_stats_persistent_storage_check(
dberr_t ret;
if (!caller_has_dict_sys_mutex) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* first check table_stats */
ret = dict_table_schema_check(&table_stats_schema, errstr,
@@ -250,7 +251,7 @@ dict_stats_persistent_storage_check(
}
if (!caller_has_dict_sys_mutex) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
if (ret != DB_SUCCESS && ret != DB_STATS_DO_NOT_EXIST) {
@@ -283,8 +284,7 @@ dict_stats_exec_sql(
dberr_t err;
bool trx_started = false;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
if (!dict_stats_persistent_storage_check(true)) {
pars_info_free(pinfo);
@@ -418,11 +418,6 @@ dict_stats_table_clone_create(
t->corrupted = table->corrupted;
- /* This private object "t" is not shared with other threads, so
- we do not need the stats_latch (thus we pass false below). The
- dict_table_stats_lock()/unlock() routines will do nothing. */
- dict_table_stats_latch_create(t, false);
-
UT_LIST_INIT(t->indexes, &dict_index_t::indexes);
for (index = dict_table_get_first_index(table);
@@ -485,6 +480,8 @@ dict_stats_table_clone_create(
ut_d(t->magic_n = DICT_TABLE_MAGIC_N);
+ rw_lock_create(dict_table_stats_key, &t->stats_latch, SYNC_INDEX_TREE);
+
return(t);
}
@@ -497,15 +494,13 @@ dict_stats_table_clone_free(
/*========================*/
dict_table_t* t) /*!< in: dummy table object to free */
{
- dict_table_stats_latch_destroy(t);
+ rw_lock_free(&t->stats_latch);
mem_heap_free(t->heap);
}
/*********************************************************************//**
Write all zeros (or 1 where it makes sense) into an index
-statistics members. The resulting stats correspond to an empty index.
-The caller must own index's table stats latch in X mode
-(dict_table_stats_lock(table, RW_X_LATCH)) */
+statistics members. The resulting stats correspond to an empty index. */
static
void
dict_stats_empty_index(
@@ -516,6 +511,7 @@ dict_stats_empty_index(
{
ut_ad(!(index->type & DICT_FTS));
ut_ad(!dict_index_is_ibuf(index));
+ ut_ad(rw_lock_own(&index->table->stats_latch, RW_LOCK_X));
ulint n_uniq = index->n_uniq;
@@ -547,7 +543,7 @@ dict_stats_empty_table(
{
/* Zero the stats members */
- dict_table_stats_lock(table, RW_X_LATCH);
+ rw_lock_x_lock(&table->stats_latch);
table->stat_n_rows = 0;
table->stat_clustered_index_size = 1;
@@ -573,7 +569,7 @@ dict_stats_empty_table(
table->stat_initialized = TRUE;
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
}
/*********************************************************************//**
@@ -787,9 +783,9 @@ dict_table_t*
dict_stats_snapshot_create(
dict_table_t* table)
{
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
- dict_table_stats_lock(table, RW_S_LATCH);
+ rw_lock_s_lock(&table->stats_latch);
dict_stats_assert_initialized(table);
@@ -804,9 +800,9 @@ dict_stats_snapshot_create(
t->stats_sample_pages = table->stats_sample_pages;
t->stats_bg_flag = table->stats_bg_flag;
- dict_table_stats_unlock(table, RW_S_LATCH);
+ rw_lock_s_unlock(&table->stats_latch);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return(t);
}
@@ -1491,7 +1487,7 @@ dict_stats_analyze_index_below_cur(
page_id_t page_id(index->table->space_id,
btr_node_ptr_get_child_page_no(
rec, offsets_rec));
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* assume no external pages by default - in case we quit from this
function without analyzing any leaf pages */
@@ -1504,7 +1500,7 @@ dict_stats_analyze_index_below_cur(
dberr_t err = DB_SUCCESS;
- block = buf_page_get_gen(page_id, page_size, RW_S_LATCH,
+ block = buf_page_get_gen(page_id, zip_size, RW_S_LATCH,
NULL /* no guessed block */,
BUF_GET, __FILE__, __LINE__, &mtr, &err);
@@ -2198,7 +2194,7 @@ dict_stats_update_persistent(
DEBUG_PRINTF("%s(table=%s)\n", __func__, table->name);
- dict_table_stats_lock(table, RW_X_LATCH);
+ rw_lock_x_lock(&table->stats_latch);
/* analyze the clustered index first */
@@ -2209,7 +2205,7 @@ dict_stats_update_persistent(
|| (index->type | DICT_UNIQUE) != (DICT_CLUSTERED | DICT_UNIQUE)) {
/* Table definition is corrupt */
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
dict_stats_empty_table(table, true);
return(DB_CORRUPTION);
@@ -2261,7 +2257,7 @@ dict_stats_update_persistent(
dict_stats_assert_initialized(table);
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
return(DB_SUCCESS);
}
@@ -2295,8 +2291,7 @@ dict_stats_save_index_stat(
char table_utf8[MAX_TABLE_UTF8_LEN];
ut_ad(!trx || trx->internal || trx->mysql_thd);
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
dict_fs2utf8(index->table->name.m_name, db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));
@@ -2430,8 +2425,7 @@ dict_stats_save(
table_utf8, sizeof(table_utf8));
const time_t now = time(NULL);
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
pinfo = pars_info_create();
@@ -2469,13 +2463,10 @@ dict_stats_save(
if (ret != DB_SUCCESS) {
ib::error() << "Cannot save table statistics for table "
<< table->name << ": " << ut_strerr(ret);
-
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
-
+func_exit:
+ dict_sys_unlock();
dict_stats_snapshot_free(table);
-
- return(ret);
+ return ret;
}
trx_t* trx = trx_create();
@@ -2576,13 +2567,7 @@ dict_stats_save(
end:
trx_free(trx);
-
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
-
- dict_stats_snapshot_free(table);
-
- return(ret);
+ goto func_exit;
}
/*********************************************************************//**
@@ -2949,7 +2934,7 @@ dict_stats_fetch_from_ps(
char db_utf8[MAX_DB_UTF8_LEN];
char table_utf8[MAX_TABLE_UTF8_LEN];
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
/* Initialize all stats to dummy values before fetching because if
the persistent storage contains incomplete stats (e.g. missing stats
@@ -3085,16 +3070,16 @@ dict_stats_update_for_index(
{
DBUG_ENTER("dict_stats_update_for_index");
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
if (dict_stats_is_persistent_enabled(index->table)) {
if (dict_stats_persistent_storage_check(false)) {
- dict_table_stats_lock(index->table, RW_X_LATCH);
+ rw_lock_x_lock(&index->table->stats_latch);
dict_stats_analyze_index(index);
index->table->stat_sum_of_other_index_sizes
+= index->stat_index_size;
- dict_table_stats_unlock(index->table, RW_X_LATCH);
+ rw_lock_x_unlock(&index->table->stats_latch);
dict_stats_save(index->table, &index->id);
DBUG_VOID_RETURN;
}
@@ -3115,9 +3100,9 @@ dict_stats_update_for_index(
}
}
- dict_table_stats_lock(index->table, RW_X_LATCH);
+ rw_lock_x_lock(&index->table->stats_latch);
dict_stats_update_transient_for_index(index);
- dict_table_stats_unlock(index->table, RW_X_LATCH);
+ rw_lock_x_unlock(&index->table->stats_latch);
DBUG_VOID_RETURN;
}
@@ -3136,7 +3121,7 @@ dict_stats_update(
the persistent statistics
storage */
{
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
if (!table->is_readable()) {
return (dict_stats_report_error(table));
@@ -3271,7 +3256,7 @@ dict_stats_update(
switch (err) {
case DB_SUCCESS:
- dict_table_stats_lock(table, RW_X_LATCH);
+ rw_lock_x_lock(&table->stats_latch);
/* Pass reset_ignored_indexes=true as parameter
to dict_stats_copy. This will cause statictics
@@ -3280,7 +3265,7 @@ dict_stats_update(
dict_stats_assert_initialized(table);
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
dict_stats_table_clone_free(t);
@@ -3335,11 +3320,11 @@ dict_stats_update(
transient:
- dict_table_stats_lock(table, RW_X_LATCH);
+ rw_lock_x_lock(&table->stats_latch);
dict_stats_update_transient(table);
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
return(DB_SUCCESS);
}
@@ -3369,7 +3354,7 @@ dict_stats_drop_index(
pars_info_t* pinfo;
dberr_t ret;
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
/* skip indexes whose table names do not contain a database name
e.g. if we are dropping an index from SYS_TABLES */
@@ -3389,8 +3374,7 @@ dict_stats_drop_index(
pars_info_add_str_literal(pinfo, "index_name", iname);
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
ret = dict_stats_exec_sql(
pinfo,
@@ -3402,8 +3386,7 @@ dict_stats_drop_index(
"index_name = :index_name;\n"
"END;\n", NULL);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
if (ret == DB_STATS_DO_NOT_EXIST) {
ret = DB_SUCCESS;
@@ -3451,8 +3434,7 @@ dict_stats_delete_from_table_stats(
pars_info_t* pinfo;
dberr_t ret;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@@ -3487,8 +3469,7 @@ dict_stats_delete_from_index_stats(
pars_info_t* pinfo;
dberr_t ret;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@@ -3524,8 +3505,7 @@ dict_stats_drop_table(
char table_utf8[MAX_TABLE_UTF8_LEN];
dberr_t ret;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
/* skip tables that do not contain a database name
e.g. if we are dropping SYS_TABLES */
@@ -3600,8 +3580,7 @@ dict_stats_rename_table_in_table_stats(
pars_info_t* pinfo;
dberr_t ret;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@@ -3644,8 +3623,7 @@ dict_stats_rename_table_in_index_stats(
pars_info_t* pinfo;
dberr_t ret;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
pinfo = pars_info_create();
@@ -3688,9 +3666,6 @@ dict_stats_rename_table(
char new_table_utf8[MAX_TABLE_UTF8_LEN];
dberr_t ret;
- ut_ad(!rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(!mutex_own(&dict_sys->mutex));
-
/* skip innodb_table_stats and innodb_index_stats themselves */
if (strcmp(old_name, TABLE_STATS_NAME) == 0
|| strcmp(old_name, INDEX_STATS_NAME) == 0
@@ -3706,8 +3681,7 @@ dict_stats_rename_table(
dict_fs2utf8(new_name, new_db_utf8, sizeof(new_db_utf8),
new_table_utf8, sizeof(new_table_utf8));
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
ulint n_attempts = 0;
do {
@@ -3727,11 +3701,9 @@ dict_stats_rename_table(
}
if (ret != DB_SUCCESS) {
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
os_thread_sleep(200000 /* 0.2 sec */);
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
}
} while ((ret == DB_DEADLOCK
|| ret == DB_DUPLICATE_KEY
@@ -3759,8 +3731,7 @@ dict_stats_rename_table(
TABLE_STATS_NAME_PRINT,
new_db_utf8, new_table_utf8,
old_db_utf8, old_table_utf8);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
return(ret);
}
/* else */
@@ -3783,19 +3754,16 @@ dict_stats_rename_table(
}
if (ret != DB_SUCCESS) {
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
os_thread_sleep(200000 /* 0.2 sec */);
- rw_lock_x_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ dict_sys_lock();
}
} while ((ret == DB_DEADLOCK
|| ret == DB_DUPLICATE_KEY
|| ret == DB_LOCK_WAIT_TIMEOUT)
&& n_attempts < 5);
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
if (ret != DB_SUCCESS) {
snprintf(errstr, errstr_sz,
@@ -3823,6 +3791,60 @@ dict_stats_rename_table(
return(ret);
}
+/*********************************************************************//**
+Renames an index in InnoDB persistent stats storage.
+This function creates its own transaction and commits it.
+@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
+if the persistent stats do not exist. */
+dberr_t
+dict_stats_rename_index(
+/*====================*/
+ const dict_table_t* table, /*!< in: table whose index
+ is renamed */
+ const char* old_index_name, /*!< in: old index name */
+ const char* new_index_name) /*!< in: new index name */
+{
+ dict_sys_lock();
+
+ if (!dict_stats_persistent_storage_check(true)) {
+ dict_sys_unlock();
+ return(DB_STATS_DO_NOT_EXIST);
+ }
+
+ char dbname_utf8[MAX_DB_UTF8_LEN];
+ char tablename_utf8[MAX_TABLE_UTF8_LEN];
+
+ dict_fs2utf8(table->name.m_name, dbname_utf8, sizeof(dbname_utf8),
+ tablename_utf8, sizeof(tablename_utf8));
+
+ pars_info_t* pinfo;
+
+ pinfo = pars_info_create();
+
+ pars_info_add_str_literal(pinfo, "dbname_utf8", dbname_utf8);
+ pars_info_add_str_literal(pinfo, "tablename_utf8", tablename_utf8);
+ pars_info_add_str_literal(pinfo, "new_index_name", new_index_name);
+ pars_info_add_str_literal(pinfo, "old_index_name", old_index_name);
+
+ dberr_t ret;
+
+ ret = dict_stats_exec_sql(
+ pinfo,
+ "PROCEDURE RENAME_INDEX_IN_INDEX_STATS () IS\n"
+ "BEGIN\n"
+ "UPDATE \"" INDEX_STATS_NAME "\" SET\n"
+ "index_name = :new_index_name\n"
+ "WHERE\n"
+ "database_name = :dbname_utf8 AND\n"
+ "table_name = :tablename_utf8 AND\n"
+ "index_name = :old_index_name;\n"
+ "END;\n", NULL);
+
+ dict_sys_unlock();
+
+ return(ret);
+}
+
/* tests @{ */
#ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS
@@ -3868,7 +3890,7 @@ test_dict_table_schema_check()
/* prevent any data dictionary modifications while we are checking
the tables' structure */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
/* check that a valid table is reported as valid */
schema.n_cols = 7;
@@ -3944,7 +3966,7 @@ test_dict_table_schema_check()
test_dict_table_schema_check_end:
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
/* @} */
diff --git a/storage/innobase/dict/dict0stats_bg.cc b/storage/innobase/dict/dict0stats_bg.cc
index 812c5c539f5..2985b6faf35 100644
--- a/storage/innobase/dict/dict0stats_bg.cc
+++ b/storage/innobase/dict/dict0stats_bg.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 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
@@ -156,7 +156,7 @@ void dict_stats_update_if_needed_func(dict_table_t* table)
#endif
{
ut_ad(table->stat_initialized);
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
ulonglong counter = table->stat_modified_counter++;
ulonglong n_rows = dict_table_get_n_rows(table);
@@ -180,7 +180,7 @@ void dict_stats_update_if_needed_func(dict_table_t* table)
lock waits to be enqueued at head of waiting
queue. */
if (thd
- && !wsrep_thd_is_applier(thd)
+ && !wsrep_thd_is_applying(thd)
&& wsrep_on(thd)
&& wsrep_thd_is_BF(thd, 0)) {
WSREP_DEBUG("Avoiding background statistics"
@@ -250,7 +250,7 @@ dict_stats_recalc_pool_del(
const dict_table_t* table) /*!< in: table to remove */
{
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
mutex_enter(&recalc_pool_mutex);
@@ -278,7 +278,7 @@ and restore the lock before it exits.
The background stats thread is guaranteed not to start using the specified
table after this function returns and before the caller unlocks the data
dictionary because it sets the BG_STAT_IN_PROGRESS bit in table->stats_bg_flag
-under dict_sys->mutex. */
+under dict_sys.mutex. */
void
dict_stats_wait_bg_to_stop_using_table(
/*===================================*/
@@ -309,11 +309,11 @@ dict_stats_thread_init()
any level would do here)
2) from dict_stats_update_if_needed()
and released without latching anything else in between. We know
- that dict_sys->mutex (SYNC_DICT) is not acquired when
+ that dict_sys.mutex (SYNC_DICT) is not acquired when
dict_stats_update_if_needed() is called and it may be acquired
inside that function (thus a level <=SYNC_DICT would do).
- 3) from row_drop_table_for_mysql() after dict_sys->mutex (SYNC_DICT)
- and dict_operation_lock (SYNC_DICT_OPERATION) have been locked
+ 3) from row_drop_table_for_mysql() after dict_sys.mutex (SYNC_DICT)
+ and dict_sys.latch (SYNC_DICT_OPERATION) have been locked
(thus a level <SYNC_DICT && <SYNC_DICT_OPERATION would do)
So we choose SYNC_STATS_AUTO_RECALC to be about below SYNC_DICT. */
@@ -370,14 +370,14 @@ dict_stats_process_entry_from_recalc_pool()
dict_table_t* table;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
table = dict_table_open_on_id(table_id, TRUE, DICT_TABLE_OP_NORMAL);
if (table == NULL) {
/* table does not exist, must have been DROPped
after its id was enqueued */
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return;
}
@@ -385,13 +385,13 @@ dict_stats_process_entry_from_recalc_pool()
if (!fil_table_accessible(table)) {
dict_table_close(table, TRUE, FALSE);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return;
}
table->stats_bg_flag |= BG_STAT_IN_PROGRESS;
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
/* time() could be expensive, the current function
is called once every time a table has been changed more than 10% and
@@ -414,13 +414,13 @@ dict_stats_process_entry_from_recalc_pool()
dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT);
}
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
table->stats_bg_flag = BG_STAT_NONE;
dict_table_close(table, TRUE, FALSE);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
#ifdef UNIV_DEBUG
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 496f428c1ba..bd22e78c5b2 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -23,16 +23,16 @@ Created Jonas Oreland Google
Modified Jan Lindström jan.lindstrom@mariadb.com
*******************************************************/
-#include "fil0fil.h"
+#include "fil0crypt.h"
#include "mtr0types.h"
#include "mach0data.h"
-#include "page0size.h"
#include "page0zip.h"
-#ifndef UNIV_INNOCHECKSUM
-#include "fil0crypt.h"
+#include "buf0checksum.h"
+#ifdef UNIV_INNOCHECKSUM
+# include "buf0buf.h"
+#else
#include "srv0srv.h"
#include "srv0start.h"
-#include "log0recv.h"
#include "mtr0mtr.h"
#include "mtr0log.h"
#include "ut0ut.h"
@@ -274,16 +274,14 @@ fil_space_merge_crypt_data(
}
/** Initialize encryption parameters from a tablespace header page.
-@param[in] page_size page size of the tablespace
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] page first page of the tablespace
@return crypt data from page 0
@retval NULL if not present or not valid */
-UNIV_INTERN
-fil_space_crypt_t*
-fil_space_read_crypt_data(const page_size_t& page_size, const byte* page)
+fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page)
{
const ulint offset = FSP_HEADER_OFFSET
- + fsp_header_get_encryption_offset(page_size);
+ + fsp_header_get_encryption_offset(zip_size);
if (memcmp(page + offset, CRYPT_MAGIC, MAGIC_SZ) != 0) {
/* Crypt data is not stored. */
@@ -367,7 +365,8 @@ fil_space_crypt_t::fill_page0(
{
const uint len = sizeof(iv);
const ulint offset = FSP_HEADER_OFFSET
- + fsp_header_get_encryption_offset(page_size_t(flags));
+ + fsp_header_get_encryption_offset(
+ fil_space_t::zip_size(flags));
page0_offset = offset;
memcpy(page + offset, CRYPT_MAGIC, MAGIC_SZ);
@@ -398,7 +397,7 @@ fil_space_crypt_t::write_page0(
ut_ad(this == space->crypt_data);
const uint len = sizeof(iv);
const ulint offset = FSP_HEADER_OFFSET
- + fsp_header_get_encryption_offset(page_size_t(space->flags));
+ + fsp_header_get_encryption_offset(space->zip_size());
page0_offset = offset;
/*
@@ -537,29 +536,27 @@ fil_parse_write_crypt_data(
return ptr;
}
-/** Encrypt a buffer.
-@param[in,out] crypt_data Crypt data
-@param[in] space space_id
-@param[in] offset Page offset
-@param[in] lsn Log sequence number
-@param[in] src_frame Page to encrypt
-@param[in] page_size Page size
-@param[in,out] dst_frame Output buffer
+/** Encrypt a buffer for non full checksum.
+@param[in,out] crypt_data Crypt data
+@param[in] space space_id
+@param[in] offset Page offset
+@param[in] lsn Log sequence number
+@param[in] src_frame Page to encrypt
+@param[in] zip_size ROW_FORMAT=COMPRESSED
+ page size, or 0
+@param[in,out] dst_frame Output buffer
@return encrypted buffer or NULL */
-UNIV_INTERN
-byte*
-fil_encrypt_buf(
+static byte* fil_encrypt_buf_for_non_full_checksum(
fil_space_crypt_t* crypt_data,
ulint space,
ulint offset,
lsn_t lsn,
const byte* src_frame,
- const page_size_t& page_size,
+ ulint zip_size,
byte* dst_frame)
{
- uint size = uint(page_size.physical());
+ uint size = uint(zip_size ? zip_size : srv_page_size);
uint key_version = fil_crypt_get_latest_key_version(crypt_data);
-
ut_a(key_version != ENCRYPTION_KEY_VERSION_INVALID);
ulint orig_page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
@@ -567,21 +564,21 @@ fil_encrypt_buf(
uint header_len = FIL_PAGE_DATA;
if (page_compressed) {
- header_len += (FIL_PAGE_COMPRESSED_SIZE + FIL_PAGE_COMPRESSION_METHOD_SIZE);
+ header_len += FIL_PAGE_ENCRYPT_COMP_METADATA_LEN;
}
/* FIL page header is not encrypted */
memcpy(dst_frame, src_frame, header_len);
-
- /* Store key version */
- mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, key_version);
+ mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ key_version);
/* Calculate the start offset in a page */
- uint unencrypted_bytes = header_len + FIL_PAGE_DATA_END;
- uint srclen = size - unencrypted_bytes;
- const byte* src = src_frame + header_len;
- byte* dst = dst_frame + header_len;
- uint32 dstlen = 0;
+ uint unencrypted_bytes = header_len + FIL_PAGE_DATA_END;
+ uint srclen = size - unencrypted_bytes;
+ const byte* src = src_frame + header_len;
+ byte* dst = dst_frame + header_len;
+ uint32 dstlen = 0;
+ ib_uint32_t checksum = 0;
if (page_compressed) {
srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA);
@@ -599,30 +596,137 @@ fil_encrypt_buf(
to sector boundary is written. */
if (!page_compressed) {
/* FIL page trailer is also not encrypted */
- memcpy(dst_frame + page_size.physical() - FIL_PAGE_DATA_END,
- src_frame + page_size.physical() - FIL_PAGE_DATA_END,
+ memcpy(dst_frame + size - FIL_PAGE_DATA_END,
+ src_frame + size - FIL_PAGE_DATA_END,
FIL_PAGE_DATA_END);
} else {
/* Clean up rest of buffer */
memset(dst_frame+header_len+srclen, 0,
- page_size.physical() - (header_len + srclen));
+ size - (header_len + srclen));
}
- /* handle post encryption checksum */
- ib_uint32_t checksum = 0;
+ checksum = fil_crypt_calculate_checksum(zip_size, dst_frame);
+
+ /* store the post-encryption checksum after the key-version */
+ mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
+ checksum);
+
+ ut_ad(fil_space_verify_crypt_checksum(dst_frame, zip_size));
+
+ srv_stats.pages_encrypted.inc();
- checksum = fil_crypt_calculate_checksum(page_size, dst_frame);
+ return dst_frame;
+}
- // store the post-encryption checksum after the key-version
- mach_write_to_4(dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, checksum);
+/** Encrypt a buffer for full checksum format.
+@param[in,out] crypt_data Crypt data
+@param[in] space space_id
+@param[in] offset Page offset
+@param[in] lsn Log sequence number
+@param[in] src_frame Page to encrypt
+@param[in,out] dst_frame Output buffer
+@return encrypted buffer or NULL */
+static byte* fil_encrypt_buf_for_full_crc32(
+ fil_space_crypt_t* crypt_data,
+ ulint space,
+ ulint offset,
+ lsn_t lsn,
+ const byte* src_frame,
+ byte* dst_frame)
+{
+ uint key_version = fil_crypt_get_latest_key_version(crypt_data);
+ ut_d(bool corrupted = false);
+ const uint size = buf_page_full_crc32_size(src_frame, NULL,
+#ifdef UNIV_DEBUG
+ &corrupted
+#else
+ NULL
+#endif
+ );
+ ut_ad(!corrupted);
+ uint srclen = size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ + FIL_PAGE_FCRC32_CHECKSUM);
+ const byte* src = src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
+ byte* dst = dst_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
+ uint dstlen = 0;
+
+ ut_a(key_version != ENCRYPTION_KEY_VERSION_INVALID);
+
+ /* Till FIL_PAGE_LSN, page is not encrypted */
+ memcpy(dst_frame, src_frame, FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+
+ /* Write key version to the page. */
+ mach_write_to_4(dst_frame + FIL_PAGE_FCRC32_KEY_VERSION, key_version);
+
+ int rc = encryption_scheme_encrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ uint(space), uint(offset), lsn);
+ ut_a(rc == MY_AES_OK);
+ ut_a(dstlen == srclen);
- ut_ad(fil_space_verify_crypt_checksum(dst_frame, page_size));
+ const ulint payload = size - FIL_PAGE_FCRC32_CHECKSUM;
+ mach_write_to_4(dst_frame + payload, ut_crc32(dst_frame, payload));
+ /* Clean the rest of the buffer. FIXME: Punch holes when writing! */
+ memset(dst_frame + (payload + 4), 0, srv_page_size - (payload + 4));
srv_stats.pages_encrypted.inc();
return dst_frame;
}
+/** Encrypt a buffer.
+@param[in,out] crypt_data Crypt data
+@param[in] space space_id
+@param[in] offset Page offset
+@param[in] lsn Log sequence number
+@param[in] src_frame Page to encrypt
+@param[in] zip_size ROW_FORMAT=COMPRESSED
+ page size, or 0
+@param[in,out] dst_frame Output buffer
+@param[in] use_full_checksum full crc32 algo is used
+@return encrypted buffer or NULL */
+UNIV_INTERN
+byte*
+fil_encrypt_buf(
+ fil_space_crypt_t* crypt_data,
+ ulint space,
+ ulint offset,
+ lsn_t lsn,
+ const byte* src_frame,
+ ulint zip_size,
+ byte* dst_frame,
+ bool use_full_checksum)
+{
+ if (use_full_checksum) {
+ return fil_encrypt_buf_for_full_crc32(
+ crypt_data, space, offset,
+ lsn, src_frame, dst_frame);
+ }
+
+ return fil_encrypt_buf_for_non_full_checksum(
+ crypt_data, space, offset, lsn,
+ src_frame, zip_size, dst_frame);
+}
+
+/** Check whether these page types are allowed to encrypt.
+@param[in] space tablespace object
+@param[in] src_frame source page
+@return true if it is valid page type */
+static bool fil_space_encrypt_valid_page_type(
+ const fil_space_t* space,
+ byte* src_frame)
+{
+ switch (mach_read_from_2(src_frame+FIL_PAGE_TYPE)) {
+ case FIL_PAGE_RTREE:
+ return space->full_crc32();
+ case FIL_PAGE_TYPE_FSP_HDR:
+ case FIL_PAGE_TYPE_XDES:
+ return false;
+ }
+
+ return true;
+}
+
/******************************************************************
Encrypt a page
@@ -641,12 +745,7 @@ fil_space_encrypt(
byte* src_frame,
byte* dst_frame)
{
- switch (mach_read_from_2(src_frame+FIL_PAGE_TYPE)) {
- case FIL_PAGE_TYPE_FSP_HDR:
- case FIL_PAGE_TYPE_XDES:
- case FIL_PAGE_RTREE:
- /* File space header, extent descriptor or spatial index
- are not encrypted. */
+ if (!fil_space_encrypt_valid_page_type(space, src_frame)) {
return src_frame;
}
@@ -655,32 +754,104 @@ fil_space_encrypt(
}
ut_ad(space->pending_io());
+
return fil_encrypt_buf(space->crypt_data, space->id, offset, lsn,
- src_frame, page_size_t(space->flags),
- dst_frame);
+ src_frame, space->zip_size(),
+ dst_frame, space->full_crc32());
}
-/** Decrypt a page.
+/** Decrypt a page for full checksum format.
+@param[in] space space id
@param[in] crypt_data crypt_data
@param[in] tmp_frame Temporary buffer
-@param[in] page_size Page size
@param[in,out] src_frame Page to decrypt
@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
@return true if page decrypted, false if not.*/
-UNIV_INTERN
-bool
-fil_space_decrypt(
+static bool fil_space_decrypt_full_crc32(
+ ulint space,
+ fil_space_crypt_t* crypt_data,
+ byte* tmp_frame,
+ byte* src_frame,
+ dberr_t* err)
+{
+ uint key_version = mach_read_from_4(
+ src_frame + FIL_PAGE_FCRC32_KEY_VERSION);
+ lsn_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
+ uint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
+ *err = DB_SUCCESS;
+
+ if (key_version == ENCRYPTION_KEY_NOT_ENCRYPTED) {
+ return false;
+ }
+
+ ut_ad(crypt_data);
+ ut_ad(crypt_data->is_encrypted());
+
+ memcpy(tmp_frame, src_frame, FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+
+ /* Calculate the offset where decryption starts */
+ const byte* src = src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
+ byte* dst = tmp_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION;
+ uint dstlen = 0;
+ bool corrupted = false;
+ uint size = buf_page_full_crc32_size(src_frame, NULL, &corrupted);
+ if (UNIV_UNLIKELY(corrupted)) {
+fail:
+ *err = DB_DECRYPTION_FAILED;
+ return false;
+ }
+
+ uint srclen = size - (FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ + FIL_PAGE_FCRC32_CHECKSUM);
+
+ int rc = encryption_scheme_decrypt(src, srclen, dst, &dstlen,
+ crypt_data, key_version,
+ (uint) space, offset, lsn);
+
+ if (rc != MY_AES_OK || dstlen != srclen) {
+ if (rc == -1) {
+ goto fail;
+ }
+
+ ib::fatal() << "Unable to decrypt data-block "
+ << " src: " << src << "srclen: "
+ << srclen << " buf: " << dst << "buflen: "
+ << dstlen << " return-code: " << rc
+ << " Can't continue!";
+ }
+
+ /* Copy only checksum part in the trailer */
+ memcpy(tmp_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM,
+ src_frame + srv_page_size - FIL_PAGE_FCRC32_CHECKSUM,
+ FIL_PAGE_FCRC32_CHECKSUM);
+
+ srv_stats.pages_decrypted.inc();
+
+ return true; /* page was decrypted */
+}
+
+/** Decrypt a page for non full checksum format.
+@param[in] crypt_data crypt_data
+@param[in] tmp_frame Temporary buffer
+@param[in] physical_size page size
+@param[in,out] src_frame Page to decrypt
+@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
+@return true if page decrypted, false if not.*/
+static bool fil_space_decrypt_for_non_full_checksum(
fil_space_crypt_t* crypt_data,
byte* tmp_frame,
- const page_size_t& page_size,
+ ulint physical_size,
byte* src_frame,
dberr_t* err)
{
ulint page_type = mach_read_from_2(src_frame+FIL_PAGE_TYPE);
- uint key_version = mach_read_from_4(src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
- bool page_compressed = (page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
+ uint key_version = mach_read_from_4(
+ src_frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ bool page_compressed = (page_type
+ == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
uint offset = mach_read_from_4(src_frame + FIL_PAGE_OFFSET);
- uint space = mach_read_from_4(src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ uint space = mach_read_from_4(
+ src_frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
ib_uint64_t lsn = mach_read_from_8(src_frame + FIL_PAGE_LSN);
*err = DB_SUCCESS;
@@ -695,7 +866,7 @@ fil_space_decrypt(
uint header_len = FIL_PAGE_DATA;
if (page_compressed) {
- header_len += (FIL_PAGE_COMPRESSED_SIZE + FIL_PAGE_COMPRESSION_METHOD_SIZE);
+ header_len += FIL_PAGE_ENCRYPT_COMP_METADATA_LEN;
}
/* Copy FIL page header, it is not encrypted */
@@ -705,8 +876,7 @@ fil_space_decrypt(
const byte* src = src_frame + header_len;
byte* dst = tmp_frame + header_len;
uint32 dstlen = 0;
- uint srclen = uint(page_size.physical())
- - header_len - FIL_PAGE_DATA_END;
+ uint srclen = uint(physical_size) - header_len - FIL_PAGE_DATA_END;
if (page_compressed) {
srclen = mach_read_from_2(src_frame + FIL_PAGE_DATA);
@@ -736,8 +906,8 @@ fil_space_decrypt(
to sector boundary is written. */
if (!page_compressed) {
/* Copy FIL trailer */
- memcpy(tmp_frame + page_size.physical() - FIL_PAGE_DATA_END,
- src_frame + page_size.physical() - FIL_PAGE_DATA_END,
+ memcpy(tmp_frame + physical_size - FIL_PAGE_DATA_END,
+ src_frame + physical_size - FIL_PAGE_DATA_END,
FIL_PAGE_DATA_END);
}
@@ -746,6 +916,36 @@ fil_space_decrypt(
return true; /* page was decrypted */
}
+/** Decrypt a page.
+@param[in] space_id tablespace id
+@param[in] crypt_data crypt_data
+@param[in] tmp_frame Temporary buffer
+@param[in] physical_size page size
+@param[in] fsp_flags Tablespace flags
+@param[in,out] src_frame Page to decrypt
+@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
+@return true if page decrypted, false if not.*/
+UNIV_INTERN
+bool
+fil_space_decrypt(
+ ulint space_id,
+ fil_space_crypt_t* crypt_data,
+ byte* tmp_frame,
+ ulint physical_size,
+ ulint fsp_flags,
+ byte* src_frame,
+ dberr_t* err)
+{
+ if (fil_space_t::full_crc32(fsp_flags)) {
+ return fil_space_decrypt_full_crc32(
+ space_id, crypt_data, tmp_frame, src_frame, err);
+ }
+
+ return fil_space_decrypt_for_non_full_checksum(crypt_data, tmp_frame,
+ physical_size, src_frame,
+ err);
+}
+
/**
Decrypt a page.
@param[in] space Tablespace
@@ -762,19 +962,21 @@ fil_space_decrypt(
{
dberr_t err = DB_SUCCESS;
byte* res = NULL;
- const page_size_t page_size(space->flags);
+ const ulint physical_size = space->physical_size();
ut_ad(space->crypt_data != NULL && space->crypt_data->is_encrypted());
ut_ad(space->pending_io());
- bool encrypted = fil_space_decrypt(space->crypt_data, tmp_frame,
- page_size, src_frame, &err);
+ bool encrypted = fil_space_decrypt(space->id, space->crypt_data,
+ tmp_frame, physical_size,
+ space->flags,
+ src_frame, &err);
if (err == DB_SUCCESS) {
if (encrypted) {
/* Copy the decrypted page back to page buffer, not
really any other options. */
- memcpy(src_frame, tmp_frame, page_size.physical());
+ memcpy(src_frame, tmp_frame, physical_size);
}
res = src_frame;
@@ -783,21 +985,18 @@ fil_space_decrypt(
return res;
}
-/******************************************************************
+/**
Calculate post encryption checksum
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] dst_frame Block where checksum is calculated
@return page checksum
not needed. */
-UNIV_INTERN
uint32_t
-fil_crypt_calculate_checksum(
- const page_size_t& page_size,
- const byte* dst_frame)
+fil_crypt_calculate_checksum(ulint zip_size, const byte* dst_frame)
{
/* For encrypted tables we use only crc32 and strict_crc32 */
- return page_size.is_compressed()
- ? page_zip_calc_checksum(dst_frame, page_size.physical(),
+ return zip_size
+ ? page_zip_calc_checksum(dst_frame, zip_size,
SRV_CHECKSUM_ALGORITHM_CRC32)
: buf_calc_page_crc32(dst_frame);
}
@@ -909,15 +1108,15 @@ fil_crypt_read_crypt_data(fil_space_t* space)
return;
}
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
mtr_t mtr;
mtr.start();
if (buf_block_t* block = buf_page_get(page_id_t(space->id, 0),
- page_size, RW_S_LATCH, &mtr)) {
+ zip_size, RW_S_LATCH, &mtr)) {
mutex_enter(&fil_system.mutex);
if (!space->crypt_data) {
space->crypt_data = fil_space_read_crypt_data(
- page_size, block->frame);
+ zip_size, block->frame);
}
mutex_exit(&fil_system.mutex);
}
@@ -988,7 +1187,7 @@ static bool fil_crypt_start_encrypting_space(fil_space_t* space)
/* 2 - get page 0 */
dberr_t err = DB_SUCCESS;
buf_block_t* block = buf_page_get_gen(
- page_id_t(space->id, 0), page_size_t(space->flags),
+ page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__,
&mtr, &err);
@@ -1573,7 +1772,7 @@ fil_crypt_get_page_throttle_func(
unsigned line)
{
fil_space_t* space = state->space;
- const page_size_t page_size = page_size_t(space->flags);
+ const ulint zip_size = space->zip_size();
const page_id_t page_id(space->id, offset);
ut_ad(space->referenced());
@@ -1584,7 +1783,7 @@ fil_crypt_get_page_throttle_func(
}
dberr_t err = DB_SUCCESS;
- buf_block_t* block = buf_page_get_gen(page_id, page_size, RW_X_LATCH,
+ buf_block_t* block = buf_page_get_gen(page_id, zip_size, RW_X_LATCH,
NULL,
BUF_PEEK_IF_IN_POOL, file, line,
mtr, &err);
@@ -1601,7 +1800,7 @@ fil_crypt_get_page_throttle_func(
state->crypt_stat.pages_read_from_disk++;
const ulonglong start = my_interval_timer();
- block = buf_page_get_gen(page_id, page_size,
+ block = buf_page_get_gen(page_id, zip_size,
RW_X_LATCH,
NULL, BUF_GET_POSSIBLY_FREED,
file, line, mtr, &err);
@@ -1734,7 +1933,7 @@ fil_crypt_rotate_page(
int needs_scrubbing = BTR_SCRUB_SKIP_PAGE;
lsn_t block_lsn = block->page.newest_modification;
byte* frame = buf_block_get_frame(block);
- uint kv = mach_read_from_4(frame+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ uint kv = buf_page_get_key_version(frame, space->flags);
if (space->is_stopping()) {
/* The tablespace is closing (in DROP TABLE or
@@ -1978,7 +2177,7 @@ fil_crypt_flush_space(
dberr_t err;
if (buf_block_t* block = buf_page_get_gen(
- page_id_t(space->id, 0), page_size_t(space->flags),
+ page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, &mtr, &err)) {
mtr.set_named_space(space);
@@ -2555,10 +2754,9 @@ calculated checksum as if it does page could be valid unencrypted,
encrypted, or corrupted.
@param[in,out] page page frame (checksum is temporarily modified)
-@param[in] page_size page size
-@return whether the encrypted page is OK */
-bool
-fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return true if page is encrypted AND OK, false otherwise */
+bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
{
ut_ad(mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION));
@@ -2578,24 +2776,14 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
page is not corrupted. */
switch (srv_checksum_algorithm_t(srv_checksum_algorithm)) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- if (page_size.is_compressed()) {
+ if (zip_size) {
return checksum == page_zip_calc_checksum(
- page, page_size.physical(),
- SRV_CHECKSUM_ALGORITHM_CRC32)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- || checksum == page_zip_calc_checksum(
- page, page_size.physical(),
- SRV_CHECKSUM_ALGORITHM_CRC32, true)
-#endif
- ;
+ page, zip_size, SRV_CHECKSUM_ALGORITHM_CRC32);
}
- return checksum == buf_calc_page_crc32(page)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- || checksum == buf_calc_page_crc32(page, true)
-#endif
- ;
+ return checksum == buf_calc_page_crc32(page);
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
/* Starting with MariaDB 10.1.25, 10.2.7, 10.3.1,
due to MDEV-12114, fil_crypt_calculate_checksum()
@@ -2610,27 +2798,20 @@ fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
Due to this, we must treat "strict_innodb" as "innodb". */
case SRV_CHECKSUM_ALGORITHM_INNODB:
case SRV_CHECKSUM_ALGORITHM_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
if (checksum == BUF_NO_CHECKSUM_MAGIC) {
return true;
}
- if (page_size.is_compressed()) {
+ if (zip_size) {
return checksum == page_zip_calc_checksum(
- page, page_size.physical(),
+ page, zip_size,
SRV_CHECKSUM_ALGORITHM_CRC32)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- || checksum == page_zip_calc_checksum(
- page, page_size.physical(),
- SRV_CHECKSUM_ALGORITHM_CRC32, true)
-#endif
|| checksum == page_zip_calc_checksum(
- page, page_size.physical(),
+ page, zip_size,
SRV_CHECKSUM_ALGORITHM_INNODB);
}
return checksum == buf_calc_page_crc32(page)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- || checksum == buf_calc_page_crc32(page, true)
-#endif
|| checksum == buf_calc_page_new_checksum(page);
}
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 3484de8787a..b2fe9c01ca0 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -42,7 +42,6 @@ Created 10/25/1995 Heikki Tuuri
#include "os0file.h"
#include "page0zip.h"
#include "row0mysql.h"
-#include "row0trunc.h"
#include "srv0start.h"
#include "trx0purge.h"
#include "buf0lru.h"
@@ -51,6 +50,11 @@ Created 10/25/1995 Heikki Tuuri
#include "sync0sync.h"
#include "buf0flu.h"
#include "os0api.h"
+#ifdef UNIV_LINUX
+# include <sys/types.h>
+# include <sys/sysmacros.h>
+# include <dirent.h>
+#endif
/** Tries to close a file in the LRU list. The caller must hold the fil_sys
mutex.
@@ -166,9 +170,6 @@ ulint fil_n_pending_log_flushes = 0;
/** Number of pending tablespace flushes */
ulint fil_n_pending_tablespace_flushes = 0;
-/** The null file address */
-const fil_addr_t fil_addr_null = {FIL_NULL, 0};
-
/** The tablespace memory cache. This variable is NULL before the module is
initialized. */
fil_system_t fil_system;
@@ -208,19 +209,11 @@ fil_validate_skip(void)
/*===================*/
{
/** The fil_validate() call skip counter. */
- static int fil_validate_count = FIL_VALIDATE_SKIP;
+ static Atomic_counter<uint32_t> fil_validate_count;
/* We want to reduce the call frequency of the costly fil_validate()
check in debug builds. */
- int count = my_atomic_add32_explicit(&fil_validate_count, -1,
- MY_MEMORY_ORDER_RELAXED);
- if (count > 0) {
- return(true);
- }
-
- my_atomic_store32_explicit(&fil_validate_count, FIL_VALIDATE_SKIP,
- MY_MEMORY_ORDER_RELAXED);
- return(fil_validate());
+ return (fil_validate_count++ % FIL_VALIDATE_SKIP) || fil_validate();
}
#endif /* UNIV_DEBUG */
@@ -273,7 +266,7 @@ fil_node_complete_io(fil_node_t* node, const IORequest& type);
blocks at the end of file are ignored: they are not taken into account when
calculating the byte offset within a space.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to read; this must not cross a
@@ -286,12 +279,12 @@ UNIV_INLINE
dberr_t
fil_read(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf)
{
- return(fil_io(IORequestRead, true, page_id, page_size,
+ return(fil_io(IORequestRead, true, page_id, zip_size,
byte_offset, len, buf, NULL));
}
@@ -299,7 +292,7 @@ fil_read(
blocks at the end of file are ignored: they are not taken into account when
calculating the byte offset within a space.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to write; this must not cross
@@ -312,14 +305,14 @@ UNIV_INLINE
dberr_t
fil_write(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf)
{
ut_ad(!srv_read_only_mode);
- return(fil_io(IORequestWrite, true, page_id, page_size,
+ return(fil_io(IORequestWrite, true, page_id, zip_size,
byte_offset, len, buf, NULL));
}
@@ -393,20 +386,6 @@ fil_space_get_latch(
return(&(space->latch));
}
-/** Note that the tablespace has been imported.
-Initially, purpose=FIL_TYPE_IMPORT so that no redo log is
-written while the space ID is being updated in each page. */
-void fil_space_t::set_imported()
-{
- ut_ad(purpose == FIL_TYPE_IMPORT);
- const fil_node_t* node = UT_LIST_GET_FIRST(chain);
- atomic_write_supported = node->atomic_write
- && srv_use_atomic_writes
- && my_test_if_atomic_write(node->handle,
- int(page_size_t(flags).physical()));
- purpose = FIL_TYPE_TABLESPACE;
-}
-
/**********************************************************************//**
Checks if all the file nodes in a space are flushed.
@return true if all are flushed */
@@ -432,6 +411,42 @@ fil_space_is_flushed(
return(true);
}
+/** Validate the compression algorithm for full crc32 format.
+@param[in] space tablespace object
+@return whether the compression algorithm support */
+static bool fil_comp_algo_validate(const fil_space_t* space)
+{
+ if (!space->full_crc32()) {
+ return true;
+ }
+
+ DBUG_EXECUTE_IF("fil_comp_algo_validate_fail",
+ return false;);
+
+ ulint comp_algo = space->get_compression_algo();
+ switch (comp_algo) {
+ case PAGE_UNCOMPRESSED:
+ case PAGE_ZLIB_ALGORITHM:
+#ifdef HAVE_LZ4
+ case PAGE_LZ4_ALGORITHM:
+#endif /* HAVE_LZ4 */
+#ifdef HAVE_LZO
+ case PAGE_LZO_ALGORITHM:
+#endif /* HAVE_LZO */
+#ifdef HAVE_LZMA
+ case PAGE_LZMA_ALGORITHM:
+#endif /* HAVE_LZMA */
+#ifdef HAVE_BZIP2
+ case PAGE_BZIP2_ALGORITHM:
+#endif /* HAVE_BZIP2 */
+#ifdef HAVE_SNAPPY
+ case PAGE_SNAPPY_ALGORITHM:
+#endif /* HAVE_SNAPPY */
+ return true;
+ }
+
+ return false;
+}
/** Append a file to the chain of files of a space.
@param[in] name file name of a file that is not open
@@ -483,103 +498,6 @@ fil_node_t* fil_space_t::add(const char* name, pfs_os_file_t handle,
return node;
}
-/** Read the first page of a data file.
-@param[in] first whether this is the very first read
-@return whether the page was found valid */
-bool fil_node_t::read_page0(bool first)
-{
- ut_ad(mutex_own(&fil_system.mutex));
- ut_a(space->purpose != FIL_TYPE_LOG);
- const page_size_t page_size(space->flags);
- const ulint psize = page_size.physical();
-
- os_offset_t size_bytes = os_file_get_size(handle);
- ut_a(size_bytes != (os_offset_t) -1);
- const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE * psize;
-
- if (size_bytes < min_size) {
- ib::error() << "The size of the file " << name
- << " is only " << size_bytes
- << " bytes, should be at least " << min_size;
- return false;
- }
-
- byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize));
-
- /* Align the memory for file i/o if we might have O_DIRECT set */
- byte* page = static_cast<byte*>(ut_align(buf2, psize));
- IORequest request(IORequest::READ);
- if (os_file_read(request, handle, page, 0, psize) != DB_SUCCESS) {
- ib::error() << "Unable to read first page of file " << name;
- ut_free(buf2);
- return false;
- }
- srv_stats.page0_read.add(1);
- const ulint space_id = fsp_header_get_space_id(page);
- ulint flags = fsp_header_get_flags(page);
- const ulint size = fsp_header_get_field(page, FSP_SIZE);
- const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT);
- const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE
- + page);
- /* Try to read crypt_data from page 0 if it is not yet read. */
- if (!space->crypt_data) {
- space->crypt_data = fil_space_read_crypt_data(page_size, page);
- }
- ut_free(buf2);
-
- if (!fsp_flags_is_valid(flags, space->id)) {
- ulint cflags = fsp_flags_convert_from_101(flags);
- if (cflags == ULINT_UNDEFINED
- || (cflags ^ space->flags) & ~FSP_FLAGS_MEM_MASK) {
- ib::error()
- << "Expected tablespace flags "
- << ib::hex(space->flags)
- << " but found " << ib::hex(flags)
- << " in the file " << name;
- return false;
- }
-
- flags = cflags;
- }
-
- if (UNIV_UNLIKELY(space_id != space->id)) {
- ib::error() << "Expected tablespace id " << space->id
- << " but found " << space_id
- << " in the file " << name;
- return false;
- }
-
- if (first) {
- ut_ad(space->id != TRX_SYS_SPACE);
-
- /* Truncate the size to a multiple of extent size. */
- ulint mask = psize * FSP_EXTENT_SIZE - 1;
-
- if (size_bytes <= mask) {
- /* .ibd files start smaller than an
- extent size. Do not truncate valid data. */
- } else {
- size_bytes &= ~os_offset_t(mask);
- }
-
- this->size = ulint(size_bytes / psize);
- space->size += this->size;
- } else if (space->id != TRX_SYS_SPACE || space->size_in_header) {
- /* If this is not the first-time open, do nothing.
- For the system tablespace, we always get invoked as
- first=false, so we detect the true first-time-open based
- on size_in_header and proceed to initiailze the data. */
- return true;
- }
-
- ut_ad(space->free_limit == 0 || space->free_limit == free_limit);
- ut_ad(space->free_len == 0 || space->free_len == free_len);
- space->size_in_header = size;
- space->free_limit = free_limit;
- space->free_len = free_len;
- return true;
-}
-
/** Open a file node of a tablespace.
@param[in,out] node File node
@return false if the file can't be opened, otherwise true */
@@ -601,8 +519,7 @@ static bool fil_node_open_file(fil_node_t* node)
if (first_time_open
|| (space->purpose == FIL_TYPE_TABLESPACE
&& node == UT_LIST_GET_FIRST(space->chain)
- && srv_startup_is_before_trx_rollback_phase
- && !undo::Truncate::was_tablespace_truncated(space->id))) {
+ && srv_startup_is_before_trx_rollback_phase)) {
/* We do not know the size of the file yet. First we
open the file in the normal mode, no async I/O here,
for simplicity. Then do some checks, and close the
@@ -633,10 +550,16 @@ retry:
}
if (!node->read_page0(first_time_open)) {
+fail:
os_file_close(node->handle);
node->handle = OS_FILE_CLOSED;
return false;
}
+
+ if (first_time_open && !fil_comp_algo_validate(space)) {
+ goto fail;
+ }
+
} else if (space->purpose == FIL_TYPE_LOG) {
node->handle = os_file_create(
innodb_log_file_key, node->name, OS_FILE_OPEN,
@@ -650,30 +573,6 @@ retry:
OS_FILE_AIO, OS_DATA_FILE, read_only_mode, &success);
}
- if (space->purpose != FIL_TYPE_LOG) {
- /*
- For the temporary tablespace and during the
- non-redo-logged adjustments in
- IMPORT TABLESPACE, we do not care about
- the atomicity of writes.
-
- Atomic writes is supported if the file can be used
- with atomic_writes (not log file), O_DIRECT is
- used (tested in ha_innodb.cc) and the file is
- device and file system that supports atomic writes
- for the given block size
- */
- space->atomic_write_supported
- = space->purpose == FIL_TYPE_TEMPORARY
- || space->purpose == FIL_TYPE_IMPORT
- || (node->atomic_write
- && srv_use_atomic_writes
- && my_test_if_atomic_write(
- node->handle,
- int(page_size_t(space->flags)
- .physical())));
- }
-
ut_a(success);
ut_a(node->is_open());
@@ -936,14 +835,7 @@ fil_space_extend_must_retry(
ulint last_page_no = space->size;
const ulint file_start_page_no = last_page_no - node->size;
- /* Determine correct file block size */
- if (node->block_size == 0) {
- node->block_size = os_file_get_block_size(
- node->handle, node->name);
- }
-
- const page_size_t pageSize(space->flags);
- const ulint page_size = pageSize.physical();
+ const ulint page_size = space->physical_size();
/* fil_read_first_page() expects srv_page_size bytes.
fil_node_open_file() expects at least 4 * srv_page_size bytes.*/
@@ -1003,7 +895,6 @@ fil_space_extend_must_retry(
srv_tmp_space.set_last_file_size(pages_in_MiB);
return(false);
}
-
}
/*******************************************************************//**
@@ -1319,7 +1210,7 @@ fil_space_create(
fil_space_t* space;
ut_ad(fil_system.is_initialised());
- ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, id));
+ ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
ut_ad(purpose == FIL_TYPE_LOG
|| srv_page_size == UNIV_PAGE_SIZE_ORIG || flags != 0);
@@ -1401,8 +1292,8 @@ fil_space_create(
to do */
if (purpose == FIL_TYPE_TABLESPACE
&& !srv_fil_crypt_rotate_key_age && fil_crypt_threads_event &&
- (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF ||
- srv_encrypt_tables)) {
+ (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF
+ || srv_encrypt_tables)) {
/* Key rotation is not enabled, need to inform background
encryption threads. */
fil_system.rotation_list.push_back(*space);
@@ -1655,28 +1546,6 @@ void fil_space_t::close()
mutex_exit(&fil_system.mutex);
}
-/** Returns the page size of the space and whether it is compressed or not.
-The tablespace must be cached in the memory cache.
-@param[in] id space id
-@param[out] found true if tablespace was found
-@return page size */
-const page_size_t
-fil_space_get_page_size(
- ulint id,
- bool* found)
-{
- const ulint flags = fil_space_get_flags(id);
-
- if (flags == ULINT_UNDEFINED) {
- *found = false;
- return(univ_page_size);
- }
-
- *found = true;
-
- return(page_size_t(flags));
-}
-
void fil_system_t::create(ulint hash_size)
{
ut_ad(this == &fil_system);
@@ -1697,6 +1566,66 @@ void fil_system_t::create(ulint hash_size)
spaces = hash_create(hash_size);
fil_space_crypt_init();
+#ifdef UNIV_LINUX
+ ssd.clear();
+ char fn[sizeof(dirent::d_name)
+ + sizeof "/sys/block/" "/queue/rotational"];
+ const size_t sizeof_fnp = (sizeof fn) - sizeof "/sys/block";
+ memcpy(fn, "/sys/block/", sizeof "/sys/block");
+ char* fnp = &fn[sizeof "/sys/block"];
+
+ std::set<std::string> ssd_devices;
+ if (DIR* d = opendir("/sys/block")) {
+ while (struct dirent* e = readdir(d)) {
+ if (e->d_name[0] == '.') {
+ continue;
+ }
+ snprintf(fnp, sizeof_fnp, "%s/queue/rotational",
+ e->d_name);
+ int f = open(fn, O_RDONLY);
+ if (f == -1) {
+ continue;
+ }
+ char b[sizeof "4294967295:4294967295\n"];
+ ssize_t l = read(f, b, sizeof b);
+ ::close(f);
+ if (l != 2 || memcmp("0\n", b, 2)) {
+ continue;
+ }
+ snprintf(fnp, sizeof_fnp, "%s/dev", e->d_name);
+ f = open(fn, O_RDONLY);
+ if (f == -1) {
+ continue;
+ }
+ l = read(f, b, sizeof b);
+ ::close(f);
+ if (l <= 0 || b[l - 1] != '\n') {
+ continue;
+ }
+ b[l - 1] = '\0';
+ char* end = b;
+ unsigned long dev_major = strtoul(b, &end, 10);
+ if (b == end || *end != ':'
+ || dev_major != unsigned(dev_major)) {
+ continue;
+ }
+ char* c = end + 1;
+ unsigned long dev_minor = strtoul(c, &end, 10);
+ if (c == end || *end
+ || dev_minor != unsigned(dev_minor)) {
+ continue;
+ }
+ ssd.push_back(makedev(unsigned(dev_major),
+ unsigned(dev_minor)));
+ }
+ closedir(d);
+ }
+ /* fil_system_t::is_ssd() assumes the following */
+ ut_ad(makedev(0, 8) == 8);
+ ut_ad(makedev(0, 4) == 4);
+ ut_ad(makedev(0, 2) == 2);
+ ut_ad(makedev(0, 1) == 1);
+#endif
}
void fil_system_t::close()
@@ -1914,13 +1843,19 @@ fil_write_flushed_lsn(
const page_id_t page_id(TRX_SYS_SPACE, 0);
- err = fil_read(page_id, univ_page_size, 0, srv_page_size,
- buf);
+ err = fil_read(page_id, 0, 0, srv_page_size, buf);
if (err == DB_SUCCESS) {
mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, lsn);
- err = fil_write(page_id, univ_page_size, 0,
- srv_page_size, buf);
+
+ ulint fsp_flags = mach_read_from_4(
+ buf + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
+
+ if (fil_space_t::full_crc32(fsp_flags)) {
+ buf_flush_assign_full_crc32_checksum(buf);
+ }
+
+ err = fil_write(page_id, 0, 0, srv_page_size, buf);
fil_flush_file_spaces(FIL_TYPE_TABLESPACE);
}
@@ -1934,10 +1869,8 @@ for concurrency control.
@param[in] id tablespace ID
@param[in] silent whether to silently ignore missing tablespaces
@return the tablespace
-@retval NULL if missing or being deleted or truncated */
-UNIV_INTERN
-fil_space_t*
-fil_space_acquire_low(ulint id, bool silent)
+@retval NULL if missing or being deleted */
+fil_space_t* fil_space_acquire_low(ulint id, bool silent)
{
fil_space_t* space;
@@ -2037,7 +1970,7 @@ fil_op_write_log(
ulint len;
ut_ad(first_page_no == 0 || type == MLOG_FILE_CREATE2);
- ut_ad(fsp_flags_is_valid(flags, space_id));
+ ut_ad(fil_space_t::is_valid_flags(flags, space_id));
/* fil_name_parse() requires that there be at least one path
separator and that the file path end with ".ibd". */
@@ -2264,9 +2197,7 @@ enum fil_operation_t {
@param[in] space tablespace
@param[in] count number of attempts so far
@return 0 if no operations else count + 1. */
-static
-ulint
-fil_check_pending_ops(const fil_space_t* space, ulint count)
+static ulint fil_check_pending_ops(const fil_space_t* space, ulint count)
{
ut_ad(mutex_own(&fil_system.mutex));
@@ -2274,10 +2205,10 @@ fil_check_pending_ops(const fil_space_t* space, ulint count)
return 0;
}
- if (ulint n_pending_ops = my_atomic_loadlint(&space->n_pending_ops)) {
+ if (ulint n_pending_ops = space->n_pending_ops) {
if (count > 5000) {
- ib::warn() << "Trying to close/delete/truncate"
+ ib::warn() << "Trying to delete"
" tablespace '" << space->name
<< "' but there are " << n_pending_ops
<< " pending operations on it.";
@@ -2324,7 +2255,7 @@ fil_check_pending_io(
ut_a(!(*node)->being_extended);
if (count > 1000) {
- ib::warn() << "Trying to delete/close/truncate"
+ ib::warn() << "Trying to delete"
" tablespace '" << space->name
<< "' but there are "
<< space->n_pending_flushes
@@ -2954,6 +2885,9 @@ skip_second_rename:
return(success);
}
+/* FIXME: remove this! */
+IF_WIN(, bool os_is_sparse_file_supported(os_file_t fh));
+
/** Create a tablespace file.
@param[in] space_id Tablespace ID
@param[in] name Tablespace name in dbname/tablename format.
@@ -2982,14 +2916,12 @@ fil_ibd_create(
byte* page;
bool success;
bool has_data_dir = FSP_FLAGS_HAS_DATA_DIR(flags) != 0;
- fil_space_t* space = NULL;
- fil_space_crypt_t *crypt_data = NULL;
ut_ad(!is_system_tablespace(space_id));
ut_ad(!srv_read_only_mode);
ut_a(space_id < SRV_LOG_SPACE_FIRST_ID);
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
- ut_a(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, space_id));
+ ut_a(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, space_id));
/* Create the subdirectories in the path, if they are
not there already. */
@@ -3029,6 +2961,7 @@ fil_ibd_create(
}
const bool is_compressed = FSP_FLAGS_HAS_PAGE_COMPRESSION(flags);
+ bool punch_hole = is_compressed;
#ifdef _WIN32
if (is_compressed) {
@@ -3046,9 +2979,8 @@ err_exit:
return NULL;
}
- bool punch_hole = os_is_sparse_file_supported(file);
-
- ulint block_size = os_file_get_block_size(file, path);
+ /* FIXME: remove this */
+ IF_WIN(, punch_hole = punch_hole && os_is_sparse_file_supported(file));
/* We have to write the space id to the file immediately and flush the
file to disk. This is because in crash recovery we must be aware what
@@ -3065,16 +2997,21 @@ err_exit:
memset(page, '\0', srv_page_size);
- flags |= FSP_FLAGS_PAGE_SSIZE();
+ if (fil_space_t::full_crc32(flags)) {
+ flags |= FSP_FLAGS_FCRC32_PAGE_SSIZE();
+ } else {
+ flags |= FSP_FLAGS_PAGE_SSIZE();
+ }
+
fsp_header_init_fields(page, space_id, flags);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
/* Create crypt data if the tablespace is either encrypted or user has
requested it to remain unencrypted. */
- if (mode == FIL_ENCRYPTION_ON || mode == FIL_ENCRYPTION_OFF ||
- srv_encrypt_tables) {
- crypt_data = fil_space_create_crypt_data(mode, key_id);
- }
+ fil_space_crypt_t *crypt_data = (mode != FIL_ENCRYPTION_DEFAULT
+ || srv_encrypt_tables)
+ ? fil_space_create_crypt_data(mode, key_id)
+ : NULL;
if (crypt_data) {
/* Write crypt data information in page0 while creating
@@ -3082,18 +3019,9 @@ err_exit:
crypt_data->fill_page0(flags, page);
}
- const page_size_t page_size(flags);
- IORequest request(IORequest::WRITE);
-
- if (!page_size.is_compressed()) {
-
- buf_flush_init_for_writing(NULL, page, NULL, 0);
-
- *err = os_file_write(
- request, path, file, page, 0, page_size.physical());
- } else {
+ if (ulint zip_size = fil_space_t::zip_size(flags)) {
page_zip_des_t page_zip;
- page_zip_set_size(&page_zip, page_size.physical());
+ page_zip_set_size(&page_zip, zip_size);
page_zip.data = page + srv_page_size;
#ifdef UNIV_DEBUG
page_zip.m_start =
@@ -3101,11 +3029,16 @@ err_exit:
page_zip.m_end = page_zip.m_nonempty =
page_zip.n_blobs = 0;
- buf_flush_init_for_writing(NULL, page, &page_zip, 0);
+ buf_flush_init_for_writing(NULL, page, &page_zip, 0, false);
*err = os_file_write(
- request, path, file, page_zip.data, 0,
- page_size.physical());
+ IORequestWrite, path, file, page_zip.data, 0, zip_size);
+ } else {
+ buf_flush_init_for_writing(NULL, page, NULL, 0,
+ fil_space_t::full_crc32(flags));
+
+ *err = os_file_write(
+ IORequestWrite, path, file, page, 0, srv_page_size);
}
ut_free(buf2);
@@ -3133,25 +3066,26 @@ err_exit:
}
}
- space = fil_space_create(name, space_id, flags, FIL_TYPE_TABLESPACE,
- crypt_data, mode);
+ fil_space_t* space = fil_space_create(name, space_id, flags,
+ FIL_TYPE_TABLESPACE,
+ crypt_data, mode);
if (!space) {
free(crypt_data);
*err = DB_ERROR;
} else {
- fil_node_t* file = space->add(path, OS_FILE_CLOSED, size,
+ space->punch_hole = punch_hole;
+ /* FIXME: Keep the file open! */
+ fil_node_t* node = space->add(path, OS_FILE_CLOSED, size,
false, true);
mtr_t mtr;
mtr.start();
fil_op_write_log(
- MLOG_FILE_CREATE2, space_id, 0, file->name,
+ MLOG_FILE_CREATE2, space_id, 0, node->name,
NULL, space->flags & ~FSP_FLAGS_MEM_MASK, &mtr);
- fil_name_write(space, 0, file, &mtr);
+ fil_name_write(space, 0, node, &mtr);
mtr.commit();
- file->block_size = block_size;
- space->punch_hole = punch_hole;
-
+ node->find_metadata(file);
*err = DB_SUCCESS;
}
@@ -3243,11 +3177,12 @@ fil_ibd_open(
ulint tablespaces_found = 0;
ulint valid_tablespaces_found = 0;
- ut_ad(!fix_dict || rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ if (fix_dict) {
+ ut_d(dict_sys.assert_locked());
+ ut_ad(!srv_read_only_mode);
+ ut_ad(srv_log_file_size != 0);
+ }
- ut_ad(!fix_dict || mutex_own(&dict_sys->mutex));
- ut_ad(!fix_dict || !srv_read_only_mode);
- ut_ad(!fix_dict || srv_log_file_size != 0);
ut_ad(fil_type_is_data(purpose));
/* Table flags can be ULINT_UNDEFINED if
@@ -3258,7 +3193,7 @@ corrupted:
return NULL;
}
- ut_ad(fsp_flags_is_valid(flags & ~FSP_FLAGS_MEM_MASK, id));
+ ut_ad(fil_space_t::is_valid_flags(flags & ~FSP_FLAGS_MEM_MASK, id));
df_default.init(tablename.m_name, flags);
df_dict.init(tablename.m_name, flags);
df_remote.init(tablename.m_name, flags);
@@ -3512,7 +3447,8 @@ skip_validate:
df_remote.get_first_page();
fil_space_crypt_t* crypt_data = first_page
- ? fil_space_read_crypt_data(page_size_t(flags), first_page)
+ ? fil_space_read_crypt_data(fil_space_t::zip_size(flags),
+ first_page)
: NULL;
fil_space_t* space = fil_space_create(
@@ -3860,7 +3796,8 @@ fil_ibd_load(
const byte* first_page = file.get_first_page();
fil_space_crypt_t* crypt_data = first_page
- ? fil_space_read_crypt_data(page_size_t(flags), first_page)
+ ? fil_space_read_crypt_data(fil_space_t::zip_size(flags),
+ first_page)
: NULL;
space = fil_space_create(
file.name(), space_id, flags, FIL_TYPE_TABLESPACE, crypt_data);
@@ -3923,7 +3860,10 @@ fil_file_readdir_next_file(
void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
{
ut_ad(!srv_read_only_mode);
- ut_ad(fsp_flags_is_valid(flags, space->id));
+ ut_ad(fil_space_t::is_valid_flags(flags, space->id));
+ if (space->full_crc32() || fil_space_t::full_crc32(flags)) {
+ return;
+ }
if (!space->size && (space->purpose != FIL_TYPE_TABLESPACE
|| !fil_space_get_size(space->id))) {
return;
@@ -3934,9 +3874,15 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
mtr_t mtr;
mtr.start();
if (buf_block_t* b = buf_page_get(
- page_id_t(space->id, 0), page_size_t(flags),
+ page_id_t(space->id, 0), space->zip_size(),
RW_X_LATCH, &mtr)) {
ulint f = fsp_header_get_flags(b->frame);
+ if (fil_space_t::full_crc32(f)) {
+ goto func_exit;
+ }
+ if (fil_space_t::is_flags_equal(f, flags)) {
+ goto func_exit;
+ }
/* Suppress the message if only the DATA_DIR flag to differs. */
if ((f ^ flags) & ~(1U << FSP_FLAGS_POS_RESERVED)) {
ib::warn()
@@ -3945,13 +3891,11 @@ void fsp_flags_try_adjust(fil_space_t* space, ulint flags)
<< "' from " << ib::hex(f)
<< " to " << ib::hex(flags);
}
- if (f != flags) {
- mtr.set_named_space(space);
- mlog_write_ulint(FSP_HEADER_OFFSET
- + FSP_SPACE_FLAGS + b->frame,
- flags, MLOG_4BYTES, &mtr);
- }
+ mtr.set_named_space(space);
+ mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS
+ + b->frame, flags, MLOG_4BYTES, &mtr);
}
+func_exit:
mtr.commit();
}
@@ -3973,7 +3917,11 @@ fil_space_for_table_exists_in_mem(
mutex_enter(&fil_system.mutex);
if (fil_space_t* space = fil_space_get_by_id(id)) {
- if ((space->flags ^ expected_flags) & ~FSP_FLAGS_MEM_MASK) {
+ ulint tf = expected_flags & ~FSP_FLAGS_MEM_MASK;
+ ulint sf = space->flags & ~FSP_FLAGS_MEM_MASK;
+
+ if (!fil_space_t::is_flags_equal(tf, sf)
+ && !fil_space_t::is_flags_equal(sf, tf)) {
goto func_exit;
}
@@ -3990,7 +3938,8 @@ fil_space_for_table_exists_in_mem(
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
FSP_SPACE_FLAGS will not be written back here. */
- space->flags = expected_flags;
+ space->flags = (space->flags & ~FSP_FLAGS_MEM_MASK)
+ | (expected_flags & FSP_FLAGS_MEM_MASK);
mutex_exit(&fil_system.mutex);
if (!srv_read_only_mode) {
fsp_flags_try_adjust(space, expected_flags
@@ -4116,12 +4065,21 @@ fil_report_invalid_page_access(
: "");
}
+inline void IORequest::set_fil_node(fil_node_t* node)
+{
+ if (!node->space->punch_hole) {
+ clear_punch_hole();
+ }
+
+ m_fil_node = node;
+}
+
/** Reads or writes data. This operation could be asynchronous (aio).
@param[in,out] type IO context
@param[in] sync true if synchronous aio is desired
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to read or write; this must
@@ -4133,14 +4091,14 @@ fil_report_invalid_page_access(
@param[in] message message for aio handler if non-sync aio
used, else ignored
@param[in] ignore_missing_space true=ignore missing space duging read
-@return DB_SUCCESS, DB_TABLESPACE_DELETED or DB_TABLESPACE_TRUNCATED
+@return DB_SUCCESS, or DB_TABLESPACE_DELETED
if we are trying to do i/o on a tablespace which does not exist */
dberr_t
fil_io(
const IORequest& type,
bool sync,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf,
@@ -4154,7 +4112,7 @@ fil_io(
ut_ad(len > 0);
ut_ad(byte_offset < srv_page_size);
- ut_ad(!page_size.is_compressed() || byte_offset == 0);
+ ut_ad(!zip_size || byte_offset == 0);
ut_ad(srv_page_size == 1UL << srv_page_size_shift);
compile_time_assert((1U << UNIV_PAGE_SIZE_SHIFT_MAX)
== UNIV_PAGE_SIZE_MAX);
@@ -4165,7 +4123,7 @@ fil_io(
/* ibuf bitmap pages must be read in the sync AIO mode: */
ut_ad(recv_no_ibuf_operations
|| req_type.is_write()
- || !ibuf_bitmap_page(page_id, page_size)
+ || !ibuf_bitmap_page(page_id, zip_size)
|| sync
|| req_type.is_log());
@@ -4181,7 +4139,7 @@ fil_io(
} else if (req_type.is_read()
&& !recv_no_ibuf_operations
- && ibuf_page(page_id, page_size, NULL)) {
+ && ibuf_page(page_id, zip_size, NULL)) {
mode = OS_AIO_IBUF;
@@ -4265,19 +4223,6 @@ fil_io(
break;
} else {
- if (space->id != TRX_SYS_SPACE
- && UT_LIST_GET_LEN(space->chain) == 1
- && (srv_is_tablespace_truncated(space->id)
- || srv_was_tablespace_truncated(space))
- && req_type.is_read()) {
-
- /* Handle page which is outside the truncated
- tablespace bounds when recovering from a crash
- happened during a truncation */
- mutex_exit(&fil_system.mutex);
- return(DB_TABLESPACE_TRUNCATED);
- }
-
cur_page_no -= node->size;
node = UT_LIST_GET_NEXT(chain, node);
@@ -4336,37 +4281,10 @@ fil_io(
/* Now we have made the changes in the data structures of fil_system */
mutex_exit(&fil_system.mutex);
- /* Calculate the low 32 bits and the high 32 bits of the file offset */
+ if (!zip_size) zip_size = srv_page_size;
- if (!page_size.is_compressed()) {
-
- offset = ((os_offset_t) cur_page_no
- << srv_page_size_shift) + byte_offset;
-
- ut_a(node->size - cur_page_no
- >= ((byte_offset + len + (srv_page_size - 1))
- >> srv_page_size_shift));
- } else {
- ulint size_shift;
-
- switch (page_size.physical()) {
- case 1024: size_shift = 10; break;
- case 2048: size_shift = 11; break;
- case 4096: size_shift = 12; break;
- case 8192: size_shift = 13; break;
- case 16384: size_shift = 14; break;
- case 32768: size_shift = 15; break;
- case 65536: size_shift = 16; break;
- default: ut_error;
- }
-
- offset = ((os_offset_t) cur_page_no << size_shift)
- + byte_offset;
-
- ut_a(node->size - cur_page_no
- >= (len + (page_size.physical() - 1))
- / page_size.physical());
- }
+ offset = os_offset_t(cur_page_no) * zip_size + byte_offset;
+ ut_ad(node->size - cur_page_no >= (len + (zip_size - 1)) / zip_size);
/* Do AIO */
@@ -4380,7 +4298,7 @@ fil_io(
ut_ad(!req_type.is_write()
|| page_id.space() == SRV_LOG_SPACE_FIRST_ID
|| !fil_is_user_tablespace_id(page_id.space())
- || offset == page_id.page_no() * page_size.physical());
+ || offset == page_id.page_no() * zip_size);
/* Queue the aio request */
dberr_t err = os_aio(
@@ -4500,7 +4418,7 @@ fil_aio_wait(
ut_ad(type.is_read());
if (recv_recovery_is_on() && !srv_force_recovery) {
- recv_sys->found_corrupt_fs = true;
+ recv_sys.found_corrupt_fs = true;
}
if (fil_space_t* space = fil_space_acquire_for_io(space_id)) {
@@ -4847,7 +4765,7 @@ fil_space_validate_for_mtr_commit(
/* We are serving mtr_commit(). While there is an active
mini-transaction, we should have !space->stop_new_ops. This is
guaranteed by meta-data locks or transactional locks, or
- dict_operation_lock (X-lock in DROP, S-lock in purge).
+ dict_sys.latch (X-lock in DROP, S-lock in purge).
However, a file I/O thread can invoke change buffer merge
while fil_check_pending_operations() is waiting for operations
@@ -4996,116 +4914,6 @@ fil_names_clear(
return(do_write);
}
-/** Truncate a single-table tablespace. The tablespace must be cached
-in the memory cache.
-@param space_id space id
-@param dir_path directory path
-@param tablename the table name in the usual
- databasename/tablename format of InnoDB
-@param flags tablespace flags
-@param trunc_to_default truncate to default size if tablespace
- is being newly re-initialized.
-@return DB_SUCCESS or error */
-dberr_t
-truncate_t::truncate(
-/*=================*/
- ulint space_id,
- const char* dir_path,
- const char* tablename,
- ulint flags,
- bool trunc_to_default)
-{
- dberr_t err = DB_SUCCESS;
- char* path;
-
- ut_a(!is_system_tablespace(space_id));
-
- if (FSP_FLAGS_HAS_DATA_DIR(flags)) {
- ut_ad(dir_path != NULL);
- path = fil_make_filepath(dir_path, tablename, IBD, true);
- } else {
- path = fil_make_filepath(NULL, tablename, IBD, false);
- }
-
- if (path == NULL) {
- return(DB_OUT_OF_MEMORY);
- }
-
- mutex_enter(&fil_system.mutex);
-
- fil_space_t* space = fil_space_get_by_id(space_id);
-
- /* The following code must change when InnoDB supports
- multiple datafiles per tablespace. */
- ut_a(UT_LIST_GET_LEN(space->chain) == 1);
-
- fil_node_t* node = UT_LIST_GET_FIRST(space->chain);
-
- if (trunc_to_default) {
- space->size = node->size = FIL_IBD_FILE_INITIAL_SIZE;
- }
-
- const bool already_open = node->is_open();
-
- if (!already_open) {
-
- bool ret;
-
- node->handle = os_file_create_simple_no_error_handling(
- innodb_data_file_key, path, OS_FILE_OPEN,
- OS_FILE_READ_WRITE,
- space->purpose != FIL_TYPE_TEMPORARY
- && srv_read_only_mode, &ret);
-
- if (!ret) {
- ib::error() << "Failed to open tablespace file "
- << path << ".";
-
- ut_free(path);
-
- return(DB_ERROR);
- }
-
- ut_a(node->is_open());
- }
-
- os_offset_t trunc_size = trunc_to_default
- ? FIL_IBD_FILE_INITIAL_SIZE
- : space->size;
-
- const bool success = os_file_truncate(
- path, node->handle, trunc_size << srv_page_size_shift);
-
- if (!success) {
- ib::error() << "Cannot truncate file " << path
- << " in TRUNCATE TABLESPACE.";
- err = DB_ERROR;
- }
-
- space->stop_new_ops = false;
-
- /* If we opened the file in this function, close it. */
- if (!already_open) {
- bool closed = os_file_close(node->handle);
-
- if (!closed) {
-
- ib::error() << "Failed to close tablespace file "
- << path << ".";
-
- err = DB_ERROR;
- } else {
- node->handle = OS_FILE_CLOSED;
- }
- }
-
- mutex_exit(&fil_system.mutex);
-
- ut_free(path);
-
- return(err);
-}
-
/* Unit Tests */
#ifdef UNIV_ENABLE_UNIT_TEST_MAKE_FILEPATH
#define MF fil_make_filepath
@@ -5316,29 +5124,6 @@ fil_space_found_by_id(
return space;
}
-/**
-Get should we punch hole to tablespace.
-@param[in] node File node
-@return true, if punch hole should be tried, false if not. */
-bool
-fil_node_should_punch_hole(
- const fil_node_t* node)
-{
- return (node->space->punch_hole);
-}
-
-/**
-Set punch hole to tablespace to given value.
-@param[in] node File node
-@param[in] val value to be set. */
-void
-fil_space_set_punch_hole(
- fil_node_t* node,
- bool val)
-{
- node->space->punch_hole = val;
-}
-
/** Checks that this tablespace in a list of unflushed tablespaces.
@return true if in a list */
bool fil_space_t::is_in_unflushed_spaces() const
diff --git a/storage/innobase/fil/fil0pagecompress.cc b/storage/innobase/fil/fil0pagecompress.cc
index 3c24f1c6886..e6f23c852dc 100644
--- a/storage/innobase/fil/fil0pagecompress.cc
+++ b/storage/innobase/fil/fil0pagecompress.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (C) 2013, 2018, MariaDB Corporation.
+Copyright (C) 2013, 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
@@ -73,45 +73,24 @@ Updated 14/02/2015
#include "snappy-c.h"
#endif
-/** Compress a page_compressed page before writing to a data file.
+/** Compress a page for the given compression algorithm.
@param[in] buf page to be compressed
@param[out] out_buf compressed page
-@param[in] level compression level
-@param[in] block_size file system block size
-@param[in] encrypted whether the page will be subsequently encrypted
-@return actual length of compressed page
-@retval 0 if the page was not compressed */
-ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
- ulint block_size, bool encrypted)
+@param[in] header_len header length of the page
+@param[in] comp_algo compression algorithm
+@param[in] comp_level compression level
+@return actual length of compressed page data
+@retval 0 if the page was not compressed */
+static ulint fil_page_compress_low(
+ const byte* buf,
+ byte* out_buf,
+ ulint header_len,
+ ulint comp_algo,
+ ulint comp_level)
{
- int comp_level = int(level);
- ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
- /* Cache to avoid change during function execution */
- ulint comp_method = innodb_compression_algorithm;
-
- if (encrypted) {
- header_len += FIL_PAGE_COMPRESSION_METHOD_SIZE;
- }
-
- /* Let's not compress file space header or
- extent descriptor */
- switch (fil_page_get_type(buf)) {
- case 0:
- case FIL_PAGE_TYPE_FSP_HDR:
- case FIL_PAGE_TYPE_XDES:
- case FIL_PAGE_PAGE_COMPRESSED:
- return 0;
- }
-
- /* If no compression level was provided to this table, use system
- default level */
- if (comp_level == 0) {
- comp_level = int(page_zip_level);
- }
-
ulint write_size = srv_page_size - header_len;
- switch (comp_method) {
+ switch (comp_algo) {
default:
ut_ad(!"unknown compression method");
/* fall through */
@@ -121,10 +100,9 @@ ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
{
ulong len = uLong(write_size);
if (Z_OK == compress2(
- out_buf + header_len, &len,
- buf, uLong(srv_page_size), comp_level)) {
- write_size = len;
- goto success;
+ out_buf + header_len, &len, buf,
+ uLong(srv_page_size), int(comp_level))) {
+ return len;
}
}
break;
@@ -142,10 +120,7 @@ ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
int(srv_page_size), int(write_size));
# endif
- if (write_size) {
- goto success;
- }
- break;
+ return write_size;
#endif /* HAVE_LZ4 */
#ifdef HAVE_LZO
case PAGE_LZO_ALGORITHM: {
@@ -156,8 +131,7 @@ ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
out_buf + header_len, &len,
out_buf + srv_page_size)
&& len <= write_size) {
- write_size = len;
- goto success;
+ return len;
}
break;
}
@@ -171,8 +145,7 @@ ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
buf, srv_page_size, out_buf + header_len,
&out_pos, write_size)
&& out_pos <= write_size) {
- write_size = out_pos;
- goto success;
+ return out_pos;
}
break;
}
@@ -188,8 +161,7 @@ ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
reinterpret_cast<const char*>(buf)),
unsigned(srv_page_size), 1, 0, 0)
&& len <= write_size) {
- write_size = len;
- goto success;
+ return len;
}
break;
}
@@ -205,53 +177,188 @@ ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
reinterpret_cast<char*>(out_buf) + header_len,
&len)
&& len <= write_size) {
- write_size = len;
- goto success;
+ return len;
}
break;
}
#endif /* HAVE_SNAPPY */
}
- srv_stats.pages_page_compression_error.inc();
return 0;
-success:
+}
+
+/** Compress a page_compressed page for full crc32 format.
+@param[in] buf page to be compressed
+@param[out] out_buf compressed page
+@param[in] flags tablespace flags
+@param[in] block_size file system block size
+@return actual length of compressed page
+@retval 0 if the page was not compressed */
+static ulint fil_page_compress_for_full_crc32(
+ const byte* buf,
+ byte* out_buf,
+ ulint flags,
+ ulint block_size,
+ bool encrypted)
+{
+ ulint comp_level = fsp_flags_get_page_compression_level(flags);
+
+ if (comp_level == 0) {
+ comp_level = page_zip_level;
+ }
+
+ const ulint header_len = FIL_PAGE_COMP_ALGO;
+
+ ulint write_size = fil_page_compress_low(
+ buf, out_buf, header_len,
+ fil_space_t::get_compression_algo(flags), comp_level);
+
+ if (write_size == 0) {
+fail:
+ srv_stats.pages_page_compression_error.inc();
+ return 0;
+ }
+
+ write_size += header_len;
+ const ulint actual_size = write_size;
+ /* Write the actual length of the data & page type
+ for full crc32 format. */
+ const bool lsb = fil_space_t::full_crc32_page_compressed_len(flags);
+ /* In the MSB, store the rounded-up page size. */
+ write_size = (write_size + lsb + (4 + 255)) & ~255;
+ if (write_size >= srv_page_size) {
+ goto fail;
+ }
+
+ /* Set up the page header */
+ memcpy(out_buf, buf, header_len);
+ out_buf[FIL_PAGE_TYPE] = 1U << (FIL_PAGE_COMPRESS_FCRC32_MARKER - 8);
+ out_buf[FIL_PAGE_TYPE + 1] = byte(write_size >> 8);
+ /* Clean up the buffer for the remaining write_size (except checksum) */
+ memset(out_buf + actual_size, 0, write_size - actual_size - 4);
+ if (lsb) {
+ /* Store the LSB */
+ out_buf[write_size - 5] = byte(actual_size + (1 + 4));
+ }
+
+ if (!block_size) {
+ block_size = 512;
+ }
+
+ ut_ad(write_size);
+ if (write_size & (block_size - 1)) {
+ size_t tmp = write_size;
+ write_size = (write_size + (block_size - 1))
+ & ~(block_size - 1);
+ memset(out_buf + tmp, 0, write_size - tmp);
+ }
+
+#ifdef UNIV_DEBUG
+ /* Verify that page can be decompressed */
+ {
+ page_t tmp_buf[UNIV_PAGE_SIZE_MAX];
+ page_t page[UNIV_PAGE_SIZE_MAX];
+ memcpy(page, out_buf, write_size);
+ ut_ad(fil_page_decompress(tmp_buf, page, flags));
+ }
+#endif
+ srv_stats.page_compression_saved.add(srv_page_size - write_size);
+ srv_stats.pages_page_compressed.inc();
+
+ return write_size;
+}
+
+/** Compress a page_compressed page for non full crc32 format.
+@param[in] buf page to be compressed
+@param[out] out_buf compressed page
+@param[in] flags tablespace flags
+@param[in] block_size file system block size
+@param[in] encrypted whether the page will be subsequently encrypted
+@return actual length of compressed page
+@retval 0 if the page was not compressed */
+static ulint fil_page_compress_for_non_full_crc32(
+ const byte* buf,
+ byte* out_buf,
+ ulint flags,
+ ulint block_size,
+ bool encrypted)
+{
+ int comp_level = int(fsp_flags_get_page_compression_level(flags));
+ ulint header_len = FIL_PAGE_DATA + FIL_PAGE_COMP_METADATA_LEN;
+ /* Cache to avoid change during function execution */
+ ulint comp_algo = innodb_compression_algorithm;
+
+ if (encrypted) {
+ header_len += FIL_PAGE_ENCRYPT_COMP_ALGO;
+ }
+
+ /* If no compression level was provided to this table, use system
+ default level */
+ if (comp_level == 0) {
+ comp_level = int(page_zip_level);
+ }
+
+ ulint write_size = fil_page_compress_low(
+ buf, out_buf,
+ header_len, comp_algo, comp_level);
+
+ if (write_size == 0) {
+ srv_stats.pages_page_compression_error.inc();
+ return 0;
+ }
+
/* Set up the page header */
memcpy(out_buf, buf, FIL_PAGE_DATA);
/* Set up the checksum */
- mach_write_to_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM, BUF_NO_CHECKSUM_MAGIC);
+ mach_write_to_4(out_buf + FIL_PAGE_SPACE_OR_CHKSUM, BUF_NO_CHECKSUM_MAGIC);
/* Set up the compression algorithm */
- mach_write_to_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, comp_method);
+ mach_write_to_8(out_buf + FIL_PAGE_COMP_ALGO, comp_algo);
if (encrypted) {
/* Set up the correct page type */
- mach_write_to_2(out_buf+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
- mach_write_to_2(out_buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE, comp_method);
+ mach_write_to_2(out_buf + FIL_PAGE_TYPE,
+ FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED);
+
+ mach_write_to_2(out_buf + FIL_PAGE_DATA
+ + FIL_PAGE_ENCRYPT_COMP_ALGO, comp_algo);
} else {
/* Set up the correct page type */
- mach_write_to_2(out_buf+FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED);
+ mach_write_to_2(out_buf + FIL_PAGE_TYPE, FIL_PAGE_PAGE_COMPRESSED);
}
/* Set up the actual payload lenght */
- mach_write_to_2(out_buf+FIL_PAGE_DATA, write_size);
+ mach_write_to_2(out_buf + FIL_PAGE_DATA + FIL_PAGE_COMP_SIZE,
+ write_size);
#ifdef UNIV_DEBUG
/* Verify */
- ut_ad(fil_page_is_compressed(out_buf) || fil_page_is_compressed_encrypted(out_buf));
- ut_ad(mach_read_from_4(out_buf+FIL_PAGE_SPACE_OR_CHKSUM) == BUF_NO_CHECKSUM_MAGIC);
- ut_ad(mach_read_from_2(out_buf+FIL_PAGE_DATA) == write_size);
- ut_ad(mach_read_from_8(out_buf+FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION) == (ulint)comp_method ||
- mach_read_from_2(out_buf+FIL_PAGE_DATA+FIL_PAGE_COMPRESSED_SIZE) == (ulint)comp_method);
+ ut_ad(fil_page_is_compressed(out_buf)
+ || fil_page_is_compressed_encrypted(out_buf));
+
+ ut_ad(mach_read_from_4(out_buf + FIL_PAGE_SPACE_OR_CHKSUM)
+ == BUF_NO_CHECKSUM_MAGIC);
+
+ ut_ad(mach_read_from_2(out_buf + FIL_PAGE_DATA + FIL_PAGE_COMP_SIZE)
+ == write_size);
+
+ bool is_compressed = (mach_read_from_8(out_buf + FIL_PAGE_COMP_ALGO)
+ == (ulint) comp_algo);
+
+ bool is_encrypted_compressed =
+ (mach_read_from_2(out_buf + FIL_PAGE_DATA
+ + FIL_PAGE_ENCRYPT_COMP_ALGO)
+ == (ulint) comp_algo);
+
+ ut_ad(is_compressed || is_encrypted_compressed);
/* Verify that page can be decompressed */
{
page_t tmp_buf[UNIV_PAGE_SIZE_MAX];
page_t page[UNIV_PAGE_SIZE_MAX];
memcpy(page, out_buf, srv_page_size);
- ut_ad(fil_page_decompress(tmp_buf, page));
- ut_ad(!buf_page_is_corrupted(false, page, univ_page_size,
- NULL));
+ ut_ad(fil_page_decompress(tmp_buf, page, flags));
+ ut_ad(!buf_page_is_corrupted(false, page, flags));
}
#endif /* UNIV_DEBUG */
@@ -266,7 +373,8 @@ success:
/* Actual write needs to be alligned on block size */
if (write_size % block_size) {
size_t tmp = write_size;
- write_size = (size_t)ut_uint64_align_up((ib_uint64_t)write_size, block_size);
+ write_size = (size_t)ut_uint64_align_up(
+ (ib_uint64_t)write_size, block_size);
/* Clean up the end of buffer */
memset(out_buf+tmp, 0, write_size - tmp);
#ifdef UNIV_DEBUG
@@ -281,131 +389,245 @@ success:
return write_size;
}
-/** Decompress a page that may be subject to page_compressed compression.
-@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
-@param[in,out] buf possibly compressed page buffer
-@return size of the compressed data
-@retval 0 if decompression failed
-@retval srv_page_size if the page was not compressed */
-ulint fil_page_decompress(byte* tmp_buf, byte* buf)
+/** Compress a page_compressed page before writing to a data file.
+@param[in] buf page to be compressed
+@param[out] out_buf compressed page
+@param[in] flags tablespace flags
+@param[in] block_size file system block size
+@param[in] encrypted whether the page will be subsequently encrypted
+@return actual length of compressed page
+@retval 0 if the page was not compressed */
+ulint fil_page_compress(
+ const byte* buf,
+ byte* out_buf,
+ ulint flags,
+ ulint block_size,
+ bool encrypted)
{
- const unsigned ptype = mach_read_from_2(buf+FIL_PAGE_TYPE);
- ulint header_len;
- uint64_t compression_alg;
- switch (ptype) {
- case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED:
- header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE
- + FIL_PAGE_COMPRESSION_METHOD_SIZE;
- compression_alg = mach_read_from_2(
- FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE + buf);
- break;
- case FIL_PAGE_PAGE_COMPRESSED:
- header_len = FIL_PAGE_DATA + FIL_PAGE_COMPRESSED_SIZE;
- compression_alg = mach_read_from_8(
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + buf);
- break;
- default:
- return srv_page_size;
- }
+ /* The full_crc32 page_compressed format assumes this. */
+ ut_ad(!(block_size & 255));
+ ut_ad(ut_is_2pow(block_size));
- if (mach_read_from_4(buf + FIL_PAGE_SPACE_OR_CHKSUM)
- != BUF_NO_CHECKSUM_MAGIC) {
+ /* Let's not compress file space header or
+ extent descriptor */
+ switch (fil_page_get_type(buf)) {
+ case 0:
+ case FIL_PAGE_TYPE_FSP_HDR:
+ case FIL_PAGE_TYPE_XDES:
+ case FIL_PAGE_PAGE_COMPRESSED:
return 0;
}
- ulint actual_size = mach_read_from_2(buf + FIL_PAGE_DATA);
-
- /* Check if payload size is corrupted */
- if (actual_size == 0 || actual_size > srv_page_size - header_len) {
- return 0;
+ if (fil_space_t::full_crc32(flags)) {
+ return fil_page_compress_for_full_crc32(
+ buf, out_buf, flags, block_size, encrypted);
}
- switch (compression_alg) {
+ return fil_page_compress_for_non_full_crc32(
+ buf, out_buf, flags, block_size, encrypted);
+}
+
+/** Decompress a page that may be subject to page_compressed compression.
+@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
+@param[in,out] buf possibly compressed page buffer
+@param[in] comp_algo compression algorithm
+@param[in] header_len header length of the page
+@param[in] actual size actual size of the page
+@retval true if the page is decompressed or false */
+static bool fil_page_decompress_low(
+ byte* tmp_buf,
+ byte* buf,
+ ulint comp_algo,
+ ulint header_len,
+ ulint actual_size)
+{
+ switch (comp_algo) {
default:
ib::error() << "Unknown compression algorithm "
- << compression_alg;
- return 0;
+ << comp_algo;
+ return false;
case PAGE_ZLIB_ALGORITHM:
{
uLong len = srv_page_size;
- if (Z_OK == uncompress(tmp_buf, &len,
+ return (Z_OK == uncompress(tmp_buf, &len,
buf + header_len,
uLong(actual_size))
- && len == srv_page_size) {
- break;
- }
+ && len == srv_page_size);
}
- return 0;
#ifdef HAVE_LZ4
case PAGE_LZ4_ALGORITHM:
- if (LZ4_decompress_safe(reinterpret_cast<const char*>(buf)
- + header_len,
- reinterpret_cast<char*>(tmp_buf),
- actual_size, srv_page_size)
- == int(srv_page_size)) {
- break;
- }
- return 0;
+ return LZ4_decompress_safe(
+ reinterpret_cast<const char*>(buf) + header_len,
+ reinterpret_cast<char*>(tmp_buf),
+ actual_size, srv_page_size) == int(srv_page_size);
#endif /* HAVE_LZ4 */
#ifdef HAVE_LZO
- case PAGE_LZO_ALGORITHM: {
- lzo_uint len_lzo = srv_page_size;
- if (LZO_E_OK == lzo1x_decompress_safe(
- buf + header_len,
- actual_size, tmp_buf, &len_lzo, NULL)
- && len_lzo == srv_page_size) {
- break;
+ case PAGE_LZO_ALGORITHM:
+ {
+ lzo_uint len_lzo = srv_page_size;
+ return (LZO_E_OK == lzo1x_decompress_safe(
+ buf + header_len,
+ actual_size, tmp_buf, &len_lzo, NULL)
+ && len_lzo == srv_page_size);
}
- return 0;
- }
#endif /* HAVE_LZO */
#ifdef HAVE_LZMA
- case PAGE_LZMA_ALGORITHM: {
- size_t src_pos = 0;
- size_t dst_pos = 0;
- uint64_t memlimit = UINT64_MAX;
-
- if (LZMA_OK == lzma_stream_buffer_decode(
- &memlimit, 0, NULL, buf + header_len,
- &src_pos, actual_size, tmp_buf, &dst_pos,
- srv_page_size)
- && dst_pos == srv_page_size) {
- break;
+ case PAGE_LZMA_ALGORITHM:
+ {
+ size_t src_pos = 0;
+ size_t dst_pos = 0;
+ uint64_t memlimit = UINT64_MAX;
+
+ return LZMA_OK == lzma_stream_buffer_decode(
+ &memlimit, 0, NULL, buf + header_len,
+ &src_pos, actual_size, tmp_buf, &dst_pos,
+ srv_page_size)
+ && dst_pos == srv_page_size;
}
- return 0;
- }
#endif /* HAVE_LZMA */
#ifdef HAVE_BZIP2
- case PAGE_BZIP2_ALGORITHM: {
- unsigned int dst_pos = srv_page_size;
- if (BZ_OK == BZ2_bzBuffToBuffDecompress(
- reinterpret_cast<char*>(tmp_buf),
- &dst_pos,
- reinterpret_cast<char*>(buf) + header_len,
- actual_size, 1, 0)
- && dst_pos == srv_page_size) {
- break;
+ case PAGE_BZIP2_ALGORITHM:
+ {
+ unsigned int dst_pos = srv_page_size;
+ return BZ_OK == BZ2_bzBuffToBuffDecompress(
+ reinterpret_cast<char*>(tmp_buf),
+ &dst_pos,
+ reinterpret_cast<char*>(buf) + header_len,
+ actual_size, 1, 0)
+ && dst_pos == srv_page_size;
}
- return 0;
- }
#endif /* HAVE_BZIP2 */
#ifdef HAVE_SNAPPY
- case PAGE_SNAPPY_ALGORITHM: {
- size_t olen = srv_page_size;
-
- if (SNAPPY_OK == snappy_uncompress(
- reinterpret_cast<const char*>(buf) + header_len,
- actual_size,
- reinterpret_cast<char*>(tmp_buf), &olen)
- && olen == srv_page_size) {
- break;
+ case PAGE_SNAPPY_ALGORITHM:
+ {
+ size_t olen = srv_page_size;
+
+ return SNAPPY_OK == snappy_uncompress(
+ reinterpret_cast<const char*>(buf)
+ + header_len,
+ actual_size,
+ reinterpret_cast<char*>(tmp_buf), &olen)
+ && olen == srv_page_size;
+ }
+#endif /* HAVE_SNAPPY */
+ }
+
+ return false;
+}
+
+/** Decompress a page for full crc32 format.
+@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
+@param[in,out] buf possibly compressed page buffer
+@param[in] flags tablespace flags
+@return size of the compressed data
+@retval 0 if decompression failed
+@retval srv_page_size if the page was not compressed */
+ulint fil_page_decompress_for_full_crc32(byte* tmp_buf, byte* buf, ulint flags)
+{
+ ut_ad(fil_space_t::full_crc32(flags));
+ bool compressed = false;
+ size_t size = buf_page_full_crc32_size(buf, &compressed, NULL);
+ if (!compressed) {
+ ut_ad(size == srv_page_size);
+ return size;
+ }
+
+ if (!fil_space_t::is_compressed(flags)) {
+ return 0;
+ }
+
+ if (size >= srv_page_size) {
+ return 0;
+ }
+
+ if (fil_space_t::full_crc32_page_compressed_len(flags)) {
+ compile_time_assert(FIL_PAGE_FCRC32_CHECKSUM == 4);
+ if (size_t lsb = buf[size - 5]) {
+ size += lsb - 0x100;
}
+ size -= 5;
+ }
+
+ const size_t header_len = FIL_PAGE_COMP_ALGO;
+
+ if (!fil_page_decompress_low(tmp_buf, buf,
+ fil_space_t::get_compression_algo(flags),
+ header_len, size - header_len)) {
return 0;
}
-#endif /* HAVE_SNAPPY */
+
+ srv_stats.pages_page_decompressed.inc();
+ memcpy(buf, tmp_buf, srv_page_size);
+ return size;
+}
+
+/** Decompress a page for non full crc32 format.
+@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
+@param[in,out] buf possibly compressed page buffer
+@return size of the compressed data
+@retval 0 if decompression failed
+@retval srv_page_size if the page was not compressed */
+ulint fil_page_decompress_for_non_full_crc32(
+ byte* tmp_buf,
+ byte* buf)
+{
+ const unsigned ptype = mach_read_from_2(buf+FIL_PAGE_TYPE);
+ ulint header_len;
+ uint comp_algo;
+ switch (ptype) {
+ case FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED:
+ header_len= FIL_PAGE_DATA + FIL_PAGE_ENCRYPT_COMP_METADATA_LEN;
+ comp_algo = mach_read_from_2(
+ FIL_PAGE_DATA + FIL_PAGE_ENCRYPT_COMP_ALGO + buf);
+ break;
+ case FIL_PAGE_PAGE_COMPRESSED:
+ header_len = FIL_PAGE_DATA + FIL_PAGE_COMP_METADATA_LEN;
+ if (mach_read_from_6(FIL_PAGE_COMP_ALGO + buf)) {
+ return 0;
+ }
+ comp_algo = mach_read_from_2(FIL_PAGE_COMP_ALGO + 6 + buf);
+ break;
+ default:
+ return srv_page_size;
+ }
+
+ if (mach_read_from_4(buf + FIL_PAGE_SPACE_OR_CHKSUM)
+ != BUF_NO_CHECKSUM_MAGIC) {
+ return 0;
+ }
+
+ ulint actual_size = mach_read_from_2(buf + FIL_PAGE_DATA
+ + FIL_PAGE_COMP_SIZE);
+
+ /* Check if payload size is corrupted */
+ if (actual_size == 0 || actual_size > srv_page_size - header_len) {
+ return 0;
+ }
+
+ if (!fil_page_decompress_low(tmp_buf, buf, comp_algo, header_len,
+ actual_size)) {
+ return 0;
}
srv_stats.pages_page_decompressed.inc();
memcpy(buf, tmp_buf, srv_page_size);
return actual_size;
}
+
+/** Decompress a page that may be subject to page_compressed compression.
+@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
+@param[in,out] buf possibly compressed page buffer
+@return size of the compressed data
+@retval 0 if decompression failed
+@retval srv_page_size if the page was not compressed */
+ulint fil_page_decompress(
+ byte* tmp_buf,
+ byte* buf,
+ ulint flags)
+{
+ if (fil_space_t::full_crc32(flags)) {
+ return fil_page_decompress_for_full_crc32(tmp_buf, buf, flags);
+ }
+
+ return fil_page_decompress_for_non_full_crc32(tmp_buf, buf);
+}
diff --git a/storage/innobase/fsp/fsp0file.cc b/storage/innobase/fsp/fsp0file.cc
index 811a5b7fee3..4deacd1c3b6 100644
--- a/storage/innobase/fsp/fsp0file.cc
+++ b/storage/innobase/fsp/fsp0file.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 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
@@ -343,7 +343,7 @@ Datafile::read_first_page(bool read_only_mode)
if (m_order == 0) {
m_space_id = fsp_header_get_space_id(m_first_page);
m_flags = fsp_header_get_flags(m_first_page);
- if (!fsp_flags_is_valid(m_flags, m_space_id)) {
+ if (!fil_space_t::is_valid_flags(m_flags, m_space_id)) {
ulint cflags = fsp_flags_convert_from_101(m_flags);
if (cflags == ULINT_UNDEFINED) {
ib::error()
@@ -356,8 +356,9 @@ Datafile::read_first_page(bool read_only_mode)
}
}
- const page_size_t ps(m_flags);
- if (ps.physical() > page_size) {
+ const size_t physical_size = fil_space_t::physical_size(m_flags);
+
+ if (physical_size > page_size) {
ib::error() << "File " << m_filepath
<< " should be longer than "
<< page_size << " bytes";
@@ -407,7 +408,9 @@ Datafile::validate_to_dd(ulint space_id, ulint flags)
/* Make sure the datafile we found matched the space ID.
If the datafile is a file-per-table tablespace then also match
the row format and zip page size. */
- if (m_space_id == space_id && m_flags == flags) {
+ if (m_space_id == space_id
+ && (fil_space_t::is_flags_equal(flags, m_flags)
+ || fil_space_t::is_flags_equal(m_flags, flags))) {
/* Datafile matches the tablespace expected. */
return(DB_SUCCESS);
}
@@ -537,19 +540,19 @@ err_exit:
}
}
- if (!fsp_flags_is_valid(m_flags, m_space_id)) {
+ if (!fil_space_t::is_valid_flags(m_flags, m_space_id)) {
/* Tablespace flags must be valid. */
error_txt = "Tablespace flags are invalid";
goto err_exit;
}
- const page_size_t page_size(m_flags);
+ ulint logical_size = fil_space_t::logical_size(m_flags);
- if (srv_page_size != page_size.logical()) {
+ if (srv_page_size != logical_size) {
/* Logical size must be innodb_page_size. */
ib::error()
<< "Data file '" << m_filepath << "' uses page size "
- << page_size.logical() << ", but the innodb_page_size"
+ << logical_size << ", but the innodb_page_size"
" start-up parameter is "
<< srv_page_size;
free_first_page();
@@ -567,7 +570,7 @@ err_exit:
goto err_exit;
}
- if (buf_page_is_corrupted(false, m_first_page, page_size)) {
+ if (buf_page_is_corrupted(false, m_first_page, m_flags)) {
/* Look for checksum and other corruptions. */
error_txt = "Checksum mismatch";
goto err_exit;
@@ -629,7 +632,6 @@ Datafile::find_space_id()
for (ulint page_size = UNIV_ZIP_SIZE_MIN;
page_size <= UNIV_PAGE_SIZE_MAX;
page_size <<= 1) {
-
/* map[space_id] = count of pages */
typedef std::map<
ulint,
@@ -657,6 +659,20 @@ Datafile::find_space_id()
byte* page = static_cast<byte*>(
ut_align(buf, UNIV_SECTOR_SIZE));
+ ulint fsp_flags;
+ /* provide dummy value if the first os_file_read() fails */
+ switch (srv_checksum_algorithm) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ fsp_flags = 1U << FSP_FLAGS_FCRC32_POS_MARKER
+ | FSP_FLAGS_FCRC32_PAGE_SSIZE()
+ | innodb_compression_algorithm
+ << FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO;
+ break;
+ default:
+ fsp_flags = 0;
+ }
+
for (ulint j = 0; j < page_count; ++j) {
dberr_t err;
@@ -674,33 +690,27 @@ Datafile::find_space_id()
continue;
}
+ if (j == 0) {
+ fsp_flags = mach_read_from_4(
+ page + FSP_HEADER_OFFSET + FSP_SPACE_FLAGS);
+ }
+
bool noncompressed_ok = false;
/* For noncompressed pages, the page size must be
equal to srv_page_size. */
- if (page_size == srv_page_size) {
+ if (page_size == srv_page_size
+ && !fil_space_t::zip_size(fsp_flags)) {
noncompressed_ok = !buf_page_is_corrupted(
- false, page, univ_page_size, NULL);
+ false, page, fsp_flags);
}
bool compressed_ok = false;
- /* file-per-table tablespaces can be compressed with
- the same physical and logical page size. General
- tablespaces must have different physical and logical
- page sizes in order to be compressed. For this check,
- assume the page is compressed if univ_page_size.
- logical() is equal to or less than 16k and the
- page_size we are checking is equal to or less than
- srv_page_size. */
if (srv_page_size <= UNIV_PAGE_SIZE_DEF
- && page_size <= srv_page_size) {
- const page_size_t compr_page_size(
- page_size, srv_page_size,
- true);
-
+ && page_size == fil_space_t::zip_size(fsp_flags)) {
compressed_ok = !buf_page_is_corrupted(
- false, page, compr_page_size, NULL);
+ false, page, fsp_flags);
}
if (noncompressed_ok || compressed_ok) {
@@ -768,7 +778,7 @@ Datafile::restore_from_doublewrite()
}
/* Find if double write buffer contains page_no of given space id. */
- const byte* page = recv_sys->dblwr.find_page(m_space_id, 0);
+ const byte* page = recv_sys.dblwr.find_page(m_space_id, 0);
const page_id_t page_id(m_space_id, 0);
if (page == NULL) {
@@ -787,7 +797,7 @@ Datafile::restore_from_doublewrite()
ulint flags = mach_read_from_4(
FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + page);
- if (!fsp_flags_is_valid(flags, m_space_id)) {
+ if (!fil_space_t::is_valid_flags(flags, m_space_id)) {
ulint cflags = fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED) {
ib::warn()
@@ -800,21 +810,21 @@ Datafile::restore_from_doublewrite()
/* The flags on the page should be converted later. */
}
- const page_size_t page_size(flags);
+ ulint physical_size = fil_space_t::physical_size(flags);
ut_a(page_get_page_no(page) == page_id.page_no());
ib::info() << "Restoring page " << page_id
<< " of datafile '" << m_filepath
<< "' from the doublewrite buffer. Writing "
- << page_size.physical() << " bytes into file '"
+ << physical_size << " bytes into file '"
<< m_filepath << "'";
IORequest request(IORequest::WRITE);
return(os_file_write(
request,
- m_filepath, m_handle, page, 0, page_size.physical())
+ m_filepath, m_handle, page, 0, physical_size)
!= DB_SUCCESS);
}
@@ -921,8 +931,9 @@ RemoteDatafile::create_link_file(
prev_filepath = read_link_file(link_filepath);
if (prev_filepath) {
- /* Truncate will call this with an existing
- link file which contains the same filepath. */
+ /* Truncate (starting with MySQL 5.6, probably no
+ longer since MariaDB Server 10.2.19) used to call this
+ with an existing link file which contains the same filepath. */
bool same = !strcmp(prev_filepath, filepath);
ut_free(prev_filepath);
if (same) {
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 6942b1f4730..809ad3ded4f 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -50,7 +50,6 @@ typedef ulint page_no_t;
/** Return an extent to the free list of a space.
@param[in,out] space tablespace
@param[in] offset page number in the extent
-@param[in] page_size page size
@param[in,out] mtr mini-transaction */
MY_ATTRIBUTE((nonnull))
static
@@ -58,7 +57,6 @@ void
fsp_free_extent(
fil_space_t* space,
page_no_t offset,
- const page_size_t& page_size,
mtr_t* mtr);
/********************************************************************//**
@@ -78,7 +76,6 @@ We think of the extent lists of the segment catenated in the order
FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE.
@param[in] inode segment inode
@param[in] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the first extent descriptor, or NULL if none */
MY_ATTRIBUTE((nonnull, warn_unused_result))
@@ -87,7 +84,6 @@ xdes_t*
fseg_get_first_extent(
fseg_inode_t* inode,
const fil_space_t* space,
- const page_size_t& page_size,
mtr_t* mtr);
/** Put new extents to the free list if there are free extents above the free
@@ -111,7 +107,6 @@ fsp_fill_free_list(
This function implements the intelligent allocation strategy which tries
to minimize file space fragmentation.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] seg_inode segment inode
@param[in] hint hint of which page would be desirable
@param[in] direction if the new page is needed because of
@@ -132,7 +127,6 @@ static
buf_block_t*
fseg_alloc_free_page_low(
fil_space_t* space,
- const page_size_t& page_size,
fseg_inode_t* seg_inode,
ulint hint,
byte direction,
@@ -147,24 +141,16 @@ fseg_alloc_free_page_low(
/** Gets a pointer to the space header and x-locks its page.
@param[in] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return pointer to the space header, page x-locked */
-UNIV_INLINE
-fsp_header_t*
-fsp_get_space_header(
- const fil_space_t* space,
- const page_size_t& page_size,
- mtr_t* mtr)
+inline fsp_header_t* fsp_get_space_header(const fil_space_t* space, mtr_t* mtr)
{
buf_block_t* block;
fsp_header_t* header;
ut_ad(space->purpose != FIL_TYPE_LOG);
- ut_ad(!FSP_FLAGS_GET_ZIP_SSIZE(space->flags)
- == !page_size.is_compressed());
- block = buf_page_get(page_id_t(space->id, 0), page_size,
+ block = buf_page_get(page_id_t(space->id, 0), space->zip_size(),
RW_SX_LATCH, mtr);
header = FSP_HEADER_OFFSET + buf_block_get_frame(block);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -371,16 +357,8 @@ xdes_init(
xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in/out: mini-transaction */
{
- ulint i;
-
- ut_ad(descr && mtr);
ut_ad(mtr_memo_contains_page(mtr, descr, MTR_MEMO_PAGE_SX_FIX));
- ut_ad((XDES_SIZE - XDES_BITMAP) % 4 == 0);
-
- for (i = XDES_BITMAP; i < XDES_SIZE; i += 4) {
- mlog_write_ulint(descr + i, 0xFFFFFFFFUL, MLOG_4BYTES, mtr);
- }
-
+ mlog_memset(descr + XDES_BITMAP, XDES_SIZE - XDES_BITMAP, 0xff, mtr);
xdes_set_state(descr, XDES_FREE, mtr);
}
@@ -427,9 +405,9 @@ xdes_get_descriptor_with_space_hdr(
return(NULL);
}
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
- descr_page_no = xdes_calc_descriptor_page(page_size, offset);
+ descr_page_no = xdes_calc_descriptor_page(zip_size, offset);
buf_block_t* block;
@@ -440,7 +418,7 @@ xdes_get_descriptor_with_space_hdr(
block = NULL;
} else {
block = buf_page_get(
- page_id_t(space->id, descr_page_no), page_size,
+ page_id_t(space->id, descr_page_no), zip_size,
RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -453,7 +431,7 @@ xdes_get_descriptor_with_space_hdr(
}
return(descr_page + XDES_ARR_OFFSET
- + XDES_SIZE * xdes_calc_descriptor_index(page_size, offset));
+ + XDES_SIZE * xdes_calc_descriptor_index(zip_size, offset));
}
/** Get the extent descriptor of a page.
@@ -465,22 +443,17 @@ defined, as they are uninitialized above the free limit.
@param[in] space tablespace
@param[in] offset page offset; if equal to the free limit, we
try to add new extents to the space free list
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the extent descriptor */
MY_ATTRIBUTE((warn_unused_result))
static
xdes_t*
-xdes_get_descriptor(
- const fil_space_t* space,
- page_no_t offset,
- const page_size_t& page_size,
- mtr_t* mtr)
+xdes_get_descriptor(const fil_space_t* space, page_no_t offset, mtr_t* mtr)
{
buf_block_t* block;
fsp_header_t* sp_header;
- block = buf_page_get(page_id_t(space->id, 0), page_size,
+ block = buf_page_get(page_id_t(space->id, 0), space->zip_size(),
RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -499,7 +472,6 @@ defined, as they are uninitialized above the free limit.
@param[in] space tablespace
@param[in] page descriptor page offset
@param[in] offset page offset
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the extent descriptor
@retval NULL if the descriptor is not available */
@@ -510,15 +482,16 @@ xdes_get_descriptor_const(
const fil_space_t* space,
page_no_t page,
page_no_t offset,
- const page_size_t& page_size,
mtr_t* mtr)
{
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_S_LOCK));
ut_ad(offset < space->free_limit);
ut_ad(offset < space->size_in_header);
+ const ulint zip_size = space->zip_size();
+
if (buf_block_t* block = buf_page_get(page_id_t(space->id, page),
- page_size, RW_S_LATCH, mtr)) {
+ zip_size, RW_S_LATCH, mtr)) {
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
ut_ad(page != 0 || space->free_limit == mach_read_from_4(
@@ -529,7 +502,7 @@ xdes_get_descriptor_const(
+ block->frame));
return(block->frame + XDES_ARR_OFFSET + XDES_SIZE
- * xdes_calc_descriptor_index(page_size, offset));
+ * xdes_calc_descriptor_index(zip_size, offset));
}
return(NULL);
@@ -538,7 +511,6 @@ xdes_get_descriptor_const(
/** Get a pointer to the extent descriptor. The page where the
extent descriptor resides is x-locked.
@param[in] space tablespace
-@param[in] page_size page size
@param[in] lst_node file address of the list node
contained in the descriptor
@param[in,out] mtr mini-transaction
@@ -548,14 +520,13 @@ UNIV_INLINE
xdes_t*
xdes_lst_get_descriptor(
const fil_space_t* space,
- const page_size_t& page_size,
fil_addr_t lst_node,
mtr_t* mtr)
{
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
- ut_ad(page_size.equals_to(page_size_t(space->flags)));
- return(fut_get_ptr(space->id, page_size, lst_node, RW_SX_LATCH, mtr)
- - XDES_FLST_NODE);
+ return fut_get_ptr(space->id, space->zip_size(),
+ lst_node, RW_SX_LATCH, mtr)
+ - XDES_FLST_NODE;
}
/********************************************************************//**
@@ -612,9 +583,7 @@ void fil_space_t::modify_check(const mtr_t& mtr) const
case MTR_LOG_NO_REDO:
ut_ad(purpose == FIL_TYPE_TEMPORARY
|| purpose == FIL_TYPE_IMPORT
- || my_atomic_loadlint(&redo_skipped_count)
- || is_being_truncated
- || srv_is_tablespace_truncated(id));
+ || redo_skipped_count);
return;
case MTR_LOG_ALL:
/* We may only write redo log for a persistent
@@ -640,7 +609,7 @@ fsp_header_init_fields(
ulint flags) /*!< in: tablespace flags (FSP_SPACE_FLAGS) */
{
flags &= ~FSP_FLAGS_MEM_MASK;
- ut_a(fsp_flags_is_valid(flags, space_id));
+ ut_a(fil_space_t::is_valid_flags(flags, space_id));
mach_write_to_4(FSP_HEADER_OFFSET + FSP_SPACE_ID + page,
space_id);
@@ -654,12 +623,12 @@ fsp_header_init_fields(
@param[in,out] mtr mini-transaction */
void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
{
- const page_id_t page_id(space->id, 0);
- const page_size_t page_size(space->flags);
+ const page_id_t page_id(space->id, 0);
+ const ulint zip_size = space->zip_size();
mtr_x_lock_space(space, mtr);
- buf_block_t* block = buf_page_create(page_id, page_size, mtr);
- buf_page_get(page_id, page_size, RW_SX_LATCH, mtr);
+ buf_block_t* block = buf_page_create(page_id, zip_size, mtr);
+ buf_page_get(page_id, zip_size, RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
space->size_in_header = size;
@@ -675,23 +644,23 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_ID + block->frame,
space->id, MLOG_4BYTES, mtr);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_NOT_USED + block->frame, 0,
- MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED
+ + block->frame));
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE + block->frame, size,
MLOG_4BYTES, mtr);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + block->frame, 0,
- MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ + block->frame));
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + block->frame,
space->flags & ~FSP_FLAGS_MEM_MASK,
MLOG_4BYTES, mtr);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FRAG_N_USED + block->frame, 0,
- MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ + block->frame));
- flst_init(FSP_HEADER_OFFSET + FSP_FREE + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_FREE_FRAG + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_FULL_FRAG + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE + block->frame, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_FULL_FRAG, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, mtr);
mlog_write_ull(FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame, 1, mtr);
@@ -768,6 +737,44 @@ fsp_try_extend_data_file_with_pages(
return(success);
}
+/** Calculate the number of physical pages in an extent for this file.
+@param[in] physical_size page_size of the datafile
+@return number of pages in an extent for this file */
+inline ulint fsp_get_extent_size_in_pages(ulint physical_size)
+{
+ return (FSP_EXTENT_SIZE << srv_page_size_shift) / physical_size;
+}
+
+
+/** Calculate the number of pages to extend a datafile.
+We extend single-table tablespaces first one extent at a time,
+but 4 at a time for bigger tablespaces. It is not enough to extend always
+by one extent, because we need to add at least one extent to FSP_FREE.
+A single extent descriptor page will track many extents. And the extent
+that uses its extent descriptor page is put onto the FSP_FREE_FRAG list.
+Extents that do not use their extent descriptor page are added to FSP_FREE.
+The physical page size is used to determine how many extents are tracked
+on one extent descriptor page. See xdes_calc_descriptor_page().
+@param[in] physical_size page size in data file
+@param[in] size current number of pages in the datafile
+@return number of pages to extend the file. */
+static ulint fsp_get_pages_to_extend_ibd(ulint physical_size, ulint size)
+{
+ ulint extent_size = fsp_get_extent_size_in_pages(physical_size);
+ /* The threshold is set at 32MiB except when the physical page
+ size is small enough that it must be done sooner. */
+ ulint threshold = std::min(32 * extent_size, physical_size);
+
+ if (size >= threshold) {
+ /* Below in fsp_fill_free_list() we assume
+ that we add at most FSP_FREE_ADD extents at
+ a time */
+ extent_size *= FSP_FREE_ADD;
+ }
+
+ return extent_size;
+}
+
/** Try to extend the last data file of a tablespace if it is auto-extending.
@param[in,out] space tablespace
@param[in,out] header tablespace header
@@ -820,8 +827,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
size = mach_read_from_4(header + FSP_SIZE);
ut_ad(size == space->size_in_header);
- const page_size_t page_size(
- mach_read_from_4(header + FSP_SPACE_FLAGS));
+ const ulint ps = space->physical_size();
switch (space->id) {
case TRX_SYS_SPACE:
@@ -831,8 +837,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
size_increase = srv_tmp_space.get_increment();
break;
default:
- ulint extent_pages
- = fsp_get_extent_size_in_pages(page_size);
+ ulint extent_pages = fsp_get_extent_size_in_pages(ps);
if (size < extent_pages) {
/* Let us first extend the file to extent_size */
if (!fsp_try_extend_data_file_with_pages(
@@ -843,7 +848,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
size = extent_pages;
}
- size_increase = fsp_get_pages_to_extend_ibd(page_size, size);
+ size_increase = fsp_get_pages_to_extend_ibd(ps, size);
}
if (size_increase == 0) {
@@ -857,8 +862,7 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
/* We ignore any fragments of a full megabyte when storing the size
to the space header */
- space->size_in_header = ut_2pow_round(
- space->size, (1024 * 1024) / page_size.physical());
+ space->size_in_header = ut_2pow_round(space->size, (1024 * 1024) / ps);
mlog_write_ulint(
header + FSP_SIZE, space->size_in_header, MLOG_4BYTES, mtr);
@@ -866,47 +870,6 @@ fsp_try_extend_data_file(fil_space_t* space, fsp_header_t* header, mtr_t* mtr)
return(size_increase);
}
-/** Calculate the number of pages to extend a datafile.
-We extend single-table tablespaces first one extent at a time,
-but 4 at a time for bigger tablespaces. It is not enough to extend always
-by one extent, because we need to add at least one extent to FSP_FREE.
-A single extent descriptor page will track many extents. And the extent
-that uses its extent descriptor page is put onto the FSP_FREE_FRAG list.
-Extents that do not use their extent descriptor page are added to FSP_FREE.
-The physical page size is used to determine how many extents are tracked
-on one extent descriptor page. See xdes_calc_descriptor_page().
-@param[in] page_size page_size of the datafile
-@param[in] size current number of pages in the datafile
-@return number of pages to extend the file. */
-ulint
-fsp_get_pages_to_extend_ibd(
- const page_size_t& page_size,
- ulint size)
-{
- ulint size_increase; /* number of pages to extend this file */
- ulint extent_size; /* one megabyte, in pages */
- ulint threshold; /* The size of the tablespace (in number
- of pages) where we start allocating more
- than one extent at a time. */
-
- extent_size = fsp_get_extent_size_in_pages(page_size);
-
- /* The threshold is set at 32MiB except when the physical page
- size is small enough that it must be done sooner. */
- threshold = ut_min(32 * extent_size, page_size.physical());
-
- if (size < threshold) {
- size_increase = extent_size;
- } else {
- /* Below in fsp_fill_free_list() we assume
- that we add at most FSP_FREE_ADD extents at
- a time */
- size_increase = FSP_FREE_ADD * extent_size;
- }
-
- return(size_increase);
-}
-
/** Reset the page type.
Data files created before MySQL 5.1.48 may contain garbage in FIL_PAGE_TYPE.
In MySQL 3.23.53, only undo log pages and index pages were tagged.
@@ -957,7 +920,7 @@ fsp_fill_free_list(
ut_ad(size == space->size_in_header);
ut_ad(limit == space->free_limit);
- const page_size_t page_size(space->flags);
+ const ulint zip_size = space->zip_size();
if (size < limit + FSP_EXTENT_SIZE * FSP_FREE_ADD) {
bool skip_resize = init_space;
@@ -981,8 +944,8 @@ fsp_fill_free_list(
while ((init_space && i < 1)
|| ((i + FSP_EXTENT_SIZE <= size) && (count < FSP_FREE_ADD))) {
- bool init_xdes
- = (ut_2pow_remainder(i, page_size.physical()) == 0);
+ const bool init_xdes = 0
+ == ut_2pow_remainder(i, ulint(space->physical_size()));
space->free_limit = i + FSP_EXTENT_SIZE;
mlog_write_ulint(header + FSP_FREE_LIMIT, i + FSP_EXTENT_SIZE,
@@ -1000,10 +963,10 @@ fsp_fill_free_list(
const page_id_t page_id(space->id, i);
block = buf_page_create(
- page_id, page_size, mtr);
+ page_id, zip_size, mtr);
buf_page_get(
- page_id, page_size, RW_SX_LATCH, mtr);
+ page_id, zip_size, RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
@@ -1025,30 +988,23 @@ fsp_fill_free_list(
mtr_start(&ibuf_mtr);
ibuf_mtr.set_named_space(space);
- /* Avoid logging while truncate table
- fix-up is active. */
- if (srv_is_tablespace_truncated(space->id)) {
- mtr_set_log_mode(
- &ibuf_mtr, MTR_LOG_NO_REDO);
- }
-
const page_id_t page_id(
space->id,
i + FSP_IBUF_BITMAP_OFFSET);
block = buf_page_create(
- page_id, page_size, &ibuf_mtr);
+ page_id, zip_size, &ibuf_mtr);
buf_page_get(
- page_id, page_size, RW_SX_LATCH,
+ page_id, zip_size, RW_SX_LATCH,
&ibuf_mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
fsp_init_file_page(space, block, &ibuf_mtr);
-
- ibuf_bitmap_page_init(block, &ibuf_mtr);
-
+ mlog_write_ulint(block->frame + FIL_PAGE_TYPE,
+ FIL_PAGE_IBUF_BITMAP,
+ MLOG_2BYTES, &ibuf_mtr);
mtr_commit(&ibuf_mtr);
}
}
@@ -1056,7 +1012,7 @@ fsp_fill_free_list(
buf_block_t* desc_block = NULL;
descr = xdes_get_descriptor_with_space_hdr(
header, space, i, mtr, init_space, &desc_block);
- if (desc_block != NULL) {
+ if (desc_block && !space->full_crc32()) {
fil_block_check_type(
*desc_block, FIL_PAGE_TYPE_XDES, mtr);
}
@@ -1093,7 +1049,6 @@ fsp_fill_free_list(
/** Allocates a new free extent.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in] hint hint of which extent would be desirable: any
page offset in the extent goes; the hint must not be > FSP_FREE_LIMIT
@param[in,out] mtr mini-transaction
@@ -1102,7 +1057,6 @@ static
xdes_t*
fsp_alloc_free_extent(
fil_space_t* space,
- const page_size_t& page_size,
ulint hint,
mtr_t* mtr)
{
@@ -1111,12 +1065,12 @@ fsp_alloc_free_extent(
xdes_t* descr;
buf_block_t* desc_block = NULL;
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
header, space, hint, mtr, false, &desc_block);
- if (desc_block != NULL) {
+ if (desc_block && !space->full_crc32()) {
fil_block_check_type(*desc_block, FIL_PAGE_TYPE_XDES, mtr);
}
@@ -1137,8 +1091,7 @@ fsp_alloc_free_extent(
return(NULL); /* No free extents left */
}
- descr = xdes_lst_get_descriptor(
- space, page_size, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, mtr);
}
flst_remove(header + FSP_FREE, descr + XDES_FLST_NODE, mtr);
@@ -1189,7 +1142,6 @@ not previously x-latched. It is assumed that the block has been
x-latched only by mtr, and freed in mtr in that case.
@param[in,out] space tablespace
@param[in] offset page number of the allocated page
-@param[in] page_size page size of the allocated page
@param[in] rw_latch RW_SX_LATCH, RW_X_LATCH
@param[in,out] mtr mini-transaction of the allocation
@param[in,out] init_mtr mini-transaction for initializing the page
@@ -1200,15 +1152,12 @@ buf_block_t*
fsp_page_create(
fil_space_t* space,
page_no_t offset,
- const page_size_t& page_size,
rw_lock_type_t rw_latch,
mtr_t* mtr,
mtr_t* init_mtr)
{
- ut_ad(page_size.equals_to(page_size_t(space->flags)));
-
buf_block_t* block = buf_page_create(page_id_t(space->id, offset),
- page_size, init_mtr);
+ space->zip_size(), init_mtr);
ut_d(bool latched = mtr_memo_contains_flagged(mtr, block,
MTR_MEMO_PAGE_X_FIX
@@ -1245,7 +1194,6 @@ fsp_page_create(
/** Allocates a single free page from a space.
The page is marked as used.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in] hint hint of which page would be desirable
@param[in] rw_latch RW_SX_LATCH, RW_X_LATCH
@param[in,out] mtr mini-transaction
@@ -1259,7 +1207,6 @@ static MY_ATTRIBUTE((warn_unused_result, nonnull))
buf_block_t*
fsp_alloc_free_page(
fil_space_t* space,
- const page_size_t& page_size,
ulint hint,
rw_lock_type_t rw_latch,
mtr_t* mtr,
@@ -1272,7 +1219,7 @@ fsp_alloc_free_page(
const ulint space_id = space->id;
ut_d(space->modify_check(*mtr));
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
/* Get the hinted descriptor */
descr = xdes_get_descriptor_with_space_hdr(header, space, hint, mtr);
@@ -1291,8 +1238,7 @@ fsp_alloc_free_page(
FREE_FRAG list. But we will allocate our page from the
the free extent anyway. */
- descr = fsp_alloc_free_extent(space, page_size,
- hint, mtr);
+ descr = fsp_alloc_free_extent(space, hint, mtr);
if (descr == NULL) {
/* No free space left */
@@ -1304,8 +1250,7 @@ fsp_alloc_free_page(
flst_add_last(header + FSP_FREE_FRAG,
descr + XDES_FLST_NODE, mtr);
} else {
- descr = xdes_lst_get_descriptor(space, page_size,
- first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, mtr);
}
/* Reset the hint */
@@ -1353,23 +1298,17 @@ fsp_alloc_free_page(
}
fsp_alloc_from_free_frag(header, descr, free, mtr);
- return(fsp_page_create(space, page_no, page_size, rw_latch,
- mtr, init_mtr));
+ return fsp_page_create(space, page_no, rw_latch, mtr, init_mtr);
}
/** Frees a single page of a space.
The page is marked as free and clean.
@param[in,out] space tablespace
@param[in] offset page number
-@param[in] page_size page size
+@param[in] log whether to write MLOG_INIT_FREE_PAGE record
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_free_page(
- fil_space_t* space,
- ulint offset,
- const page_size_t& page_size,
- mtr_t* mtr)
+static void fsp_free_page(fil_space_t* space, page_no_t offset,
+ bool log, mtr_t* mtr)
{
fsp_header_t* header;
xdes_t* descr;
@@ -1381,7 +1320,7 @@ fsp_free_page(
/* fprintf(stderr, "Freeing page %lu in space %lu\n", page, space); */
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
header, space, offset, mtr);
@@ -1423,14 +1362,24 @@ fsp_free_page(
return;
}
+ if (UNIV_UNLIKELY(!log)) {
+ /* The last page freed in BtrBulk::finish() must be
+ written with redo logging disabled for the page
+ itself. The modifications of the allocation data
+ structures are covered by redo log. */
+ } else if (byte* log_ptr = mlog_open(mtr, 11)) {
+ log_ptr = mlog_write_initial_log_record_low(
+ MLOG_INIT_FREE_PAGE, space->id, offset, log_ptr, mtr);
+ mlog_close(mtr, log_ptr);
+ }
+
const ulint bit = offset % FSP_EXTENT_SIZE;
xdes_set_bit(descr, XDES_FREE_BIT, bit, TRUE, mtr);
/* xdes_init() should have set all XDES_CLEAN_BIT */
ut_ad(xdes_get_bit(descr, XDES_CLEAN_BIT, bit));
- frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
- mtr);
+ frag_n_used = mach_read_from_4(header + FSP_FRAG_N_USED);
if (state == XDES_FULL_FRAG) {
/* The fragment was full: move it to another list */
flst_remove(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
@@ -1451,29 +1400,22 @@ fsp_free_page(
/* The extent has become free: move it to another list */
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
mtr);
- fsp_free_extent(space, offset, page_size, mtr);
+ fsp_free_extent(space, offset, mtr);
}
}
/** Return an extent to the free list of a space.
@param[in,out] space tablespace
@param[in] offset page number in the extent
-@param[in] page_size page size
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_free_extent(
- fil_space_t* space,
- page_no_t offset,
- const page_size_t& page_size,
- mtr_t* mtr)
+static void fsp_free_extent(fil_space_t* space, page_no_t offset, mtr_t* mtr)
{
fsp_header_t* header;
xdes_t* descr;
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
- header = fsp_get_space_header(space, page_size, mtr);
+ header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(
header, space, offset, mtr);
@@ -1486,10 +1428,16 @@ fsp_free_extent(
space->free_len++;
}
+/** @return Number of segment inodes which fit on a single page */
+inline ulint FSP_SEG_INODES_PER_PAGE(ulint physical_size)
+{
+ return (physical_size - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE;
+}
+
/** Returns the nth inode slot on an inode page.
@param[in] page segment inode page
@param[in] i inode index on page
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in,out] mtr mini-transaction
@return segment inode */
UNIV_INLINE
@@ -1497,10 +1445,10 @@ fseg_inode_t*
fsp_seg_inode_page_get_nth_inode(
page_t* page,
ulint i,
- const page_size_t& page_size,
+ ulint physical_size,
mtr_t* mtr)
{
- ut_ad(i < FSP_SEG_INODES_PER_PAGE(page_size));
+ ut_ad(i < FSP_SEG_INODES_PER_PAGE(physical_size));
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_SX_FIX));
return(page + FSEG_ARR_OFFSET + FSEG_INODE_SIZE * i);
@@ -1508,23 +1456,23 @@ fsp_seg_inode_page_get_nth_inode(
/** Looks for a used segment inode on a segment inode page.
@param[in] page segment inode page
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in,out] mtr mini-transaction
@return segment inode index, or ULINT_UNDEFINED if not found */
static
ulint
fsp_seg_inode_page_find_used(
page_t* page,
- const page_size_t& page_size,
+ ulint physical_size,
mtr_t* mtr)
{
ulint i;
fseg_inode_t* inode;
- for (i = 0; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) {
+ for (i = 0; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) {
inode = fsp_seg_inode_page_get_nth_inode(
- page, i, page_size, mtr);
+ page, i, physical_size, mtr);
if (mach_read_from_8(inode + FSEG_ID)) {
/* This is used */
@@ -1541,7 +1489,7 @@ fsp_seg_inode_page_find_used(
/** Looks for an unused segment inode on a segment inode page.
@param[in] page segment inode page
@param[in] i search forward starting from this index
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in,out] mtr mini-transaction
@return segment inode index, or ULINT_UNDEFINED if not found */
static
@@ -1549,15 +1497,15 @@ ulint
fsp_seg_inode_page_find_free(
page_t* page,
ulint i,
- const page_size_t& page_size,
+ ulint physical_size,
mtr_t* mtr)
{
- for (; i < FSP_SEG_INODES_PER_PAGE(page_size); i++) {
+ for (; i < FSP_SEG_INODES_PER_PAGE(physical_size); i++) {
fseg_inode_t* inode;
inode = fsp_seg_inode_page_get_nth_inode(
- page, i, page_size, mtr);
+ page, i, physical_size, mtr);
if (!mach_read_from_8(inode + FSEG_ID)) {
/* This is unused */
@@ -1589,10 +1537,7 @@ fsp_alloc_seg_inode_page(
ut_ad(page_offset(space_header) == FSP_HEADER_OFFSET);
ut_ad(page_get_space_id(page_align(space_header)) == space->id);
- const page_size_t page_size(space->flags);
-
- block = fsp_alloc_free_page(
- space, page_size, 0, RW_SX_LATCH, mtr, mtr);
+ block = fsp_alloc_free_page(space, 0, RW_SX_LATCH, mtr, mtr);
if (block == NULL) {
@@ -1607,7 +1552,7 @@ fsp_alloc_seg_inode_page(
#ifdef UNIV_DEBUG
const byte* inode = FSEG_ID + FSEG_ARR_OFFSET + block->frame;
- for (ulint i = FSP_SEG_INODES_PER_PAGE(page_size); i--;
+ for (ulint i = FSP_SEG_INODES_PER_PAGE(space->physical_size()); i--;
inode += FSEG_INODE_SIZE) {
ut_ad(!mach_read_from_8(inode));
}
@@ -1646,25 +1591,29 @@ fsp_alloc_seg_inode(
&& !fsp_alloc_seg_inode_page(space, space_header, mtr)) {
return(NULL);
}
- const page_size_t page_size(space->flags);
const page_id_t page_id(
space->id,
flst_get_first(space_header + FSP_SEG_INODES_FREE, mtr).page);
- block = buf_page_get(page_id, page_size, RW_SX_LATCH, mtr);
+ block = buf_page_get(page_id, space->zip_size(), RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
- fil_block_check_type(*block, FIL_PAGE_INODE, mtr);
+ if (!space->full_crc32()) {
+ fil_block_check_type(*block, FIL_PAGE_INODE, mtr);
+ }
page = buf_block_get_frame(block);
- n = fsp_seg_inode_page_find_free(page, 0, page_size, mtr);
+ const ulint physical_size = space->physical_size();
+
+ n = fsp_seg_inode_page_find_free(page, 0, physical_size, mtr);
ut_a(n != ULINT_UNDEFINED);
- inode = fsp_seg_inode_page_get_nth_inode(page, n, page_size, mtr);
+ inode = fsp_seg_inode_page_get_nth_inode(page, n, physical_size, mtr);
if (ULINT_UNDEFINED == fsp_seg_inode_page_find_free(page, n + 1,
- page_size, mtr)) {
+ physical_size,
+ mtr)) {
/* There are no other unused headers left on the page: move it
to another list */
@@ -1682,14 +1631,10 @@ fsp_alloc_seg_inode(
/** Frees a file segment inode.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] inode segment inode
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_free_seg_inode(
+static void fsp_free_seg_inode(
fil_space_t* space,
- const page_size_t& page_size,
fseg_inode_t* inode,
mtr_t* mtr)
{
@@ -1700,12 +1645,14 @@ fsp_free_seg_inode(
page = page_align(inode);
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
ut_ad(mach_read_from_4(inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE);
+ const ulint physical_size = space->physical_size();
+
if (ULINT_UNDEFINED
- == fsp_seg_inode_page_find_free(page, 0, page_size, mtr)) {
+ == fsp_seg_inode_page_find_free(page, 0, physical_size, mtr)) {
/* Move the page to another list */
@@ -1720,21 +1667,21 @@ fsp_free_seg_inode(
mlog_write_ulint(inode + FSEG_MAGIC_N, 0xfa051ce3, MLOG_4BYTES, mtr);
if (ULINT_UNDEFINED
- == fsp_seg_inode_page_find_used(page, page_size, mtr)) {
+ == fsp_seg_inode_page_find_used(page, physical_size, mtr)) {
/* There are no other used headers left on the page: free it */
flst_remove(space_header + FSP_SEG_INODES_FREE,
page + FSEG_INODE_PAGE_NODE, mtr);
- fsp_free_page(space, page_get_page_no(page), page_size, mtr);
+ fsp_free_page(space, page_get_page_no(page), true, mtr);
}
}
/** Returns the file segment inode, page x-latched.
@param[in] header segment header
@param[in] space space id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction
@param[out] block inode block, or NULL to ignore
@return segment inode, page x-latched; NULL if the inode is free */
@@ -1743,7 +1690,7 @@ fseg_inode_t*
fseg_inode_try_get(
fseg_header_t* header,
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr,
buf_block_t** block)
{
@@ -1754,7 +1701,7 @@ fseg_inode_try_get(
inode_addr.boffset = mach_read_from_2(header + FSEG_HDR_OFFSET);
ut_ad(space == mach_read_from_4(header + FSEG_HDR_SPACE));
- inode = fut_get_ptr(space, page_size, inode_addr, RW_SX_LATCH, mtr,
+ inode = fut_get_ptr(space, zip_size, inode_addr, RW_SX_LATCH, mtr,
block);
if (UNIV_UNLIKELY(!mach_read_from_8(inode + FSEG_ID))) {
@@ -1771,7 +1718,7 @@ fseg_inode_try_get(
/** Returns the file segment inode, page x-latched.
@param[in] header segment header
@param[in] space space id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction
@param[out] block inode block
@return segment inode, page x-latched */
@@ -1780,12 +1727,12 @@ fseg_inode_t*
fseg_inode_get(
fseg_header_t* header,
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr,
buf_block_t** block = NULL)
{
fseg_inode_t* inode
- = fseg_inode_try_get(header, space, page_size, mtr, block);
+ = fseg_inode_try_get(header, space, zip_size, mtr, block);
ut_a(inode);
return(inode);
}
@@ -1936,7 +1883,6 @@ fseg_create(
buf_block_t* block = 0; /* remove warning */
fseg_header_t* header = 0; /* remove warning */
ulint n_reserved;
- ulint i;
DBUG_ENTER("fseg_create");
@@ -1945,21 +1891,22 @@ fseg_create(
<= srv_page_size - FIL_PAGE_DATA_END);
mtr_x_lock_space(space, mtr);
- const page_size_t page_size(space->flags);
ut_d(space->modify_check(*mtr));
if (page != 0) {
- block = buf_page_get(page_id_t(space->id, page), page_size,
+ block = buf_page_get(page_id_t(space->id, page),
+ space->zip_size(),
RW_SX_LATCH, mtr);
header = byte_offset + buf_block_get_frame(block);
- const ulint type = space->id == TRX_SYS_SPACE
- && page == TRX_SYS_PAGE_NO
- ? FIL_PAGE_TYPE_TRX_SYS
- : FIL_PAGE_TYPE_SYS;
-
- fil_block_check_type(*block, type, mtr);
+ if (!space->full_crc32()) {
+ fil_block_check_type(*block, space->id == TRX_SYS_SPACE
+ && page == TRX_SYS_PAGE_NO
+ ? FIL_PAGE_TYPE_TRX_SYS
+ : FIL_PAGE_TYPE_SYS,
+ mtr);
+ }
}
if (!has_done_reservation
@@ -1968,7 +1915,7 @@ fseg_create(
DBUG_RETURN(NULL);
}
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
inode = fsp_alloc_seg_inode(space, space_header, mtr);
@@ -1982,9 +1929,8 @@ fseg_create(
seg_id = mach_read_from_8(space_header + FSP_SEG_ID);
mlog_write_ull(space_header + FSP_SEG_ID, seg_id + 1, mtr);
-
mlog_write_ull(inode + FSEG_ID, seg_id, mtr);
- mlog_write_ulint(inode + FSEG_NOT_FULL_N_USED, 0, MLOG_4BYTES, mtr);
+ ut_ad(!mach_read_from_4(inode + FSEG_NOT_FULL_N_USED));
flst_init(inode + FSEG_FREE, mtr);
flst_init(inode + FSEG_NOT_FULL, mtr);
@@ -1992,12 +1938,13 @@ fseg_create(
mlog_write_ulint(inode + FSEG_MAGIC_N, FSEG_MAGIC_N_VALUE,
MLOG_4BYTES, mtr);
- for (i = 0; i < FSEG_FRAG_ARR_N_SLOTS; i++) {
- fseg_set_nth_frag_page_no(inode, i, FIL_NULL, mtr);
- }
+ compile_time_assert(FSEG_FRAG_SLOT_SIZE == 4);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mlog_memset(inode + FSEG_FRAG_ARR,
+ FSEG_FRAG_SLOT_SIZE * FSEG_FRAG_ARR_N_SLOTS, 0xff, mtr);
if (page == 0) {
- block = fseg_alloc_free_page_low(space, page_size,
+ block = fseg_alloc_free_page_low(space,
inode, 0, FSP_UP, RW_SX_LATCH,
mtr, mtr
#ifdef UNIV_DEBUG
@@ -2010,9 +1957,7 @@ fseg_create(
ut_ad(!has_done_reservation || block != NULL);
if (block == NULL) {
-
- fsp_free_seg_inode(space, page_size, inode, mtr);
-
+ fsp_free_seg_inode(space, inode, mtr);
goto funct_exit;
}
@@ -2089,9 +2034,7 @@ fseg_n_reserved_pages(
space_id = page_get_space_id(page_align(header));
space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
-
- inode = fseg_inode_get(header, space_id, page_size, mtr);
+ inode = fseg_inode_get(header, space_id, space->zip_size(), mtr);
ret = fseg_n_reserved_pages_low(inode, used, mtr);
@@ -2104,7 +2047,6 @@ the free list is empty, and the extents can be allocated consecutively from
the hint onward.
@param[in] inode segment inode
@param[in] space tablespace
-@param[in] page_size page size
@param[in] hint hint which extent would be good as the first
extent
@param[in,out] mtr mini-transaction */
@@ -2113,7 +2055,6 @@ void
fseg_fill_free_list(
fseg_inode_t* inode,
fil_space_t* space,
- const page_size_t& page_size,
ulint hint,
mtr_t* mtr)
{
@@ -2143,7 +2084,7 @@ fseg_fill_free_list(
}
for (i = 0; i < FSEG_FREE_LIST_MAX_LEN; i++) {
- descr = xdes_get_descriptor(space, hint, page_size, mtr);
+ descr = xdes_get_descriptor(space, hint, mtr);
if ((descr == NULL)
|| (XDES_FREE != xdes_get_state(descr, mtr))) {
@@ -2153,7 +2094,7 @@ fseg_fill_free_list(
return;
}
- descr = fsp_alloc_free_extent(space, page_size, hint, mtr);
+ descr = fsp_alloc_free_extent(space, hint, mtr);
xdes_set_state(descr, XDES_FSEG, mtr);
@@ -2173,7 +2114,6 @@ NOTE that the extent returned still resides in the segment free list, it is
not yet taken off it!
@param[in] inode segment inode
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@retval NULL if no page could be allocated
@retval block rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
@@ -2184,7 +2124,6 @@ xdes_t*
fseg_alloc_free_extent(
fseg_inode_t* inode,
fil_space_t* space,
- const page_size_t& page_size,
mtr_t* mtr)
{
xdes_t* descr;
@@ -2200,10 +2139,10 @@ fseg_alloc_free_extent(
first = flst_get_first(inode + FSEG_FREE, mtr);
- descr = xdes_lst_get_descriptor(space, page_size, first, mtr);
+ descr = xdes_lst_get_descriptor(space, first, mtr);
} else {
/* Segment free list was empty, allocate from space */
- descr = fsp_alloc_free_extent(space, page_size, 0, mtr);
+ descr = fsp_alloc_free_extent(space, 0, mtr);
if (descr == NULL) {
@@ -2217,7 +2156,7 @@ fseg_alloc_free_extent(
flst_add_last(inode + FSEG_FREE, descr + XDES_FLST_NODE, mtr);
/* Try to fill the segment free list */
- fseg_fill_free_list(inode, space, page_size,
+ fseg_fill_free_list(inode, space,
xdes_get_offset(descr) + FSP_EXTENT_SIZE,
mtr);
}
@@ -2229,7 +2168,6 @@ fseg_alloc_free_extent(
This function implements the intelligent allocation strategy which tries to
minimize file space fragmentation.
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in,out] seg_inode segment inode
@param[in] hint hint of which page would be desirable
@param[in] direction if the new page is needed because of
@@ -2250,7 +2188,6 @@ static
buf_block_t*
fseg_alloc_free_page_low(
fil_space_t* space,
- const page_size_t& page_size,
fseg_inode_t* seg_inode,
ulint hint,
byte direction,
@@ -2285,7 +2222,7 @@ fseg_alloc_free_page_low(
reserved = fseg_n_reserved_pages_low(seg_inode, &used, mtr);
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
descr = xdes_get_descriptor_with_space_hdr(space_header, space,
hint, mtr);
@@ -2294,7 +2231,7 @@ fseg_alloc_free_page_low(
hint */
/* The file space header page is always allocated. */
hint = 0;
- descr = xdes_get_descriptor(space, hint, page_size, mtr);
+ descr = xdes_get_descriptor(space, hint, mtr);
}
/* In the big if-else below we look for ret_page and ret_descr */
@@ -2321,7 +2258,7 @@ take_hinted_page:
=========================================================
the hinted page
===============*/
- ret_descr = fsp_alloc_free_extent(space, page_size, hint, mtr);
+ ret_descr = fsp_alloc_free_extent(space, hint, mtr);
ut_a(ret_descr == descr);
@@ -2331,7 +2268,7 @@ take_hinted_page:
ret_descr + XDES_FLST_NODE, mtr);
/* Try to fill the segment free list */
- fseg_fill_free_list(seg_inode, space, page_size,
+ fseg_fill_free_list(seg_inode, space,
hint + FSP_EXTENT_SIZE, mtr);
goto take_hinted_page;
/*-----------------------------------------------------------*/
@@ -2339,8 +2276,7 @@ take_hinted_page:
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
&& (used >= FSEG_FRAG_LIMIT)
&& (!!(ret_descr
- = fseg_alloc_free_extent(
- seg_inode, space, page_size, mtr)))) {
+ = fseg_alloc_free_extent(seg_inode, space, mtr)))) {
/* 3. We take any free extent (which was already assigned above
===============================================================
@@ -2386,8 +2322,7 @@ take_hinted_page:
return(NULL);
}
- ret_descr = xdes_lst_get_descriptor(space, page_size,
- first, mtr);
+ ret_descr = xdes_lst_get_descriptor(space, first, mtr);
ret_page = xdes_get_offset(ret_descr)
+ xdes_find_bit(ret_descr, XDES_FREE_BIT, TRUE,
0, mtr);
@@ -2397,7 +2332,7 @@ take_hinted_page:
/* 6. We allocate an individual page from the space
===================================================*/
buf_block_t* block = fsp_alloc_free_page(
- space, page_size, hint, rw_latch, mtr, init_mtr);
+ space, hint, rw_latch, mtr, init_mtr);
ut_ad(!has_done_reservation || block != NULL);
@@ -2419,8 +2354,7 @@ take_hinted_page:
} else {
/* 7. We allocate a new extent and take its first page
======================================================*/
- ret_descr = fseg_alloc_free_extent(seg_inode,
- space, page_size, mtr);
+ ret_descr = fseg_alloc_free_extent(seg_inode, space, mtr);
if (ret_descr == NULL) {
ret_page = FIL_NULL;
@@ -2468,8 +2402,7 @@ got_hinted_page:
The extent is still in the appropriate list (FSEG_NOT_FULL
or FSEG_FREE), and the page is not yet marked as used. */
- ut_ad(xdes_get_descriptor(space, ret_page, page_size, mtr)
- == ret_descr);
+ ut_ad(xdes_get_descriptor(space, ret_page, mtr) == ret_descr);
ut_ad(xdes_mtr_get_bit(
ret_descr, XDES_FREE_BIT,
@@ -2478,8 +2411,7 @@ got_hinted_page:
fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
}
- return(fsp_page_create(space, ret_page, page_size, rw_latch,
- mtr, init_mtr));
+ return fsp_page_create(space, ret_page, rw_latch, mtr, init_mtr);
}
/**********************************************************************//**
@@ -2521,10 +2453,11 @@ fseg_alloc_free_page_general(
space_id = page_get_space_id(page_align(seg_header));
space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
-
- inode = fseg_inode_get(seg_header, space_id, page_size, mtr, &iblock);
- fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ inode = fseg_inode_get(seg_header, space_id, space->zip_size(),
+ mtr, &iblock);
+ if (!space->full_crc32()) {
+ fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ }
if (!has_done_reservation
&& !fsp_reserve_free_extents(&n_reserved, space, 2,
@@ -2532,7 +2465,7 @@ fseg_alloc_free_page_general(
return(NULL);
}
- block = fseg_alloc_free_page_low(space, page_size,
+ block = fseg_alloc_free_page_low(space,
inode, hint, direction,
RW_X_LATCH, mtr, init_mtr
#ifdef UNIV_DEBUG
@@ -2650,9 +2583,9 @@ fsp_reserve_free_extents(
*n_reserved = n_ext;
mtr_x_lock_space(space, mtr);
- const page_size_t page_size(space->flags);
+ const ulint physical_size = space->physical_size();
- space_header = fsp_get_space_header(space, page_size, mtr);
+ space_header = fsp_get_space_header(space, mtr);
try_again:
size = mach_read_from_4(space_header + FSP_SIZE);
ut_ad(size == space->size_in_header);
@@ -2667,8 +2600,7 @@ try_again:
n_free_list_ext = flst_get_len(space_header + FSP_FREE);
ut_ad(space->free_len == n_free_list_ext);
- free_limit = mtr_read_ulint(space_header + FSP_FREE_LIMIT,
- MLOG_4BYTES, mtr);
+ free_limit = mach_read_from_4(space_header + FSP_FREE_LIMIT);
ut_ad(space->free_limit == free_limit);
/* Below we play safe when counting free extents above the free limit:
@@ -2684,8 +2616,7 @@ try_again:
if (n_free_up > 0) {
n_free_up--;
- n_free_up -= n_free_up / (page_size.physical()
- / FSP_EXTENT_SIZE);
+ n_free_up -= n_free_up / (physical_size / FSP_EXTENT_SIZE);
}
n_free = n_free_list_ext + n_free_up;
@@ -2751,9 +2682,7 @@ fseg_mark_page_used(
ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE));
ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N)
== FSEG_MAGIC_N_VALUE);
-
- ut_ad(mtr_read_ulint(seg_inode + FSEG_ID, MLOG_4BYTES, mtr)
- == mtr_read_ulint(descr + XDES_ID, MLOG_4BYTES, mtr));
+ ut_ad(!memcmp(seg_inode + FSEG_ID, descr + XDES_ID, 4));
if (xdes_is_free(descr, mtr)) {
/* We move the extent from the free list to the
@@ -2770,8 +2699,7 @@ fseg_mark_page_used(
/* We mark the page as used */
xdes_set_bit(descr, XDES_FREE_BIT, page % FSP_EXTENT_SIZE, FALSE, mtr);
- not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
+ not_full_n_used = mach_read_from_4(seg_inode + FSEG_NOT_FULL_N_USED);
not_full_n_used++;
mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED, not_full_n_used,
MLOG_4BYTES, mtr);
@@ -2793,9 +2721,9 @@ fseg_mark_page_used(
@param[in] seg_inode segment inode
@param[in,out] space tablespace
@param[in] offset page number
-@param[in] page_size page size
@param[in] ahi whether we may need to drop the adaptive
hash index
+@param[in] log whether to write MLOG_INIT_FREE_PAGE record
@param[in,out] mtr mini-transaction */
static
void
@@ -2803,10 +2731,10 @@ fseg_free_page_low(
fseg_inode_t* seg_inode,
fil_space_t* space,
page_no_t offset,
- const page_size_t& page_size,
#ifdef BTR_CUR_HASH_ADAPT
bool ahi,
#endif /* BTR_CUR_HASH_ADAPT */
+ bool log,
mtr_t* mtr)
{
xdes_t* descr;
@@ -2831,7 +2759,7 @@ fseg_free_page_low(
}
#endif /* BTR_CUR_HASH_ADAPT */
- descr = xdes_get_descriptor(space, offset, page_size, mtr);
+ descr = xdes_get_descriptor(space, offset, mtr);
if (xdes_mtr_get_bit(descr, XDES_FREE_BIT,
offset % FSP_EXTENT_SIZE, mtr)) {
@@ -2848,19 +2776,19 @@ fseg_free_page_low(
if (state != XDES_FSEG) {
/* The page is in the fragment pages of the segment */
-
for (ulint i = 0;; i++) {
if (fseg_get_nth_frag_page_no(seg_inode, i, mtr)
- == offset) {
-
- fseg_set_nth_frag_page_no(seg_inode, i,
- FIL_NULL, mtr);
- break;
+ != offset) {
+ continue;
}
- }
- fsp_free_page(space, offset, page_size, mtr);
+ compile_time_assert(FIL_NULL == 0xffffffff);
+ mlog_memset(seg_inode + FSEG_FRAG_ARR
+ + i * FSEG_FRAG_SLOT_SIZE, 4, 0xff, mtr);
+ break;
+ }
+ fsp_free_page(space, offset, log, mtr);
return;
}
@@ -2884,8 +2812,7 @@ fseg_free_page_low(
<< FORCE_RECOVERY_MSG;
}
- not_full_n_used = mtr_read_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
+ not_full_n_used = mach_read_from_4(seg_inode + FSEG_NOT_FULL_N_USED);
if (xdes_is_full(descr, mtr)) {
/* The fragment is full: move it to another list */
flst_remove(seg_inode + FSEG_FULL,
@@ -2911,13 +2838,13 @@ fseg_free_page_low(
/* The extent has become free: free it to space */
flst_remove(seg_inode + FSEG_NOT_FULL,
descr + XDES_FLST_NODE, mtr);
- fsp_free_extent(space, offset, page_size, mtr);
+ fsp_free_extent(space, offset, mtr);
}
}
#ifndef BTR_CUR_HASH_ADAPT
-# define fseg_free_page_low(inode, space, offset, page_size, ahi, mtr) \
- fseg_free_page_low(inode, space, offset, page_size, mtr)
+# define fseg_free_page_low(inode, space, offset, ahi, log, mtr) \
+ fseg_free_page_low(inode, space, offset, log, mtr)
#endif /* !BTR_CUR_HASH_ADAPT */
/** Free a page in a file segment.
@@ -2926,6 +2853,7 @@ fseg_free_page_low(
@param[in] offset page number
@param[in] ahi whether we may need to drop the adaptive
hash index
+@param[in] log whether to write MLOG_INIT_FREE_PAGE record
@param[in,out] mtr mini-transaction */
void
fseg_free_page_func(
@@ -2935,22 +2863,25 @@ fseg_free_page_func(
#ifdef BTR_CUR_HASH_ADAPT
bool ahi,
#endif /* BTR_CUR_HASH_ADAPT */
+ bool log,
mtr_t* mtr)
{
DBUG_ENTER("fseg_free_page");
fseg_inode_t* seg_inode;
buf_block_t* iblock;
mtr_x_lock_space(space, mtr);
- const page_size_t page_size(space->flags);
DBUG_LOG("fseg_free_page", "space_id: " << space->id
<< ", page_no: " << offset);
- seg_inode = fseg_inode_get(seg_header, space->id, page_size, mtr,
+ seg_inode = fseg_inode_get(seg_header, space->id, space->zip_size(),
+ mtr,
&iblock);
- fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ if (!space->full_crc32()) {
+ fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ }
- fseg_free_page_low(seg_inode, space, offset, page_size, ahi, mtr);
+ fseg_free_page_low(seg_inode, space, offset, ahi, log, mtr);
ut_d(buf_page_set_file_page_was_freed(page_id_t(space->id, offset)));
@@ -2966,8 +2897,8 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
{
bool is_free;
mtr_t mtr;
- page_size_t page_size(space->flags);
- page_no_t dpage = xdes_calc_descriptor_page(page_size, page);
+ page_no_t dpage = xdes_calc_descriptor_page(space->zip_size(),
+ page);
mtr.start();
mtr_s_lock_space(space, &mtr);
@@ -2975,7 +2906,7 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
if (page >= space->free_limit || page >= space->size_in_header) {
is_free = true;
} else if (const xdes_t* descr = xdes_get_descriptor_const(
- space, dpage, page, page_size, &mtr)) {
+ space, dpage, page, &mtr)) {
is_free = xdes_get_bit(descr, XDES_FREE_BIT,
page % FSP_EXTENT_SIZE);
} else {
@@ -2989,7 +2920,6 @@ fseg_page_is_free(fil_space_t* space, unsigned page)
/** Free an extent of a segment to the space free list.
@param[in,out] seg_inode segment inode
@param[in,out] space tablespace
-@param[in] page_size page size
@param[in] page page number in the extent
@param[in] ahi whether we may need to drop
the adaptive hash index
@@ -3000,7 +2930,6 @@ void
fseg_free_extent(
fseg_inode_t* seg_inode,
fil_space_t* space,
- const page_size_t& page_size,
ulint page,
#ifdef BTR_CUR_HASH_ADAPT
bool ahi,
@@ -3014,7 +2943,7 @@ fseg_free_extent(
ut_ad(mtr != NULL);
- descr = xdes_get_descriptor(space, page, page_size, mtr);
+ descr = xdes_get_descriptor(space, page, mtr);
ut_a(xdes_get_state(descr, mtr) == XDES_FSEG);
ut_a(!memcmp(descr + XDES_ID, seg_inode + FSEG_ID, 8));
@@ -3051,9 +2980,8 @@ fseg_free_extent(
flst_remove(seg_inode + FSEG_NOT_FULL,
descr + XDES_FLST_NODE, mtr);
- not_full_n_used = mtr_read_ulint(
- seg_inode + FSEG_NOT_FULL_N_USED, MLOG_4BYTES, mtr);
-
+ not_full_n_used = mach_read_from_4(FSEG_NOT_FULL_N_USED
+ + seg_inode);
descr_n_used = xdes_get_n_used(descr, mtr);
ut_a(not_full_n_used >= descr_n_used);
mlog_write_ulint(seg_inode + FSEG_NOT_FULL_N_USED,
@@ -3061,7 +2989,7 @@ fseg_free_extent(
MLOG_4BYTES, mtr);
}
- fsp_free_extent(space, page, page_size, mtr);
+ fsp_free_extent(space, page, mtr);
#ifdef UNIV_DEBUG
for (ulint i = 0; i < FSP_EXTENT_SIZE; i++) {
@@ -3073,8 +3001,8 @@ fseg_free_extent(
}
#ifndef BTR_CUR_HASH_ADAPT
-# define fseg_free_extent(inode, space, page_size, page, ahi, mtr) \
- fseg_free_extent(inode, space, page_size, page, mtr)
+# define fseg_free_extent(inode, space, page, ahi, mtr) \
+ fseg_free_extent(inode, space, page, mtr)
#endif /* !BTR_CUR_HASH_ADAPT */
/**********************************************************************//**
@@ -3108,9 +3036,8 @@ fseg_free_step_func(
header_page = page_get_page_no(page_align(header));
fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
- descr = xdes_get_descriptor(space, header_page, page_size, mtr);
+ descr = xdes_get_descriptor(space, header_page, mtr);
/* Check that the header resides on a page which has not been
freed yet */
@@ -3118,8 +3045,8 @@ fseg_free_step_func(
ut_a(xdes_mtr_get_bit(descr, XDES_FREE_BIT,
header_page % FSP_EXTENT_SIZE, mtr) == FALSE);
buf_block_t* iblock;
-
- inode = fseg_inode_try_get(header, space_id, page_size, mtr, &iblock);
+ const ulint zip_size = space->zip_size();
+ inode = fseg_inode_try_get(header, space_id, zip_size, mtr, &iblock);
if (inode == NULL) {
ib::info() << "Double free of inode from "
@@ -3127,15 +3054,15 @@ fseg_free_step_func(
DBUG_RETURN(TRUE);
}
- fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
- descr = fseg_get_first_extent(inode, space, page_size, mtr);
+ if (!space->full_crc32()) {
+ fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ }
+ descr = fseg_get_first_extent(inode, space, mtr);
if (descr != NULL) {
/* Free the extent held by the segment */
page = xdes_get_offset(descr);
-
- fseg_free_extent(inode, space, page_size, page, ahi, mtr);
-
+ fseg_free_extent(inode, space, page, ahi, mtr);
DBUG_RETURN(FALSE);
}
@@ -3144,7 +3071,7 @@ fseg_free_step_func(
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
- fsp_free_seg_inode(space, page_size, inode, mtr);
+ fsp_free_seg_inode(space, inode, mtr);
DBUG_RETURN(TRUE);
}
@@ -3152,13 +3079,13 @@ fseg_free_step_func(
fseg_free_page_low(
inode, space,
fseg_get_nth_frag_page_no(inode, n, mtr),
- page_size, ahi, mtr);
+ ahi, true, mtr);
n = fseg_find_last_used_frag_page_slot(inode, mtr);
if (n == ULINT_UNDEFINED) {
/* Freeing completed: free the segment inode */
- fsp_free_seg_inode(space, page_size, inode, mtr);
+ fsp_free_seg_inode(space, inode, mtr);
DBUG_RETURN(TRUE);
}
@@ -3191,19 +3118,21 @@ fseg_free_step_not_header_func(
ut_ad(mtr->is_named_space(space_id));
fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
buf_block_t* iblock;
- inode = fseg_inode_get(header, space_id, page_size, mtr, &iblock);
- fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ inode = fseg_inode_get(header, space_id, space->zip_size(), mtr,
+ &iblock);
+ if (!space->full_crc32()) {
+ fil_block_check_type(*iblock, FIL_PAGE_INODE, mtr);
+ }
- descr = fseg_get_first_extent(inode, space, page_size, mtr);
+ descr = fseg_get_first_extent(inode, space, mtr);
if (descr != NULL) {
/* Free the extent held by the segment */
page = xdes_get_offset(descr);
- fseg_free_extent(inode, space, page_size, page, ahi, mtr);
+ fseg_free_extent(inode, space, page, ahi, mtr);
return(FALSE);
}
@@ -3223,7 +3152,7 @@ fseg_free_step_not_header_func(
return(TRUE);
}
- fseg_free_page_low(inode, space, page_no, page_size, ahi, mtr);
+ fseg_free_page_low(inode, space, page_no, ahi, true, mtr);
return(FALSE);
}
@@ -3233,7 +3162,6 @@ We think of the extent lists of the segment catenated in the order
FSEG_FULL -> FSEG_NOT_FULL -> FSEG_FREE.
@param[in] inode segment inode
@param[in] space tablespace
-@param[in] page_size page size
@param[in,out] mtr mini-transaction
@return the first extent descriptor, or NULL if none */
MY_ATTRIBUTE((nonnull, warn_unused_result))
@@ -3242,7 +3170,6 @@ xdes_t*
fseg_get_first_extent(
fseg_inode_t* inode,
const fil_space_t* space,
- const page_size_t& page_size,
mtr_t* mtr)
{
fil_addr_t first;
@@ -3268,7 +3195,7 @@ fseg_get_first_extent(
ut_ad(first.page != FIL_NULL);
return(first.page == FIL_NULL ? NULL
- : xdes_lst_get_descriptor(space, page_size, first, mtr));
+ : xdes_lst_get_descriptor(space, first, mtr));
}
#ifdef UNIV_BTR_PRINT
@@ -3299,9 +3226,7 @@ fseg_print_low(
reserved = fseg_n_reserved_pages_low(inode, &used, mtr);
seg_id = mach_read_from_8(inode + FSEG_ID);
-
- n_used = mtr_read_ulint(inode + FSEG_NOT_FULL_N_USED,
- MLOG_4BYTES, mtr);
+ n_used = mach_read_from_4(inode + FSEG_NOT_FULL_N_USED);
n_frag = fseg_get_n_frag_pages(inode, mtr);
n_free = flst_get_len(inode + FSEG_FREE);
n_not_full = flst_get_len(inode + FSEG_NOT_FULL);
@@ -3332,32 +3257,20 @@ fseg_print(
space_id = page_get_space_id(page_align(header));
const fil_space_t* space = mtr_x_lock_space(space_id, mtr);
- const page_size_t page_size(space->flags);
- inode = fseg_inode_get(header, space_id, page_size, mtr);
+ inode = fseg_inode_get(header, space_id, space->zip_size(), mtr);
fseg_print_low(inode, mtr);
}
#endif /* UNIV_BTR_PRINT */
#ifdef UNIV_DEBUG
-/** Print the file segment header to the given output stream.
-@param[in] out the output stream into which the object is printed.
-@retval the output stream into which the object was printed. */
-std::ostream&
-fseg_header::to_stream(std::ostream& out) const
+std::ostream &fseg_header::to_stream(std::ostream &out) const
{
- const ulint space = mtr_read_ulint(m_header + FSEG_HDR_SPACE,
- MLOG_4BYTES, m_mtr);
- const ulint page_no = mtr_read_ulint(m_header + FSEG_HDR_PAGE_NO,
- MLOG_4BYTES, m_mtr);
-
- const ulint offset = mtr_read_ulint(m_header + FSEG_HDR_OFFSET,
- MLOG_2BYTES, m_mtr);
-
- out << "[fseg_header_t: space=" << space << ", page="
- << page_no << ", offset=" << offset << "]";
-
- return(out);
+ out << "[fseg_header_t: space="
+ << mach_read_from_4(m_header + FSEG_HDR_SPACE)
+ << ", page=" << mach_read_from_4(m_header + FSEG_HDR_PAGE_NO)
+ << ", offset=" << mach_read_from_2(m_header + FSEG_HDR_OFFSET) << "]";
+ return out;
}
#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/fsp/fsp0space.cc b/storage/innobase/fsp/fsp0space.cc
index 757eeaf90ae..1ed4af86367 100644
--- a/storage/innobase/fsp/fsp0space.cc
+++ b/storage/innobase/fsp/fsp0space.cc
@@ -118,8 +118,20 @@ Tablespace::open_or_create(bool is_temp)
/* Create the tablespace entry for the multi-file
tablespace in the tablespace manager. */
+ ulint fsp_flags = 0;
+
+ switch (srv_checksum_algorithm) {
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
+ fsp_flags = (FSP_FLAGS_FCRC32_MASK_MARKER
+ | FSP_FLAGS_FCRC32_PAGE_SSIZE());
+ break;
+ default:
+ fsp_flags = FSP_FLAGS_PAGE_SSIZE();
+ }
+
space = fil_space_create(
- m_name, m_space_id, FSP_FLAGS_PAGE_SSIZE(),
+ m_name, m_space_id, fsp_flags,
is_temp
? FIL_TYPE_TEMPORARY : FIL_TYPE_TABLESPACE,
NULL);
diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc
index dd4eb294dc4..c1772c359ea 100644
--- a/storage/innobase/fsp/fsp0sysspace.cc
+++ b/storage/innobase/fsp/fsp0sysspace.cc
@@ -914,7 +914,7 @@ SysTablespace::open_or_create(
ut_ad(!fil_system.sys_space);
ut_ad(space_id() == TRX_SYS_SPACE);
space = fil_system.sys_space = fil_space_create(
- name(), TRX_SYS_SPACE, flags(),
+ name(), TRX_SYS_SPACE, it->flags(),
FIL_TYPE_TABLESPACE, NULL);
if (!space) {
return DB_ERROR;
diff --git a/storage/innobase/fts/fts0config.cc b/storage/innobase/fts/fts0config.cc
index 88ce21c75aa..410d60a5f4e 100644
--- a/storage/innobase/fts/fts0config.cc
+++ b/storage/innobase/fts/fts0config.cc
@@ -120,9 +120,9 @@ fts_config_get_value(
error = fts_eval_sql(trx, graph);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
que_graph_free(graph);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return(error);
}
diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc
index 6b324354527..85238f3acad 100644
--- a/storage/innobase/fts/fts0fts.cc
+++ b/storage/innobase/fts/fts0fts.cc
@@ -465,7 +465,7 @@ fts_load_user_stopword(
trx->op_info = "Load user stopword table into FTS cache";
if (!has_lock) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
/* Validate the user table existence and in the right
@@ -537,7 +537,7 @@ fts_load_user_stopword(
cleanup:
if (!has_lock) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
trx_free(trx);
@@ -908,7 +908,7 @@ fts_drop_index(
}
/****************************************************************//**
-Free the query graph but check whether dict_sys->mutex is already
+Free the query graph but check whether dict_sys.mutex is already
held */
void
fts_que_graph_free_check_lock(
@@ -930,15 +930,15 @@ fts_que_graph_free_check_lock(
}
if (!has_dict) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
que_graph_free(graph);
if (!has_dict) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
}
@@ -3207,15 +3207,10 @@ fts_fetch_doc_from_rec(
documents */
{
dict_index_t* index;
- dict_table_t* table;
const rec_t* clust_rec;
- ulint num_field;
const dict_field_t* ifield;
- const dict_col_t* col;
ulint clust_pos;
- ulint i;
ulint doc_len = 0;
- ulint processed_doc = 0;
st_mysql_ftparser* parser;
if (!get_doc) {
@@ -3223,19 +3218,15 @@ fts_fetch_doc_from_rec(
}
index = get_doc->index_cache->index;
- table = get_doc->index_cache->index->table;
parser = get_doc->index_cache->index->parser;
clust_rec = btr_pcur_get_rec(pcur);
ut_ad(!page_rec_is_comp(clust_rec)
|| rec_get_status(clust_rec) == REC_STATUS_ORDINARY);
- num_field = dict_index_get_n_fields(index);
-
- for (i = 0; i < num_field; i++) {
+ for (ulint i = 0; i < index->n_fields; i++) {
ifield = dict_index_get_nth_field(index, i);
- col = dict_field_get_col(ifield);
- clust_pos = dict_col_get_clust_pos(col, clust_index);
+ clust_pos = dict_col_get_clust_pos(ifield->col, clust_index);
if (!get_doc->index_cache->charset) {
get_doc->index_cache->charset = fts_get_charset(
@@ -3246,7 +3237,7 @@ fts_fetch_doc_from_rec(
doc->text.f_str =
btr_rec_copy_externally_stored_field(
clust_rec, offsets,
- dict_table_page_size(table),
+ btr_pcur_get_block(pcur)->zip_size(),
clust_pos, &doc->text.f_len,
static_cast<mem_heap_t*>(
doc->self_heap->arg));
@@ -3264,13 +3255,12 @@ fts_fetch_doc_from_rec(
continue;
}
- if (processed_doc == 0) {
+ if (!doc_len) {
fts_tokenize_document(doc, NULL, parser);
} else {
fts_tokenize_document_next(doc, doc_len, NULL, parser);
}
- processed_doc++;
doc_len += doc->text.f_len + 1;
}
}
@@ -3635,8 +3625,7 @@ fts_read_ulint(
dfield_t* dfield = que_node_get_val(exp);
void* data = dfield_get_data(dfield);
- *value = static_cast<ulint>(mach_read_from_4(
- static_cast<const byte*>(data)));
+ *value = mach_read_from_4(static_cast<const byte*>(data));
return(TRUE);
}
@@ -3677,13 +3666,6 @@ fts_get_max_doc_id(
if (!page_is_empty(btr_pcur_get_page(&pcur))) {
const rec_t* rec = NULL;
- offset_t offsets_[REC_OFFS_NORMAL_SIZE];
- offset_t* offsets = offsets_;
- mem_heap_t* heap = NULL;
- ulint len;
- const void* data;
-
- rec_offs_init(offsets_);
do {
rec = btr_pcur_get_rec(&pcur);
@@ -3693,18 +3675,11 @@ fts_get_max_doc_id(
}
} while (btr_pcur_move_to_prev(&pcur, &mtr));
- if (!rec) {
+ if (!rec || rec_is_metadata(rec, *index)) {
goto func_exit;
}
- ut_ad(!rec_is_metadata(rec, index));
- offsets = rec_get_offsets(
- rec, index, offsets, true, ULINT_UNDEFINED, &heap);
-
- data = rec_get_nth_field(rec, offsets, 0, &len);
-
- doc_id = static_cast<doc_id_t>(fts_read_doc_id(
- static_cast<const byte*>(data)));
+ doc_id = fts_read_doc_id(rec);
}
func_exit:
@@ -5170,49 +5145,23 @@ fts_get_doc_id_from_row(
}
/** Extract the doc id from the record that belongs to index.
-@param[in] table table
-@param[in] rec record contains FTS_DOC_ID
+@param[in] rec record containing FTS_DOC_ID
@param[in] index index of rec
-@param[in] heap heap memory
+@param[in] offsets rec_get_offsets(rec,index)
@return doc id that was extracted from rec */
doc_id_t
fts_get_doc_id_from_rec(
- dict_table_t* table,
const rec_t* rec,
const dict_index_t* index,
- mem_heap_t* heap)
+ const offset_t* offsets)
{
- ulint len;
- const byte* data;
- ulint col_no;
- doc_id_t doc_id = 0;
- offset_t offsets_[REC_OFFS_NORMAL_SIZE];
- offset_t* offsets = offsets_;
- mem_heap_t* my_heap = heap;
-
- ut_a(table->fts->doc_col != ULINT_UNDEFINED);
-
- rec_offs_init(offsets_);
-
- offsets = rec_get_offsets(
- rec, index, offsets, true, ULINT_UNDEFINED, &my_heap);
-
- col_no = dict_col_get_index_pos(
- &table->cols[table->fts->doc_col], index);
-
- ut_ad(col_no != ULINT_UNDEFINED);
-
- data = rec_get_nth_field(rec, offsets, col_no, &len);
-
- ut_a(len == 8);
- ut_ad(8 == sizeof(doc_id));
- doc_id = static_cast<doc_id_t>(mach_read_from_8(data));
-
- if (my_heap && !heap) {
- mem_heap_free(my_heap);
- }
-
- return(doc_id);
+ ulint f = dict_col_get_index_pos(
+ &index->table->cols[index->table->fts->doc_col], index);
+ ulint len;
+ doc_id_t doc_id = mach_read_from_8(
+ rec_get_nth_field(rec, offsets, f, &len));
+ ut_ad(len == 8);
+ return doc_id;
}
/*********************************************************************//**
@@ -7355,7 +7304,7 @@ fts_init_recover_doc(
doc.text.f_str = btr_copy_externally_stored_field(
&doc.text.f_len,
static_cast<byte*>(dfield_get_data(dfield)),
- dict_table_page_size(table), len,
+ table->space->zip_size(), len,
static_cast<mem_heap_t*>(doc.self_heap->arg));
} else {
doc.text.f_str = static_cast<byte*>(
@@ -7409,7 +7358,7 @@ fts_init_index(
fts_cache_t* cache = table->fts->cache;
bool need_init = false;
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
/* First check cache->get_docs is initialized */
if (!has_cache_lock) {
@@ -7474,10 +7423,10 @@ func_exit:
}
if (need_init) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
/* Register the table with the optimize thread. */
fts_optimize_add_table(table);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
return(TRUE);
diff --git a/storage/innobase/fts/fts0opt.cc b/storage/innobase/fts/fts0opt.cc
index 33b4c5d1bb5..cd44ef7f67e 100644
--- a/storage/innobase/fts/fts0opt.cc
+++ b/storage/innobase/fts/fts0opt.cc
@@ -1000,9 +1000,9 @@ fts_table_fetch_doc_ids(
error = fts_eval_sql(trx, graph);
fts_sql_commit(trx);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
que_graph_free(graph);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (error == DB_SUCCESS) {
ib_vector_sort(doc_ids->doc_ids, fts_update_doc_id_cmp);
@@ -2941,8 +2941,8 @@ fts_optimize_init(void)
/* Add fts tables to fts_slots which could be skipped
during dict_load_table_one() because fts_optimize_thread
wasn't even started. */
- mutex_enter(&dict_sys->mutex);
- for (dict_table_t* table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
+ mutex_enter(&dict_sys.mutex);
+ for (dict_table_t* table = UT_LIST_GET_FIRST(dict_sys.table_LRU);
table != NULL;
table = UT_LIST_GET_NEXT(table_LRU, table)) {
if (!table->fts || !dict_table_has_fts_index(table)) {
@@ -2956,7 +2956,7 @@ fts_optimize_init(void)
fts_optimize_new_table(table);
table->fts->in_queue = true;
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
fts_opt_shutdown_event = os_event_create(0);
last_check_sync_time = time(NULL);
diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc
index 03b7fa9332b..829cfc72ec6 100644
--- a/storage/innobase/fts/fts0que.cc
+++ b/storage/innobase/fts/fts0que.cc
@@ -206,7 +206,7 @@ struct fts_phrase_t {
distance(0),
charset(NULL),
heap(NULL),
- page_size(dict_table_page_size(table)),
+ zip_size(table->space->zip_size()),
proximity_pos(NULL),
parser(NULL)
{
@@ -230,8 +230,8 @@ struct fts_phrase_t {
/** Heap for word processing */
mem_heap_t* heap;
- /** Row page size */
- const page_size_t page_size;
+ /** ROW_FORMAT=COMPRESSED page size, or 0 */
+ const ulint zip_size;
/** Position info for proximity search verification. Records the
min and max position of words matched */
@@ -2013,7 +2013,7 @@ fts_query_fetch_document(
if (dfield_is_ext(dfield)) {
data = btr_copy_externally_stored_field(
- &cur_len, data, phrase->page_size,
+ &cur_len, data, phrase->zip_size,
dfield_get_len(dfield), phrase->heap);
} else {
cur_len = dfield_get_len(dfield);
diff --git a/storage/innobase/fts/fts0sql.cc b/storage/innobase/fts/fts0sql.cc
index e3736f3277d..6873df102bf 100644
--- a/storage/innobase/fts/fts0sql.cc
+++ b/storage/innobase/fts/fts0sql.cc
@@ -91,14 +91,14 @@ fts_get_table_id(
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
-@param[in] dict_locked whether dict_sys->mutex is being held
+@param[in] dict_locked whether dict_sys.mutex is being held
@return the prefix, must be freed with ut_free() */
char* fts_get_table_name_prefix(const fts_table_t* fts_table)
{
char table_id[FTS_AUX_MIN_TABLE_ID_LENGTH];
const size_t table_id_len = size_t(fts_get_table_id(fts_table,
table_id)) + 1;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
/* Include the separator as well. */
const size_t dbname_len = fts_table->table->name.dblen() + 1;
ut_ad(dbname_len > 1);
@@ -106,7 +106,7 @@ char* fts_get_table_name_prefix(const fts_table_t* fts_table)
char* prefix_name = static_cast<char*>(
ut_malloc_nokey(prefix_name_len));
memcpy(prefix_name, fts_table->table->name.m_name, dbname_len);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
memcpy(prefix_name + dbname_len, "FTS_", 4);
memcpy(prefix_name + dbname_len + 4, table_id, table_id_len);
return prefix_name;
@@ -115,20 +115,20 @@ char* fts_get_table_name_prefix(const fts_table_t* fts_table)
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[out] table_name a name up to MAX_FULL_NAME_LEN
-@param[in] dict_locked whether dict_sys->mutex is being held */
+@param[in] dict_locked whether dict_sys.mutex is being held */
void fts_get_table_name(const fts_table_t* fts_table, char* table_name,
bool dict_locked)
{
if (!dict_locked) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* Include the separator as well. */
const size_t dbname_len = fts_table->table->name.dblen() + 1;
ut_ad(dbname_len > 1);
memcpy(table_name, fts_table->table->name.m_name, dbname_len);
if (!dict_locked) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
memcpy(table_name += dbname_len, "FTS_", 4);
table_name += 4;
@@ -157,17 +157,17 @@ fts_parse_sql(
&& fts_table->table->fts->dict_locked);
if (!dict_locked) {
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
/* The InnoDB SQL parser is not re-entrant. */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
graph = pars_sql(info, str);
ut_a(graph);
if (!dict_locked) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
ut_free(str);
@@ -187,7 +187,7 @@ fts_parse_sql_no_dict_lock(
char* str;
que_t* graph;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
str = ut_str3cat(fts_sql_begin, sql, fts_sql_end);
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc
index 203820037e1..e9a4c3b8636 100644
--- a/storage/innobase/fut/fut0lst.cc
+++ b/storage/innobase/fut/fut0lst.cc
@@ -58,8 +58,8 @@ flst_add_to_empty(
flst_write_addr(base + FLST_LAST, node_addr, mtr);
/* Set prev and next fields of node to add */
- flst_write_addr(node + FLST_PREV, fil_addr_null, mtr);
- flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr);
+ flst_zero_addr(node + FLST_PREV, mtr);
+ flst_zero_addr(node + FLST_NEXT, mtr);
/* Update len of base node */
mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr);
@@ -120,13 +120,11 @@ flst_add_last(
if (last_addr.page == node_addr.page) {
last_node = page_align(node) + last_addr.boffset;
} else {
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
- ut_ad(found);
-
- last_node = fut_get_ptr(space, page_size, last_addr,
+ last_node = fut_get_ptr(space, zip_size, last_addr,
RW_SX_LATCH, mtr);
}
@@ -170,13 +168,11 @@ flst_add_first(
if (first_addr.page == node_addr.page) {
first_node = page_align(node) + first_addr.boffset;
} else {
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
- first_node = fut_get_ptr(space, page_size, first_addr,
+ first_node = fut_get_ptr(space, zip_size, first_addr,
RW_SX_LATCH, mtr);
}
@@ -230,13 +226,11 @@ flst_insert_after(
if (!fil_addr_is_null(node3_addr)) {
/* Update prev field of node3 */
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
- node3 = fut_get_ptr(space, page_size,
+ node3 = fut_get_ptr(space, zip_size,
node3_addr, RW_SX_LATCH, mtr);
flst_write_addr(node3 + FLST_PREV, node2_addr, mtr);
} else {
@@ -294,14 +288,12 @@ flst_insert_before(
flst_write_addr(node2 + FLST_NEXT, node3_addr, mtr);
if (!fil_addr_is_null(node1_addr)) {
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(space, &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
/* Update next field of node1 */
- node1 = fut_get_ptr(space, page_size, node1_addr,
+ node1 = fut_get_ptr(space, zip_size, node1_addr,
RW_SX_LATCH, mtr);
flst_write_addr(node1 + FLST_NEXT, node2_addr, mtr);
} else {
@@ -344,11 +336,9 @@ flst_remove(
buf_ptr_get_fsp_addr(node2, &space, &node2_addr);
- bool found;
- const page_size_t& page_size = fil_space_get_page_size(space,
- &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
node1_addr = flst_get_prev_addr(node2, mtr);
node3_addr = flst_get_next_addr(node2, mtr);
@@ -361,7 +351,7 @@ flst_remove(
node1 = page_align(node2) + node1_addr.boffset;
} else {
- node1 = fut_get_ptr(space, page_size,
+ node1 = fut_get_ptr(space, zip_size,
node1_addr, RW_SX_LATCH, mtr);
}
@@ -380,7 +370,7 @@ flst_remove(
node3 = page_align(node2) + node3_addr.boffset;
} else {
- node3 = fut_get_ptr(space, page_size,
+ node3 = fut_get_ptr(space, zip_size,
node3_addr, RW_SX_LATCH, mtr);
}
@@ -431,11 +421,9 @@ flst_validate(
/* Find out the space id */
buf_ptr_get_fsp_addr(base, &space, &base_addr);
- bool found;
- const page_size_t& page_size = fil_space_get_page_size(space,
- &found);
-
- ut_ad(found);
+ fil_space_t* s = fil_space_acquire_silent(space);
+ ulint zip_size = s ? s->zip_size() : 0;
+ if (s) s->release();
len = flst_get_len(base);
node_addr = flst_get_first(base, mtr1);
@@ -443,7 +431,7 @@ flst_validate(
for (i = 0; i < len; i++) {
mtr_start(&mtr2);
- node = fut_get_ptr(space, page_size,
+ node = fut_get_ptr(space, zip_size,
node_addr, RW_SX_LATCH, &mtr2);
node_addr = flst_get_next_addr(node, &mtr2);
@@ -458,7 +446,7 @@ flst_validate(
for (i = 0; i < len; i++) {
mtr_start(&mtr2);
- node = fut_get_ptr(space, page_size,
+ node = fut_get_ptr(space, zip_size,
node_addr, RW_SX_LATCH, &mtr2);
node_addr = flst_get_prev_addr(node, &mtr2);
diff --git a/storage/innobase/gis/gis0rtree.cc b/storage/innobase/gis/gis0rtree.cc
index 5a80d394d77..ec6143d05d3 100644
--- a/storage/innobase/gis/gis0rtree.cc
+++ b/storage/innobase/gis/gis0rtree.cc
@@ -740,6 +740,8 @@ rtr_adjust_upper_level(
mem_heap_free(heap);
+ ut_ad(block->zip_size() == index->table->space->zip_size());
+
const uint32_t next_page_no = btr_page_get_next(page);
if (next_page_no != FIL_NULL) {
@@ -747,8 +749,8 @@ rtr_adjust_upper_level(
next_page_no);
buf_block_t* next_block = btr_block_get(
- next_page_id, dict_table_page_size(index->table),
- RW_X_LATCH, index, mtr);
+ next_page_id, block->zip_size(), RW_X_LATCH,
+ index, mtr);
#ifdef UNIV_BTR_DEBUG
ut_a(page_is_comp(next_block->frame) == page_is_comp(page));
ut_a(btr_page_get_prev(next_block->frame)
@@ -892,7 +894,7 @@ rtr_split_page_move_rec_list(
mtr_set_log_mode(mtr, log_mode);
if (!page_zip_compress(new_page_zip, new_page, index,
- page_zip_level, NULL, mtr)) {
+ page_zip_level, mtr)) {
ulint ret_pos;
/* Before trying to reorganize the page,
@@ -1847,7 +1849,7 @@ rtr_estimate_n_rows_in_range(
buf_block_t* block = btr_block_get(
page_id_t(index->table->space_id, index->page),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_S_LATCH, index, &mtr);
const page_t* page = buf_block_get_frame(block);
const unsigned n_recs = page_header_get_field(page, PAGE_N_RECS);
diff --git a/storage/innobase/gis/gis0sea.cc b/storage/innobase/gis/gis0sea.cc
index c73e7e6dde8..0f40d3aeb2a 100644
--- a/storage/innobase/gis/gis0sea.cc
+++ b/storage/innobase/gis/gis0sea.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2016, 2018, 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
@@ -145,7 +145,7 @@ rtr_pcur_getnext_from_path(
| MTR_MEMO_X_LOCK));
}
- const page_size_t page_size(index->table->space->flags);
+ const ulint zip_size = index->table->space->zip_size();
/* Pop each node/page to be searched from "path" structure
and do a search on it. Please note, any pages that are in
@@ -269,7 +269,7 @@ rtr_pcur_getnext_from_path(
block = buf_page_get_gen(
page_id_t(index->table->space_id,
- next_rec.page_no), page_size,
+ next_rec.page_no), zip_size,
rw_latch, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err);
if (block == NULL) {
@@ -424,7 +424,7 @@ rtr_pcur_getnext_from_path(
block,
page_id_t(index->table->space_id,
block->page.id.page_no()),
- page_size, BTR_MODIFY_TREE,
+ zip_size, BTR_MODIFY_TREE,
btr_cur, mtr);
}
@@ -972,7 +972,7 @@ rtr_create_rtr_info(
&rtr_info->rtr_path_mutex);
mutex_enter(&index->rtr_track->rtr_active_mutex);
- index->rtr_track->rtr_active->push_back(rtr_info);
+ index->rtr_track->rtr_active.push_front(rtr_info);
mutex_exit(&index->rtr_track->rtr_active_mutex);
return(rtr_info);
}
@@ -1045,7 +1045,7 @@ rtr_init_rtr_info(
rtr_info->index = index;
mutex_enter(&index->rtr_track->rtr_active_mutex);
- index->rtr_track->rtr_active->push_back(rtr_info);
+ index->rtr_track->rtr_active.push_front(rtr_info);
mutex_exit(&index->rtr_track->rtr_active_mutex);
}
@@ -1097,7 +1097,7 @@ rtr_clean_rtr_info(
}
if (index) {
- index->rtr_track->rtr_active->remove(rtr_info);
+ index->rtr_track->rtr_active.remove(rtr_info);
mutex_exit(&index->rtr_track->rtr_active_mutex);
}
@@ -1202,36 +1202,22 @@ rtr_check_discard_page(
the root page */
buf_block_t* block) /*!< in: block of page to be discarded */
{
- ulint pageno = block->page.id.page_no();
- rtr_info_t* rtr_info;
- rtr_info_active::iterator it;
+ const ulint pageno = block->page.id.page_no();
mutex_enter(&index->rtr_track->rtr_active_mutex);
- for (it = index->rtr_track->rtr_active->begin();
- it != index->rtr_track->rtr_active->end(); ++it) {
- rtr_info = *it;
- rtr_node_path_t::iterator rit;
- bool found = false;
-
+ for (const auto& rtr_info : index->rtr_track->rtr_active) {
if (cursor && rtr_info == cursor->rtr_info) {
continue;
}
mutex_enter(&rtr_info->rtr_path_mutex);
- for (rit = rtr_info->path->begin();
- rit != rtr_info->path->end(); ++rit) {
- node_visit_t node = *rit;
-
+ for (const node_visit_t& node : *rtr_info->path) {
if (node.page_no == pageno) {
- found = true;
+ rtr_rebuild_path(rtr_info, pageno);
break;
}
}
-
- if (found) {
- rtr_rebuild_path(rtr_info, pageno);
- }
mutex_exit(&rtr_info->rtr_path_mutex);
if (rtr_info->matches) {
@@ -1344,8 +1330,7 @@ rtr_cur_restore_position(
page_cur_t* page_cursor;
node_visit_t* node = rtr_get_parent_node(btr_cur, level, false);
node_seq_t path_ssn = node->seq_no;
- const page_size_t page_size(index->table->space->flags);
-
+ const ulint zip_size = index->table->space->zip_size();
ulint page_no = node->page_no;
heap = mem_heap_create(256);
@@ -1361,7 +1346,7 @@ search_again:
block = buf_page_get_gen(
page_id_t(index->table->space_id, page_no),
- page_size, RW_X_LATCH, NULL,
+ zip_size, RW_X_LATCH, NULL,
BUF_GET, __FILE__, __LINE__, mtr, &err);
ut_ad(block);
@@ -1561,14 +1546,13 @@ rtr_copy_buf(
matches->block.n_fields = block->n_fields;
matches->block.left_side = block->left_side;
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- matches->block.n_pointers = block->n_pointers;
+ matches->block.n_pointers = 0;
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
matches->block.curr_n_fields = block->curr_n_fields;
matches->block.curr_left_side = block->curr_left_side;
matches->block.index = block->index;
#endif /* BTR_CUR_HASH_ADAPT */
- ut_d(matches->block.debug_latch = block->debug_latch);
-
+ ut_d(matches->block.debug_latch = NULL);
}
/****************************************************************//**
diff --git a/storage/innobase/ha/ha0ha.cc b/storage/innobase/ha/ha0ha.cc
index f7e3c53495b..8e8a3369b7c 100644
--- a/storage/innobase/ha/ha0ha.cc
+++ b/storage/innobase/ha/ha0ha.cc
@@ -245,11 +245,8 @@ ha_insert_for_fold_func(
buf_block_t* prev_block = prev_node->block;
ut_a(prev_block->frame
== page_align(prev_node->data));
- ut_a(my_atomic_addlint(&prev_block->n_pointers,
- ulint(-1))
- < MAX_N_POINTERS);
- ut_a(my_atomic_addlint(&block->n_pointers, 1)
- < MAX_N_POINTERS);
+ ut_a(prev_block->n_pointers-- < MAX_N_POINTERS);
+ ut_a(block->n_pointers++ < MAX_N_POINTERS);
}
prev_node->block = block;
@@ -280,8 +277,7 @@ ha_insert_for_fold_func(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (table->adaptive) {
- ut_a(my_atomic_addlint(&block->n_pointers, 1)
- < MAX_N_POINTERS);
+ ut_a(block->n_pointers++ < MAX_N_POINTERS);
}
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -342,8 +338,7 @@ ha_delete_hash_node(
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (table->adaptive) {
ut_a(del_node->block->frame = page_align(del_node->data));
- ut_a(my_atomic_addlint(&del_node->block->n_pointers, ulint(-1))
- < MAX_N_POINTERS);
+ ut_a(del_node->block->n_pointers-- < MAX_N_POINTERS);
}
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@@ -385,11 +380,8 @@ ha_search_and_update_if_found_func(
if (node) {
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
if (table->adaptive) {
- ut_a(my_atomic_addlint(&node->block->n_pointers,
- ulint(-1))
- < MAX_N_POINTERS);
- ut_a(my_atomic_addlint(&new_block->n_pointers, 1)
- < MAX_N_POINTERS);
+ ut_a(node->block->n_pointers-- < MAX_N_POINTERS);
+ ut_a(new_block->n_pointers++ < MAX_N_POINTERS);
}
node->block = new_block;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 773026dbbd1..c8c9b92f727 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -54,6 +54,7 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include <my_bitmap.h>
#include <mysql/service_thd_alloc.h>
#include <mysql/service_thd_wait.h>
+#include "field.h"
// MYSQL_PLUGIN_IMPORT extern my_bool lower_case_file_system;
// MYSQL_PLUGIN_IMPORT extern char mysql_unpacked_real_data_home[];
@@ -97,7 +98,6 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include "row0mysql.h"
#include "row0quiesce.h"
#include "row0sel.h"
-#include "row0trunc.h"
#include "row0upd.h"
#include "fil0crypt.h"
#include "srv0mon.h"
@@ -133,6 +133,9 @@ void close_thread_tables(THD* thd);
#define tdc_size 400
#endif
+#include <mysql/plugin.h>
+#include <mysql/service_wsrep.h>
+
#include "ha_innodb.h"
#include "i_s.h"
#include "sync0sync.h"
@@ -140,28 +143,10 @@ void close_thread_tables(THD* thd);
#include <string>
#include <sstream>
-#include <mysql/plugin.h>
-#include <mysql/service_wsrep.h>
-
#ifdef WITH_WSREP
#include "dict0priv.h"
#include <mysql/service_md5.h>
#include "wsrep_sst.h"
-
-static inline wsrep_ws_handle_t*
-wsrep_ws_handle(THD* thd, const trx_t* trx) {
- return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd),
- (wsrep_trx_id_t)trx->id);
-}
-
-extern void wsrep_cleanup_transaction(THD *thd);
-static int
-wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
- my_bool signal);
-static void
-wsrep_fake_trx_id(handlerton* hton, THD *thd);
-static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
-static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
#endif /* WITH_WSREP */
/** to force correct commit order in binlog */
@@ -269,7 +254,7 @@ is_partition(
/** Signal to shut down InnoDB (NULL if shutdown was signaled, or if
running in innodb_read_only mode, srv_read_only_mode) */
-st_my_thread_var *srv_running;
+std::atomic <st_my_thread_var *> srv_running;
/** Service thread that waits for the server shutdown and stops purge threads.
Purge workers have THDs that are needed to calculate virtual columns.
This THDs must be destroyed rather early in the server shutdown sequence.
@@ -297,16 +282,12 @@ thd_destructor_proxy(void *)
mysql_mutex_lock(&thd_destructor_mutex);
- my_atomic_storeptr_explicit(reinterpret_cast<void**>(&srv_running),
- myvar,
- MY_MEMORY_ORDER_RELAXED);
+ srv_running.store(myvar, std::memory_order_relaxed);
/* wait until the server wakes the THD to abort and die */
- while (!srv_running->abort)
+ while (!myvar->abort)
mysql_cond_wait(&thd_destructor_cond, &thd_destructor_mutex);
mysql_mutex_unlock(&thd_destructor_mutex);
- my_atomic_storeptr_explicit(reinterpret_cast<void**>(&srv_running),
- NULL,
- MY_MEMORY_ORDER_RELAXED);
+ srv_running.store(NULL, std::memory_order_relaxed);
while (srv_fast_shutdown == 0 &&
(trx_sys.any_active_transactions() ||
@@ -378,6 +359,8 @@ const char* innodb_checksum_algorithm_names[] = {
"strict_innodb",
"none",
"strict_none",
+ "full_crc32",
+ "strict_full_crc32",
NullS
};
@@ -477,7 +460,8 @@ static TYPELIB innodb_change_buffering_typelib = {
/** Allowed values of innodb_instant_alter_column_allowed */
const char* innodb_instant_alter_column_allowed_names[] = {
"never", /* compatible with MariaDB 5.5 to 10.2 */
- "add_last",/* allow instant ADD COLUMN */
+ "add_last",/* allow instant ADD COLUMN ... LAST */
+ "add_drop_reorder", /* allow instant ADD anywhere & DROP & reorder */
NullS
};
@@ -1059,8 +1043,6 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_pages_created, SHOW_LONG},
{"pages_read",
(char*) &export_vars.innodb_pages_read, SHOW_LONG},
- {"pages0_read",
- (char*) &export_vars.innodb_page0_read, SHOW_LONG},
{"pages_written",
(char*) &export_vars.innodb_pages_written, SHOW_LONG},
{"row_lock_current_waits",
@@ -1874,8 +1856,13 @@ thd_to_trx_id(
{
return(thd_to_trx(thd)->id);
}
-#endif /* WITH_WSREP */
+static int
+wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
+ my_bool signal);
+static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid);
+static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid);
+#endif /* WITH_WSREP */
/********************************************************************//**
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used
@@ -2651,8 +2638,7 @@ ha_innobase::innobase_reset_autoinc(
if (error == DB_SUCCESS) {
dict_table_autoinc_initialize(m_prebuilt->table, autoinc);
-
- dict_table_autoinc_unlock(m_prebuilt->table);
+ mutex_exit(&m_prebuilt->table->autoinc_mutex);
}
return(error);
@@ -2937,8 +2923,9 @@ ha_innobase::ha_innobase(
| HA_CAN_EXPORT
| HA_CAN_RTREEKEYS
| HA_CAN_TABLES_WITHOUT_ROLLBACK
+ | HA_CAN_ONLINE_BACKUPS
| HA_CONCURRENT_OPTIMIZE
- | (srv_force_primary_key ? HA_WANTS_PRIMARY_KEY : 0)
+ | (srv_force_primary_key ? HA_REQUIRE_PRIMARY_KEY : 0)
),
m_start_of_scan(),
m_mysql_has_locked()
@@ -3473,6 +3460,10 @@ ha_innobase::reset_template(void)
in ha_innobase::write_row(). */
m_prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE;
}
+ if (m_prebuilt->pk_filter) {
+ m_prebuilt->pk_filter = NULL;
+ m_prebuilt->template_type = ROW_MYSQL_NO_TEMPLATE;
+ }
}
/*****************************************************************//**
@@ -3865,13 +3856,18 @@ static int innodb_init_params()
DBUG_RETURN(HA_ERR_INITIALIZATION);
}
- /* This is the first time univ_page_size is used.
- It was initialized to 16k pages before srv_page_size was set */
- univ_page_size.copy_from(
- page_size_t(srv_page_size, srv_page_size, false));
-
srv_sys_space.set_space_id(TRX_SYS_SPACE);
- srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE());
+
+ switch (srv_checksum_algorithm) {
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
+ srv_sys_space.set_flags(FSP_FLAGS_FCRC32_MASK_MARKER
+ | FSP_FLAGS_FCRC32_PAGE_SSIZE());
+ break;
+ default:
+ srv_sys_space.set_flags(FSP_FLAGS_PAGE_SSIZE());
+ }
+
srv_sys_space.set_name("innodb_system");
srv_sys_space.set_path(srv_data_home);
@@ -3884,7 +3880,10 @@ static int innodb_init_params()
srv_tmp_space.set_name("innodb_temporary");
srv_tmp_space.set_path(srv_data_home);
- srv_tmp_space.set_flags(FSP_FLAGS_PAGE_SSIZE());
+
+ /* Temporary tablespace is in full crc32 format. */
+ srv_tmp_space.set_flags(FSP_FLAGS_FCRC32_MASK_MARKER
+ | FSP_FLAGS_FCRC32_PAGE_SSIZE());
if (!srv_tmp_space.parse_params(innobase_temp_data_file_path, false)) {
ib::error() << "Unable to parse innodb_temp_data_file_path="
@@ -4173,13 +4172,12 @@ static int innodb_init(void* p)
innobase_hton->show_status = innobase_show_status;
innobase_hton->flags =
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS
- | HTON_NATIVE_SYS_VERSIONING;
+ | HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION;
#ifdef WITH_WSREP
innobase_hton->abort_transaction=wsrep_abort_transaction;
innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint;
innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint;
- innobase_hton->fake_trx_id=wsrep_fake_trx_id;
#endif /* WITH_WSREP */
innobase_hton->tablefile_extensions = ha_innobase_exts;
@@ -4271,9 +4269,7 @@ static int innodb_init(void* p)
mysql_thread_create(thd_destructor_thread_key,
&thd_destructor_thread,
NULL, thd_destructor_proxy, NULL);
- while (!my_atomic_loadptr_explicit(reinterpret_cast<void**>
- (&srv_running),
- MY_MEMORY_ORDER_RELAXED))
+ while (!srv_running.load(std::memory_order_relaxed))
os_thread_sleep(20);
}
@@ -4353,11 +4349,7 @@ innobase_end(handlerton*, ha_panic_function)
}
}
- st_my_thread_var* r = reinterpret_cast<st_my_thread_var*>(
- my_atomic_loadptr_explicit(
- reinterpret_cast<void**>(&srv_running),
- MY_MEMORY_ORDER_RELAXED));
- if (r) {
+ if (auto r = srv_running.load(std::memory_order_relaxed)) {
ut_ad(!srv_read_only_mode);
if (!abort_loop) {
// may be UNINSTALL PLUGIN statement
@@ -4520,6 +4512,14 @@ innobase_commit_ordered_2(
trx->flush_log_later = true;
}
+#ifdef WITH_WSREP
+ /* If the transaction is not run in 2pc, we must assign wsrep
+ XID here in order to get it written in rollback segment. */
+ if (wsrep_on(thd)) {
+ thd_get_xid(thd, (MYSQL_XID*)trx->xid);
+ }
+#endif /* WITH_WSREP */
+
innobase_commit_low(trx);
if (!read_only) {
@@ -4722,6 +4722,15 @@ innobase_rollback(
dberr_t error;
+#ifdef WITH_WSREP
+ /* If trx was assigned wsrep XID in prepare phase and the
+ trx is being rolled back due to BF abort, clear XID in order
+ to avoid writing it to rollback segment out of order. The XID
+ will be reassigned when the transaction is replayed. */
+ if (trx->state != TRX_STATE_NOT_STARTED && wsrep_is_wsrep_xid(trx->xid)) {
+ trx->xid->null();
+ }
+#endif /* WITH_WSREP */
if (rollback_trx
|| !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
@@ -5127,7 +5136,7 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
{
DBUG_ENTER("innobase_kill_query");
#ifdef WITH_WSREP
- if (wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) {
+ if (wsrep_on(thd) && wsrep_thd_is_aborting(thd)) {
/* if victim has been signaled by BF thread and/or aborting
is already progressing, following query aborting is not necessary
any more.
@@ -5230,17 +5239,6 @@ ha_innobase::index_type(
}
/****************************************************************//**
-Returns the table file name extension.
-@return file extension string */
-
-const char**
-ha_innobase::bas_ext() const
-/*========================*/
-{
- return(ha_innobase_exts);
-}
-
-/****************************************************************//**
Returns the operations supported for indexes.
@return flags of supported operations */
@@ -5255,24 +5253,21 @@ ha_innobase::index_flags(
return(0);
}
- ulong extra_flag= 0;
-
- if (table && key == table->s->primary_key) {
- extra_flag= HA_CLUSTERED_INDEX;
- }
-
- ulong flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
- | HA_READ_RANGE | HA_KEYREAD_ONLY
- | extra_flag
- | HA_DO_INDEX_COND_PUSHDOWN;
-
/* For spatial index, we don't support descending scan
and ICP so far. */
if (table_share->key_info[key].flags & HA_SPATIAL) {
- flags = HA_READ_NEXT | HA_READ_ORDER| HA_READ_RANGE
+ return HA_READ_NEXT | HA_READ_ORDER| HA_READ_RANGE
| HA_KEYREAD_ONLY | HA_KEY_SCAN_NOT_ROR;
}
+ ulong flags= key == table_share->primary_key
+ ? HA_CLUSTERED_INDEX : 0;
+
+ flags |= HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
+ | HA_READ_RANGE | HA_KEYREAD_ONLY
+ | HA_DO_INDEX_COND_PUSHDOWN
+ | HA_DO_RANGE_FILTER_PUSHDOWN;
+
return(flags);
}
@@ -5339,7 +5334,7 @@ ha_innobase::keys_to_use_for_scanning()
/****************************************************************//**
Ensures that if there's a concurrent inplace ADD INDEX, being-indexed virtual
columns are computed. They are not marked as indexed in the old table, so the
-server won't add them to the vcol_set automatically */
+server won't add them to the read_set automatically */
void
ha_innobase::column_bitmaps_signal()
/*================================*/
@@ -5359,7 +5354,7 @@ ha_innobase::column_bitmaps_signal()
if (col->ord_part ||
(dict_index_is_online_ddl(clust_index) &&
row_log_col_is_indexed(clust_index, num_v))) {
- table->mark_virtual_col(table->vfield[j]);
+ table->mark_virtual_column_with_deps(table->vfield[j]);
}
num_v++;
}
@@ -5798,12 +5793,12 @@ innobase_build_v_templ(
ut_ad(n_v_col > 0);
if (!locked) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
if (s_templ->vtempl) {
if (!locked) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
DBUG_VOID_RETURN;
}
@@ -5824,9 +5819,8 @@ innobase_build_v_templ(
const dict_v_col_t* vcol = dict_table_get_nth_v_col(
ib_table, i);
- for (ulint j = 0; j < vcol->num_base; j++) {
- ulint col_no = vcol->base_col[j]->ind;
- marker[col_no] = true;
+ for (ulint j = vcol->num_base; j--; ) {
+ marker[vcol->base_col[j]->ind] = true;
}
}
@@ -5834,9 +5828,8 @@ innobase_build_v_templ(
for (ulint i = 0; i < add_v->n_v_col; i++) {
const dict_v_col_t* vcol = &add_v->v_col[i];
- for (ulint j = 0; j < vcol->num_base; j++) {
- ulint col_no = vcol->base_col[j]->ind;
- marker[col_no] = true;
+ for (ulint j = vcol->num_base; j--; ) {
+ marker[vcol->base_col[j]->ind] = true;
}
}
}
@@ -5911,7 +5904,7 @@ innobase_build_v_templ(
}
if (!locked) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
s_templ->db_name = table->s->db.str;
@@ -6048,7 +6041,7 @@ initialize_auto_increment(dict_table_t* table, const Field* field)
const unsigned col_no = innodb_col_no(field);
- dict_table_autoinc_lock(table);
+ mutex_enter(&table->autoinc_mutex);
table->persistent_autoinc = 1
+ dict_table_get_nth_col_pos(table, col_no, NULL);
@@ -6056,7 +6049,7 @@ initialize_auto_increment(dict_table_t* table, const Field* field)
if (table->autoinc) {
/* Already initialized. Our caller checked
table->persistent_autoinc without
- dict_table_autoinc_lock(), and there might be multiple
+ autoinc_mutex protection, and there might be multiple
ha_innobase::open() executing concurrently. */
} else if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
/* If the recovery level is set so high that writes
@@ -6078,7 +6071,7 @@ initialize_auto_increment(dict_table_t* table, const Field* field)
innobase_get_int_col_max_value(field));
}
- dict_table_autoinc_unlock(table);
+ mutex_exit(&table->autoinc_mutex);
}
/** Open an InnoDB table
@@ -6088,6 +6081,14 @@ initialize_auto_increment(dict_table_t* table, const Field* field)
int
ha_innobase::open(const char* name, int, uint)
{
+ /* TODO: If trx_rollback_recovered(bool all=false) is ever
+ removed, the first-time open() must hold (or acquire and release)
+ a table lock that conflicts with trx_resurrect_table_locks(),
+ to ensure that any recovered incomplete ALTER TABLE will have been
+ rolled back. Otherwise, dict_table_t::instant could be cleared by
+ the rollback invoking dict_index_t::clear_instant_alter() while
+ open table handles exist in client connections. */
+
char norm_name[FN_REFLEN];
DBUG_ENTER("ha_innobase::open");
@@ -6209,7 +6210,7 @@ no_such_table:
key_used_on_scan = m_primary_key;
if (ib_table->n_v_cols) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
if (ib_table->vc_templ == NULL) {
ib_table->vc_templ = UT_NEW_NOKEY(dict_vcol_templ_t());
innobase_build_v_templ(
@@ -6217,7 +6218,7 @@ no_such_table:
true);
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
if (!check_index_consistency(table, ib_table)) {
@@ -7255,19 +7256,19 @@ static
const Field*
build_template_needs_field(
/*=======================*/
- ibool index_contains, /*!< in:
- dict_index_contains_col_or_prefix(
- index, i) */
- ibool read_just_key, /*!< in: TRUE when MySQL calls
+ bool index_contains, /*!< in:
+ dict_index_t::contains_col_or_prefix(
+ i) */
+ bool read_just_key, /*!< in: TRUE when MySQL calls
ha_innobase::extra with the
argument HA_EXTRA_KEYREAD; it is enough
to read just columns defined in
the index (i.e., no read of the
clustered index record necessary) */
- ibool fetch_all_in_key,
+ bool fetch_all_in_key,
/*!< in: true=fetch all fields in
the index */
- ibool fetch_primary_key_cols,
+ bool fetch_primary_key_cols,
/*!< in: true=fetch the
primary key columns */
dict_index_t* index, /*!< in: InnoDB index to use */
@@ -7329,11 +7330,11 @@ build_template_needs_field_in_icp(
bool is_virtual)
/*!< in: a virtual column or not */
{
- ut_ad(contains == dict_index_contains_col_or_prefix(index, i, is_virtual));
+ ut_ad(contains == index->contains_col_or_prefix(i, is_virtual));
return(index == prebuilt->index
? contains
- : dict_index_contains_col_or_prefix(prebuilt->index, i, is_virtual));
+ : prebuilt->index->contains_col_or_prefix(i, is_virtual));
}
/**************************************************************//**
@@ -7576,6 +7577,13 @@ ha_innobase::build_template(
/* Below we check column by column if we need to access
the clustered index. */
+ if (pushed_rowid_filter && rowid_filter_is_active) {
+ fetch_primary_key_cols = TRUE;
+ m_prebuilt->pk_filter = this;
+ } else {
+ m_prebuilt->pk_filter = NULL;
+ }
+
const bool skip_virtual = omits_virtual_cols(*table_share);
const ulint n_fields = table_share->fields;
@@ -7599,8 +7607,9 @@ ha_innobase::build_template(
ulint num_v = 0;
- if (active_index != MAX_KEY
- && active_index == pushed_idx_cond_keyno) {
+ if ((active_index != MAX_KEY
+ && active_index == pushed_idx_cond_keyno)
+ || (pushed_rowid_filter && rowid_filter_is_active)) {
/* Push down an index condition or an end_range check. */
for (ulint i = 0; i < n_fields; i++) {
const Field* field = table->field[i];
@@ -7609,9 +7618,8 @@ ha_innobase::build_template(
num_v++;
continue;
}
- ibool index_contains
- = dict_index_contains_col_or_prefix(
- index, is_v ? num_v : i - num_v, is_v);
+ bool index_contains = index->contains_col_or_prefix(
+ is_v ? num_v : i - num_v, is_v);
if (is_v && index_contains) {
m_prebuilt->n_template = 0;
num_v = 0;
@@ -7749,9 +7757,8 @@ ha_innobase::build_template(
continue;
}
- ibool index_contains
- = dict_index_contains_col_or_prefix(
- index, is_v ? num_v : i - num_v, is_v);
+ bool index_contains = index->contains_col_or_prefix(
+ is_v ? num_v : i - num_v, is_v);
if (!build_template_needs_field_in_icp(
index, m_prebuilt, index_contains,
@@ -7783,8 +7790,9 @@ ha_innobase::build_template(
}
}
}
-
- m_prebuilt->idx_cond = this;
+ if (active_index == pushed_idx_cond_keyno) {
+ m_prebuilt->idx_cond = this;
+ }
} else {
no_icp:
/* No index condition pushdown */
@@ -7808,8 +7816,8 @@ no_icp:
cluster index. */
if (is_v
&& m_prebuilt->read_just_key
- && !dict_index_contains_col_or_prefix(
- m_prebuilt->index, num_v, true))
+ && !m_prebuilt->index->contains_col_or_prefix(
+ num_v, true))
{
/* Turn off ROW_MYSQL_WHOLE_ROW */
m_prebuilt->template_type =
@@ -7818,21 +7826,15 @@ no_icp:
continue;
}
} else {
- ibool contain;
-
- if (!is_v) {
- contain = dict_index_contains_col_or_prefix(
- index, i - num_v,
- false);
- } else if (skip_virtual
- || dict_index_is_clust(index)) {
+ if (is_v
+ && (skip_virtual || index->is_primary())) {
num_v++;
continue;
- } else {
- contain = dict_index_contains_col_or_prefix(
- index, num_v, true);
}
+ bool contain = index->contains_col_or_prefix(
+ is_v ? num_v: i - num_v, is_v);
+
field = build_template_needs_field(
contain,
m_prebuilt->read_just_key,
@@ -7890,7 +7892,7 @@ ha_innobase::innobase_lock_autoinc(void)
switch (innobase_autoinc_lock_mode) {
case AUTOINC_NO_LOCKING:
/* Acquire only the AUTOINC mutex. */
- dict_table_autoinc_lock(m_prebuilt->table);
+ mutex_enter(&m_prebuilt->table->autoinc_mutex);
break;
case AUTOINC_NEW_STYLE_LOCKING:
@@ -7905,14 +7907,14 @@ ha_innobase::innobase_lock_autoinc(void)
) {
/* Acquire the AUTOINC mutex. */
- dict_table_autoinc_lock(m_prebuilt->table);
+ mutex_enter(&m_prebuilt->table->autoinc_mutex);
/* We need to check that another transaction isn't
already holding the AUTOINC lock on the table. */
if (m_prebuilt->table->n_waiting_or_granted_auto_inc_locks) {
/* Release the mutex to avoid deadlocks and
fall back to old style locking. */
- dict_table_autoinc_unlock(m_prebuilt->table);
+ mutex_exit(&m_prebuilt->table->autoinc_mutex);
} else {
/* Do not fall back to old style locking. */
break;
@@ -7928,7 +7930,7 @@ ha_innobase::innobase_lock_autoinc(void)
if (error == DB_SUCCESS) {
/* Acquire the AUTOINC mutex. */
- dict_table_autoinc_lock(m_prebuilt->table);
+ mutex_enter(&m_prebuilt->table->autoinc_mutex);
}
break;
@@ -7956,8 +7958,7 @@ ha_innobase::innobase_set_max_autoinc(
if (error == DB_SUCCESS) {
dict_table_autoinc_update_if_greater(m_prebuilt->table, auto_inc);
-
- dict_table_autoinc_unlock(m_prebuilt->table);
+ mutex_exit(&m_prebuilt->table->autoinc_mutex);
}
return(error);
@@ -7971,7 +7972,7 @@ handle.
int
ha_innobase::write_row(
/*===================*/
- uchar* record) /*!< in: a row in MySQL format */
+ const uchar* record) /*!< in: a row in MySQL format */
{
dberr_t error;
#ifdef WITH_WSREP
@@ -7996,16 +7997,6 @@ ha_innobase::write_row(
++trx->will_lock;
}
-#ifdef WITH_WSREP
- if (wsrep_is_load_multi_commit(m_user_thd))
- {
- /* Note that this transaction is still active. */
- trx_register_for_2pc(m_prebuilt->trx);
- /* We will need an IX lock on the destination table. */
- m_prebuilt->sql_stat_start = TRUE;
- }
-#endif /* WITH_WSREP */
-
ins_mode_t vers_set_fields;
/* Handling of Auto-Increment Columns. */
if (table->next_number_field && record == table->record[0]) {
@@ -8125,9 +8116,9 @@ ha_innobase::write_row(
wsrep_thd_query(m_user_thd) :
(char *)"void");
error= DB_SUCCESS;
- wsrep_thd_set_conflict_state(
- m_user_thd, MUST_ABORT);
- innobase_srv_conc_exit_innodb(m_prebuilt);
+ wsrep_thd_self_abort(m_user_thd);
+ innobase_srv_conc_exit_innodb(
+ m_prebuilt);
/* jump straight to func exit over
* later wsrep hooks */
goto func_exit;
@@ -8164,20 +8155,18 @@ set_max_autoinc:
properly assigned. Fetch values from
server side. */
if (wsrep_on(m_user_thd) &&
- wsrep_thd_exec_mode(m_user_thd) == REPL_RECV)
+ wsrep_thd_is_applying(m_user_thd))
{
wsrep_thd_auto_increment_variables(
m_user_thd, &offset, &increment);
}
else
- {
#endif /* WITH_WSREP */
+ {
ut_a(m_prebuilt->autoinc_increment > 0);
offset = m_prebuilt->autoinc_offset;
increment = m_prebuilt->autoinc_increment;
-#ifdef WITH_WSREP
}
-#endif /* WITH_WSREP */
auto_inc = innobase_next_autoinc(
auto_inc,
1, increment, offset,
@@ -8214,10 +8203,14 @@ report_error:
#ifdef WITH_WSREP
if (!error_result
&& wsrep_on(m_user_thd)
- && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE
+ && wsrep_thd_is_local(m_user_thd)
+ && !wsrep_thd_ignore_table(m_user_thd)
&& !wsrep_consistency_check(m_user_thd)
- && !wsrep_thd_ignore_table(m_user_thd)) {
- if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, record,
+ && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE)
+ && (thd_sql_command(m_user_thd) != SQLCOM_LOAD ||
+ thd_binlog_format(m_user_thd) == BINLOG_FORMAT_ROW)) {
+ if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE,
+ record,
NULL)) {
DBUG_PRINT("wsrep", ("row key failed"));
error_result = HA_ERR_INTERNAL_ERROR;
@@ -8876,19 +8869,13 @@ ha_innobase::update_row(
properly assigned. Fetch values from
server side. */
if (wsrep_on(m_user_thd) &&
- wsrep_thd_exec_mode(m_user_thd) == REPL_RECV)
- {
- wsrep_thd_auto_increment_variables(
- m_user_thd, &offset, &increment);
- }
+ wsrep_thd_is_applying(m_user_thd))
+ wsrep_thd_auto_increment_variables(
+ m_user_thd, &offset, &increment);
else
- {
-#endif /* WITH_WSREP */
- offset = m_prebuilt->autoinc_offset;
- increment = m_prebuilt->autoinc_increment;
-#ifdef WITH_WSREP
- }
#endif /* WITH_WSREP */
+ offset = m_prebuilt->autoinc_offset,
+ increment = m_prebuilt->autoinc_increment;
autoinc = innobase_next_autoinc(
autoinc, 1, increment, offset,
@@ -8926,14 +8913,18 @@ func_exit:
innobase_active_small();
#ifdef WITH_WSREP
- if (error == DB_SUCCESS &&
- wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE &&
- wsrep_on(m_user_thd) &&
- !wsrep_thd_ignore_table(m_user_thd)) {
+ if (error == DB_SUCCESS
+ && wsrep_on(m_user_thd)
+ && wsrep_thd_is_local(m_user_thd)
+ && !wsrep_thd_ignore_table(m_user_thd)) {
+
DBUG_PRINT("wsrep", ("update row key"));
- if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, old_row,
- new_row)) {
+ if (wsrep_append_keys(m_user_thd,
+ wsrep_protocol_version >= 4
+ ? WSREP_SERVICE_KEY_UPDATE
+ : WSREP_SERVICE_KEY_EXCLUSIVE,
+ old_row, new_row)){
WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED");
DBUG_PRINT("wsrep", ("row key failed"));
err = HA_ERR_INTERNAL_ERROR;
@@ -8994,11 +8985,13 @@ ha_innobase::delete_row(
#ifdef WITH_WSREP
if (error == DB_SUCCESS
- && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE
&& wsrep_on(m_user_thd)
+ && wsrep_thd_is_local(m_user_thd)
&& !wsrep_thd_ignore_table(m_user_thd)) {
- if (wsrep_append_keys(m_user_thd, WSREP_KEY_EXCLUSIVE, record,
- NULL)) {
+
+ if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE,
+ record,
+ NULL)) {
DBUG_PRINT("wsrep", ("delete fail"));
error = (dberr_t) HA_ERR_INTERNAL_ERROR;
goto wsrep_error;
@@ -9521,21 +9514,21 @@ ha_innobase::change_active_index(
}
}
} else {
- dtuple_set_n_fields(m_prebuilt->search_tuple,
- m_prebuilt->index->n_fields);
+ ulint n_fields = dict_index_get_n_unique_in_tree(
+ m_prebuilt->index);
+
+ dtuple_set_n_fields(m_prebuilt->search_tuple, n_fields);
dict_index_copy_types(
m_prebuilt->search_tuple, m_prebuilt->index,
- m_prebuilt->index->n_fields);
+ n_fields);
/* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is
always added to read_set. */
m_prebuilt->fts_doc_id_in_read_set = m_prebuilt->in_fts_query
&& m_prebuilt->read_just_key
- && dict_index_contains_col_or_prefix(
- m_prebuilt->index,
- m_prebuilt->table->fts->doc_col,
- false);
+ && m_prebuilt->index->contains_col_or_prefix(
+ m_prebuilt->table->fts->doc_col, false);
}
/* MySQL changes the active index for a handle also during some
@@ -10169,20 +10162,22 @@ next_record:
#ifdef WITH_WSREP
inline
const char*
-wsrep_key_type_to_str(wsrep_key_type type)
+wsrep_key_type_to_str(Wsrep_service_key_type type)
{
switch (type) {
- case WSREP_KEY_SHARED:
+ case WSREP_SERVICE_KEY_SHARED:
return "shared";
- case WSREP_KEY_SEMI:
- return "semi";
- case WSREP_KEY_EXCLUSIVE:
+ case WSREP_SERVICE_KEY_REFERENCE:
+ return "reference";
+ case WSREP_SERVICE_KEY_UPDATE:
+ return "update";
+ case WSREP_SERVICE_KEY_EXCLUSIVE:
return "exclusive";
};
return "unknown";
}
-ulint
+extern dberr_t
wsrep_append_foreign_key(
/*===========================*/
trx_t* trx, /*!< in: trx */
@@ -10190,18 +10185,17 @@ wsrep_append_foreign_key(
const rec_t* rec, /*!<in: clustered index record */
dict_index_t* index, /*!<in: clustered index */
ibool referenced, /*!<in: is check for referenced table */
- wsrep_key_type key_type) /*!< in: access type of this key
- (shared, exclusive, semi...) */
+ Wsrep_service_key_type key_type) /*!< in: access type of this key
+ (shared, exclusive, reference...) */
{
ut_a(trx);
THD* thd = (THD*)trx->mysql_thd;
ulint rcode = DB_SUCCESS;
char cache_key[513] = {'\0'};
int cache_key_len=0;
- bool const copy = true;
if (!wsrep_on(trx->mysql_thd) ||
- wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
+ wsrep_thd_is_local(trx->mysql_thd) == false) {
return DB_SUCCESS;
}
@@ -10221,7 +10215,7 @@ wsrep_append_foreign_key(
foreign->referenced_table : foreign->foreign_table)) {
WSREP_DEBUG("pulling %s table into cache",
(referenced) ? "referenced" : "foreign");
- mutex_enter(&(dict_sys->mutex));
+ mutex_enter(&dict_sys.mutex);
if (referenced) {
foreign->referenced_table =
@@ -10251,7 +10245,7 @@ wsrep_append_foreign_key(
TRUE, FALSE);
}
}
- mutex_exit(&(dict_sys->mutex));
+ mutex_exit(&dict_sys.mutex);
}
if ( !((referenced) ?
@@ -10291,11 +10285,11 @@ wsrep_append_foreign_key(
if (rcode != DB_SUCCESS) {
WSREP_ERROR(
"FK key set failed: " ULINTPF
- " (" ULINTPF " %s), index: %s %s, %s",
+ " (" ULINTPF "%s), index: %s %s, %s",
rcode, referenced, wsrep_key_type_to_str(key_type),
- index ? index->name() : "void index",
+ (index) ? index->name() : "void index",
(index && index->table) ? index->table->name.m_name :
- "void table",
+ "void table",
wsrep_thd_query(thd));
return DB_ERROR;
}
@@ -10311,7 +10305,7 @@ wsrep_append_foreign_key(
#ifdef WSREP_DEBUG_PRINT
ulint j;
fprintf(stderr, "FK parent key, table: %s %s len: %lu ",
- cache_key, (shared) ? "shared" : "exclusive", len+1);
+ cache_key, wsrep_key_type_to_str(key_type), len+1);
for (j=0; j<len+1; j++) {
fprintf(stderr, " %hhX, ", key[j]);
}
@@ -10330,7 +10324,8 @@ wsrep_append_foreign_key(
wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
- if (!wsrep_prepare_key(
+ if (!wsrep_prepare_key_for_innodb(
+ thd,
(const uchar*)cache_key,
cache_key_len + 1,
(const uchar*)key, len+1,
@@ -10341,17 +10336,7 @@ wsrep_append_foreign_key(
wsrep_thd_query(thd) : "void");
return DB_ERROR;
}
-
- wsrep_t *wsrep= get_wsrep();
-
- rcode = (int)wsrep->append_key(
- wsrep,
- wsrep_ws_handle(thd, trx),
- &wkey,
- 1,
- key_type,
- copy);
-
+ rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: " ULINTPF, rcode));
WSREP_ERROR("Appending cascaded fk row key failed: %s, "
@@ -10372,17 +10357,19 @@ wsrep_append_key(
TABLE_SHARE *table_share,
const char* key,
uint16_t key_len,
- wsrep_key_type key_type /*!< in: access type of this key
+ Wsrep_service_key_type key_type /*!< in: access type of this key
(shared, exclusive, semi...) */
)
{
DBUG_ENTER("wsrep_append_key");
- bool const copy = true;
+ DBUG_PRINT("enter",
+ ("thd: %lu trx: %lld", thd_get_thread_id(thd),
+ (long long)trx->id));
#ifdef WSREP_DEBUG_PRINT
- fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ",
+ fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", keylen %d, key %s.%s\n",
wsrep_key_type_to_str(key_type),
- wsrep_thd_thread_id(thd), trx->id, key_len,
- table_share->table_name.str, wsrep_thd_query(thd));
+ thd_get_thread_id(thd), trx->id, key_len,
+ table_share->table_name.str, key);
for (int i=0; i<key_len; i++) {
fprintf(stderr, "%hhX, ", key[i]);
}
@@ -10391,7 +10378,8 @@ wsrep_append_key(
wsrep_buf_t wkey_part[3];
wsrep_key_t wkey = {wkey_part, 3};
- if (!wsrep_prepare_key(
+ if (!wsrep_prepare_key_for_innodb(
+ thd,
(const uchar*)table_share->table_cache_key.str,
table_share->table_cache_key.length,
(const uchar*)key, key_len,
@@ -10403,15 +10391,7 @@ wsrep_append_key(
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
}
- wsrep_t *wsrep= get_wsrep();
-
- int rcode = (int)wsrep->append_key(
- wsrep,
- wsrep_ws_handle(thd, trx),
- &wkey,
- 1,
- key_type,
- copy);
+ int rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type);
if (rcode) {
DBUG_PRINT("wsrep", ("row key failed: %d", rcode));
WSREP_WARN("Appending row key failed: %s, %d",
@@ -10452,17 +10432,30 @@ int
ha_innobase::wsrep_append_keys(
/*===========================*/
THD *thd,
- wsrep_key_type key_type, /*!< in: access type of this key
- (shared, exclusive, semi...) */
+ Wsrep_service_key_type key_type, /*!< in: access type of this row
+ operation:
+ (shared, exclusive, reference...) */
const uchar* record0, /* in: row in MySQL format */
const uchar* record1) /* in: row in MySQL format */
{
+ /* Sanity check: newly inserted records should always be passed with
+ EXCLUSIVE key type, all the rest are expected to carry a pre-image
+ */
+ ut_a(record1 != NULL || key_type == WSREP_SERVICE_KEY_EXCLUSIVE);
+
int rcode;
DBUG_ENTER("wsrep_append_keys");
bool key_appended = false;
trx_t *trx = thd_to_trx(thd);
+#ifdef WSREP_DEBUG_PRINT
+ fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", table %s\nSQL: %s\n",
+ wsrep_key_type_to_str(key_type),
+ thd_get_thread_id(thd), trx->id,
+ table_share->table_name.str, wsrep_thd_query(thd));
+#endif
+
if (table_share && table_share->tmp_table != NO_TMP_TABLE) {
WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s",
thd_get_thread_id(thd),
@@ -10487,7 +10480,9 @@ ha_innobase::wsrep_append_keys(
thd, trx, table_share, keyval,
len, key_type);
- if (rcode) DBUG_RETURN(rcode);
+ if (rcode) {
+ DBUG_RETURN(rcode);
+ }
} else {
WSREP_DEBUG("NULL key skipped (proto 0): %s",
wsrep_thd_query(thd));
@@ -10501,68 +10496,91 @@ ha_innobase::wsrep_append_keys(
KEY* key_info = table->key_info + i;
if (key_info->flags & HA_NOSAME) {
hasPK = true;
+ break;
}
}
for (i=0; i<table->s->keys; ++i) {
- uint len;
- char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
- char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
- char* key0 = &keyval0[1];
- char* key1 = &keyval1[1];
KEY* key_info = table->key_info + i;
- ibool is_null;
dict_index_t* idx = innobase_get_index(i);
dict_table_t* tab = (idx) ? idx->table : NULL;
+ /* keyval[] shall contain an ordinal number at byte 0
+ and the actual key data shall be written at byte 1.
+ Hence the total data length is the key length + 1 */
+ char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
+ char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'};
keyval0[0] = (char)i;
keyval1[0] = (char)i;
+ char* key0 = &keyval0[1];
+ char* key1 = &keyval1[1];
if (!tab) {
WSREP_WARN("MariaDB-InnoDB key mismatch %s %s",
table->s->table_name.str,
key_info->name.str);
}
- /* !hasPK == table with no PK, must append all non-unique keys */
+ /* !hasPK == table with no PK,
+ must append all non-unique keys */
if (!hasPK || key_info->flags & HA_NOSAME ||
((tab &&
referenced_by_foreign_key2(tab, idx)) ||
(!tab && referenced_by_foreign_key()))) {
- len = wsrep_store_key_val_for_row(
+ ibool is_null0;
+ uint len0 = wsrep_store_key_val_for_row(
thd, table, i, key0,
WSREP_MAX_SUPPORTED_KEY_LENGTH,
- record0, &is_null);
- if (!is_null) {
- rcode = wsrep_append_key(
- thd, trx, table_share,
- keyval0, len+1, key_type);
- if (rcode) DBUG_RETURN(rcode);
-
- if (key_info->flags & HA_NOSAME ||
- key_type == WSREP_KEY_SHARED)
- key_appended = true;
- } else {
- WSREP_DEBUG("NULL key skipped: %s",
- wsrep_thd_query(thd));
- }
+ record0, &is_null0);
if (record1) {
- len = wsrep_store_key_val_for_row(
+ ibool is_null1;
+ uint len1 = wsrep_store_key_val_for_row(
thd, table, i, key1,
WSREP_MAX_SUPPORTED_KEY_LENGTH,
- record1, &is_null);
+ record1, &is_null1);
+
+ if (is_null0 != is_null1 ||
+ len0 != len1 ||
+ memcmp(key0, key1, len0)) {
+ /* This key has chaged. If it
+ is unique, this is an exclusive
+ operation -> upgrade key type */
+ if (key_info->flags & HA_NOSAME) {
+ key_type = WSREP_SERVICE_KEY_EXCLUSIVE;
+ }
- if (!is_null
- && memcmp(key0, key1, len)) {
- rcode = wsrep_append_key(
+ if (!is_null1) {
+ rcode = wsrep_append_key(
thd, trx, table_share,
- keyval1, len+1,
- key_type);
- if (rcode) DBUG_RETURN(rcode);
+ keyval1,
+ /* for len1+1 see keyval1
+ initialization comment */
+ len1+1, key_type);
+ if (rcode)
+ DBUG_RETURN(rcode);
+ }
}
}
+
+ if (!is_null0) {
+ rcode = wsrep_append_key(
+ thd, trx, table_share,
+ /* for len0+1 see keyval0
+ initialization comment */
+ keyval0, len0+1, key_type);
+ if (rcode)
+ DBUG_RETURN(rcode);
+
+ if (key_info->flags & HA_NOSAME ||
+ key_type == WSREP_SERVICE_KEY_SHARED||
+ key_type == WSREP_SERVICE_KEY_REFERENCE)
+ key_appended = true;
+ } else {
+ WSREP_DEBUG("NULL key skipped: %s",
+ wsrep_thd_query(thd));
+ }
}
}
}
@@ -10716,9 +10734,8 @@ prepare_vcol_for_base_setup(
ut_ad(col->base_col == NULL);
MY_BITMAP *old_read_set = field->table->read_set;
- MY_BITMAP *old_vcol_set = field->table->vcol_set;
- field->table->read_set = field->table->vcol_set = &field->table->tmp_set;
+ field->table->read_set = &field->table->tmp_set;
bitmap_clear_all(&field->table->tmp_set);
field->vcol_info->expr->walk(
@@ -10730,7 +10747,6 @@ prepare_vcol_for_base_setup(
* col->base_col)));
}
field->table->read_set= old_read_set;
- field->table->vcol_set= old_vcol_set;
}
@@ -10917,10 +10933,10 @@ create_table_info_t::create_table_def()
ulint vers_row = 0;
if (m_form->versioned()) {
- if (i == m_form->s->row_start_field) {
+ if (i == m_form->s->vers.start_fieldno) {
vers_row = DATA_VERS_START;
ut_d(have_vers_start = true);
- } else if (i == m_form->s->row_end_field) {
+ } else if (i == m_form->s->vers.end_fieldno) {
vers_row = DATA_VERS_END;
ut_d(have_vers_end = true);
} else if (!(field->flags
@@ -11066,7 +11082,7 @@ err_col:
}
/** Fill base columns for the stored column present in the list. */
- if (table->s_cols && table->s_cols->size()) {
+ if (table->s_cols && !table->s_cols->empty()) {
for (ulint i = 0; i < n_cols; i++) {
Field* field = m_form->field[i];
@@ -11107,9 +11123,8 @@ err_col:
"temporary table creation.");
}
- /* Get a new table ID. FIXME: Make this a private
- sequence, not shared with persistent tables! */
- dict_table_assign_new_id(table, m_trx);
+ m_trx->table_id = table->id
+ = dict_sys.get_temporary_table_id();
ut_ad(dict_tf_get_rec_format(table->flags)
!= REC_FORMAT_COMPRESSED);
table->space_id = SRV_TMP_SPACE_ID;
@@ -11361,7 +11376,7 @@ create_table_info_t::create_option_data_directory_is_valid()
}
/* Do not use DATA DIRECTORY with TEMPORARY TABLE. */
- if (m_create_info->options & HA_LEX_CREATE_TMP_TABLE) {
+ if (m_create_info->tmp_table()) {
push_warning(
m_thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
@@ -11390,8 +11405,7 @@ create_table_info_t::create_options_are_invalid()
const char* ret = NULL;
enum row_type row_format = m_create_info->row_type;
- const bool is_temp
- = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
+ const bool is_temp = m_create_info->tmp_table();
ut_ad(m_thd != NULL);
@@ -11577,9 +11591,12 @@ create_table_info_t::check_table_options()
return "ENCRYPTION_KEY_ID";
}
- /* Currently we do not support encryption for spatial indexes.
+ /* We do not support encryption for spatial indexes,
+ except if innodb_checksum_algorithm=full_crc32.
Do not allow ENCRYPTED=YES if any SPATIAL INDEX exists. */
- if (options->encryption != FIL_ENCRYPTION_ON) {
+ if (options->encryption != FIL_ENCRYPTION_ON
+ || srv_checksum_algorithm
+ >= SRV_CHECKSUM_ALGORITHM_FULL_CRC32) {
break;
}
for (ulint i = 0; i < m_form->s->keys; i++) {
@@ -11746,7 +11763,7 @@ create_table_info_t::parse_table_name(
if (m_innodb_file_per_table
&& !mysqld_embedded
- && !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
+ && !m_create_info->tmp_table()) {
if ((name[1] == ':')
|| (name[0] == '\\' && name[1] == '\\')) {
@@ -11781,13 +11798,19 @@ create_table_info_t::parse_table_name(
}
if (m_create_info->index_file_name) {
- my_error(WARN_OPTION_IGNORED, ME_JUST_WARNING,
+ my_error(WARN_OPTION_IGNORED, ME_WARNING,
"INDEX DIRECTORY");
}
DBUG_RETURN(0);
}
+/** @return whether innodb_strict_mode is active */
+bool ha_innobase::is_innodb_strict_mode(THD *thd)
+{
+ return THDVAR(thd, strict_mode);
+}
+
/** Determine InnoDB table flags.
If strict_mode=OFF, this will adjust the flags to what should be assumed.
@retval true on success
@@ -11801,10 +11824,8 @@ bool create_table_info_t::innobase_table_flags()
enum row_type row_type;
rec_format_t innodb_row_format =
get_row_format(m_default_row_format);
- const bool is_temp
- = m_create_info->options & HA_LEX_CREATE_TMP_TABLE;
- bool zip_allowed
- = !is_temp;
+ const bool is_temp = m_create_info->tmp_table();
+ bool zip_allowed = !is_temp;
const ulint zip_ssize_max =
ut_min(static_cast<ulint>(UNIV_PAGE_SSIZE_MAX),
@@ -12204,9 +12225,8 @@ create_table_info_t::set_tablespace_type(
/* Ignore the current innodb-file-per-table setting if we are
creating a temporary table. */
- m_use_file_per_table =
- m_allow_file_per_table
- && !(m_create_info->options & HA_LEX_CREATE_TMP_TABLE);
+ m_use_file_per_table = m_allow_file_per_table
+ && !m_create_info->tmp_table();
/* DATA DIRECTORY must have m_use_file_per_table but cannot be
used with TEMPORARY tables. */
@@ -12533,13 +12553,12 @@ dict_index_t::record_size_info_t dict_index_t::record_size_info() const
/* maximum allowed size of a node pointer record */
ulint page_ptr_max;
- const bool comp= dict_table_is_comp(table);
+ const bool comp= table->not_redundant();
/* table->space == NULL after DISCARD TABLESPACE */
- const page_size_t page_size(dict_tf_get_page_size(table->flags));
+ const ulint zip_size= dict_tf_get_zip_size(table->flags);
record_size_info_t result;
- if (page_size.is_compressed() &&
- page_size.physical() < univ_page_size.physical())
+ if (zip_size && zip_size < srv_page_size)
{
/* On a ROW_FORMAT=COMPRESSED page, two records must fit in the
uncompressed page modification log. On compressed pages
@@ -12550,7 +12569,7 @@ dict_index_t::record_size_info_t dict_index_t::record_size_info() const
an empty page, minus a byte for recoding the heap
number in the page modification log. The maximum
allowed node pointer size is half that. */
- result.max_leaf_size= page_zip_empty_size(n_fields, page_size.physical());
+ result.max_leaf_size= page_zip_empty_size(n_fields, zip_size);
if (result.max_leaf_size)
{
result.max_leaf_size--;
@@ -12721,11 +12740,15 @@ bool create_table_info_t::row_size_is_acceptable(
const size_t idx= info.get_first_overrun_field_index();
const dict_field_t *field= dict_index_get_nth_field(&index, idx);
+ ut_ad((!field->name) == field->col->is_dropped());
if (innodb_strict_mode || global_system_variables.log_warnings > 2)
{
- ib::error_or_warn(strict && innodb_strict_mode)
- << "Cannot add field " << field->name << " in table "
- << index.table->name << " because after adding it, the row size is "
+ ib::error_or_warn eow(strict && innodb_strict_mode);
+ if (field->name)
+ eow << "Cannot add field " << field->name << " in table ";
+ else
+ eow << "Cannot add an instantly dropped column in table ";
+ eow << index.table->name << " because after adding it, the row size is "
<< info.get_overrun_size()
<< " which is greater than maximum allowed size ("
<< info.max_leaf_size << " bytes) for a record on index leaf page.";
@@ -12783,9 +12806,9 @@ create_table_info_t::create_table_update_dict()
DBUG_RETURN(-1);
}
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
fts_optimize_add_table(innobase_table);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
if (const Field* ai = m_form->found_next_number_field) {
@@ -12797,7 +12820,7 @@ create_table_info_t::create_table_update_dict()
autoinc = 1;
}
- dict_table_autoinc_lock(innobase_table);
+ mutex_enter(&innobase_table->autoinc_mutex);
dict_table_autoinc_initialize(innobase_table, autoinc);
if (innobase_table->is_temporary()) {
@@ -12822,7 +12845,7 @@ create_table_info_t::create_table_update_dict()
}
}
- dict_table_autoinc_unlock(innobase_table);
+ mutex_exit(&innobase_table->autoinc_mutex);
}
innobase_parse_hint_from_comment(m_thd, innobase_table, m_form->s);
@@ -13054,12 +13077,12 @@ ha_innobase::discard_or_import_tablespace(
btr_cur_instant_init(). */
table_id_t id = m_prebuilt->table->id;
ut_ad(id);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
dict_table_close(m_prebuilt->table, TRUE, FALSE);
- dict_table_remove_from_cache(m_prebuilt->table);
+ dict_sys.remove(m_prebuilt->table);
m_prebuilt->table = dict_table_open_on_id(id, TRUE,
DICT_TABLE_OP_NORMAL);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!m_prebuilt->table) {
err = DB_TABLE_NOT_FOUND;
} else {
@@ -14112,7 +14135,7 @@ fsp_get_available_space_in_free_extents(const fil_space_t& space)
ulint n_free_up =
(size_in_header - space.free_limit) / FSP_EXTENT_SIZE;
- const ulint size = page_size_t(space.flags).physical();
+ const ulint size = space.physical_size();
if (n_free_up > 0) {
n_free_up--;
n_free_up -= n_free_up / (size / FSP_EXTENT_SIZE);
@@ -14189,7 +14212,7 @@ ha_innobase::info_low(
opt = DICT_STATS_RECALC_TRANSIENT;
}
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
ret = dict_stats_update(ib_table, opt);
if (ret != DB_SUCCESS) {
@@ -14211,7 +14234,7 @@ ha_innobase::info_low(
ulint stat_sum_of_other_index_sizes;
if (!(flag & HA_STATUS_NO_LOCK)) {
- dict_table_stats_lock(ib_table, RW_S_LATCH);
+ rw_lock_s_lock(&ib_table->stats_latch);
}
ut_a(ib_table->stat_initialized);
@@ -14225,7 +14248,7 @@ ha_innobase::info_low(
= ib_table->stat_sum_of_other_index_sizes;
if (!(flag & HA_STATUS_NO_LOCK)) {
- dict_table_stats_unlock(ib_table, RW_S_LATCH);
+ rw_lock_s_unlock(&ib_table->stats_latch);
}
/*
@@ -14262,8 +14285,7 @@ ha_innobase::info_low(
stats.records = (ha_rows) n_rows;
stats.deleted = 0;
if (fil_space_t* space = ib_table->space) {
- const ulint size = page_size_t(space->flags)
- .physical();
+ const ulint size = space->physical_size();
stats.data_file_length
= ulonglong(stat_clustered_index_size)
* size;
@@ -14330,7 +14352,7 @@ ha_innobase::info_low(
}
if (!(flag & HA_STATUS_NO_LOCK)) {
- dict_table_stats_lock(ib_table, RW_S_LATCH);
+ rw_lock_s_lock(&ib_table->stats_latch);
}
ut_a(ib_table->stat_initialized);
@@ -14412,7 +14434,7 @@ ha_innobase::info_low(
}
if (!(flag & HA_STATUS_NO_LOCK)) {
- dict_table_stats_unlock(ib_table, RW_S_LATCH);
+ rw_lock_s_unlock(&ib_table->stats_latch);
}
snprintf(path, sizeof(path), "%s/%s%s",
@@ -14766,20 +14788,9 @@ ha_innobase::check(
if (!(check_opt->flags & T_QUICK)
&& !index->is_corrupted()) {
- /* Enlarge the fatal lock wait timeout during
- CHECK TABLE. */
- my_atomic_addlong(
- &srv_fatal_semaphore_wait_threshold,
- SRV_SEMAPHORE_WAIT_EXTENSION);
dberr_t err = btr_validate_index(
- index, m_prebuilt->trx, false);
-
- /* Restore the fatal lock wait timeout after
- CHECK TABLE. */
- my_atomic_addlong(
- &srv_fatal_semaphore_wait_threshold,
- -SRV_SEMAPHORE_WAIT_EXTENSION);
+ index, m_prebuilt->trx);
if (err != DB_SUCCESS) {
is_ok = false;
@@ -15134,7 +15145,7 @@ get_foreign_key_info(
dict_table_t* ref_table;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ref_table = dict_table_open_on_name(
foreign->referenced_table_name_lookup,
TRUE, FALSE, DICT_ERR_IGNORE_NONE);
@@ -15189,7 +15200,7 @@ ha_innobase::get_foreign_key_list(
m_prebuilt->trx->op_info = "getting list of foreign keys";
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
for (dict_foreign_set::iterator it
= m_prebuilt->table->foreign_set.begin();
@@ -15206,7 +15217,7 @@ ha_innobase::get_foreign_key_list(
}
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
m_prebuilt->trx->op_info = "";
@@ -15227,7 +15238,7 @@ ha_innobase::get_parent_foreign_key_list(
m_prebuilt->trx->op_info = "getting list of referencing foreign keys";
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
for (dict_foreign_set::iterator it
= m_prebuilt->table->referenced_set.begin();
@@ -15244,7 +15255,7 @@ ha_innobase::get_parent_foreign_key_list(
}
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
m_prebuilt->trx->op_info = "";
@@ -15279,143 +15290,6 @@ struct tablename_compare {
}
};
-/** Get the table name and database name for the given table.
-@param[in,out] thd user thread handle
-@param[out] f_key_info pointer to table_name_info object
-@param[in] foreign foreign key constraint. */
-static
-void
-get_table_name_info(
- THD* thd,
- st_handler_tablename* f_key_info,
- const dict_foreign_t* foreign)
-{
-#define FILENAME_CHARSET_MBMAXLEN 5
- char tmp_buff[NAME_CHAR_LEN * FILENAME_CHARSET_MBMAXLEN + 1];
- char name_buff[NAME_CHAR_LEN * FILENAME_CHARSET_MBMAXLEN + 1];
- const char* ptr;
-
- size_t len = dict_get_db_name_len(
- foreign->referenced_table_name_lookup);
- ut_memcpy(tmp_buff, foreign->referenced_table_name_lookup, len);
- tmp_buff[len] = 0;
-
- ut_ad(len < sizeof(tmp_buff));
-
- len = filename_to_tablename(tmp_buff, name_buff, sizeof(name_buff));
- f_key_info->db = thd_strmake(thd, name_buff, len);
-
- ptr = dict_remove_db_name(foreign->referenced_table_name_lookup);
- len = filename_to_tablename(ptr, name_buff, sizeof(name_buff));
- f_key_info->tablename = thd_strmake(thd, name_buff, len);
-}
-
-/** Get the list of tables ordered by the dependency on the other tables using
-the 'CASCADE' foreign key constraint.
-@param[in,out] thd user thread handle
-@param[out] fk_table_list set of tables name info for the
- dependent table
-@retval 0 for success. */
-int
-ha_innobase::get_cascade_foreign_key_table_list(
- THD* thd,
- List<st_handler_tablename>* fk_table_list)
-{
- m_prebuilt->trx->op_info = "getting cascading foreign keys";
-
- std::list<table_list_item, ut_allocator<table_list_item> > table_list;
-
- typedef std::set<st_handler_tablename, tablename_compare,
- ut_allocator<st_handler_tablename> > cascade_fk_set;
-
- cascade_fk_set fk_set;
-
- mutex_enter(&dict_sys->mutex);
-
- /* Initialize the table_list with prebuilt->table name. */
- struct table_list_item item = {m_prebuilt->table,
- m_prebuilt->table->name.m_name};
-
- table_list.push_back(item);
-
- /* Get the parent table, grand parent table info from the
- table list by depth-first traversal. */
- do {
- const dict_table_t* parent_table;
- dict_table_t* parent = NULL;
- std::pair<cascade_fk_set::iterator,bool> ret;
-
- item = table_list.back();
- table_list.pop_back();
- parent_table = item.table;
-
- if (parent_table == NULL) {
-
- ut_ad(item.name != NULL);
-
- parent_table = parent = dict_table_open_on_name(
- item.name, TRUE, FALSE,
- DICT_ERR_IGNORE_NONE);
-
- if (parent_table == NULL) {
- /* foreign_key_checks is or was probably
- disabled; ignore the constraint */
- continue;
- }
- }
-
- for (dict_foreign_set::const_iterator it =
- parent_table->foreign_set.begin();
- it != parent_table->foreign_set.end(); ++it) {
-
- const dict_foreign_t* foreign = *it;
- st_handler_tablename f1;
-
- /* Skip the table if there is no
- cascading operation. */
- if (0 == (foreign->type
- & ~(DICT_FOREIGN_ON_DELETE_NO_ACTION
- | DICT_FOREIGN_ON_UPDATE_NO_ACTION))) {
- continue;
- }
-
- if (foreign->referenced_table_name_lookup != NULL) {
- get_table_name_info(thd, &f1, foreign);
- ret = fk_set.insert(f1);
-
- /* Ignore the table if it is already
- in the set. */
- if (!ret.second) {
- continue;
- }
-
- struct table_list_item item1 = {
- foreign->referenced_table,
- foreign->referenced_table_name_lookup};
-
- table_list.push_back(item1);
-
- st_handler_tablename* fk_table =
- (st_handler_tablename*) thd_memdup(
- thd, &f1, sizeof(*fk_table));
-
- fk_table_list->push_back(fk_table);
- }
- }
-
- if (parent != NULL) {
- dict_table_close(parent, true, false);
- }
-
- } while(!table_list.empty());
-
- mutex_exit(&dict_sys->mutex);
-
- m_prebuilt->trx->op_info = "";
-
- return(0);
-}
-
/*****************************************************************//**
Checks if ALTER TABLE may change the storage engine of the table.
Changing storage engines is not allowed for tables for which there
@@ -15559,12 +15433,9 @@ ha_innobase::extra(
}
/**
-MySQL calls this method at the end of each statement. This method
-exists for readability only. ha_innobase::reset() doesn't give any
-clue about the method. */
-
+MySQL calls this method at the end of each statement */
int
-ha_innobase::end_stmt()
+ha_innobase::reset()
{
if (m_prebuilt->blob_heap) {
row_mysql_prebuilt_free_blob_heap(m_prebuilt);
@@ -15583,15 +15454,6 @@ ha_innobase::end_stmt()
return(0);
}
-/**
-MySQL calls this method at the end of each statement */
-
-int
-ha_innobase::reset()
-{
- return(end_stmt());
-}
-
/******************************************************************//**
MySQL calls this function at the start of each SQL statement inside LOCK
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
@@ -15765,8 +15627,7 @@ ha_innobase::external_lock(
if (!skip) {
#ifdef WITH_WSREP
- if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE)
- {
+ if (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd)) {
#endif /* WITH_WSREP */
my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0),
" InnoDB is limited to row-logging when"
@@ -16681,7 +16542,7 @@ ha_innobase::innobase_get_autoinc(
/* It should have been initialized during open. */
if (*value == 0) {
m_prebuilt->autoinc_error = DB_UNSUPPORTED;
- dict_table_autoinc_unlock(m_prebuilt->table);
+ mutex_exit(&m_prebuilt->table->autoinc_mutex);
}
}
@@ -16705,7 +16566,7 @@ ha_innobase::innobase_peek_autoinc(void)
innodb_table = m_prebuilt->table;
- dict_table_autoinc_lock(innodb_table);
+ mutex_enter(&innodb_table->autoinc_mutex);
auto_inc = dict_table_autoinc_read(innodb_table);
@@ -16714,7 +16575,7 @@ ha_innobase::innobase_peek_autoinc(void)
" '" << innodb_table->name << "'";
}
- dict_table_autoinc_unlock(innodb_table);
+ mutex_exit(&innodb_table->autoinc_mutex);
return(auto_inc);
}
@@ -16821,7 +16682,7 @@ ha_innobase::get_auto_increment(
/* Out of range number. Let handler::update_auto_increment()
take care of this */
m_prebuilt->autoinc_last_value = 0;
- dict_table_autoinc_unlock(m_prebuilt->table);
+ mutex_exit(&m_prebuilt->table->autoinc_mutex);
*nb_reserved_values= 0;
return;
}
@@ -16864,7 +16725,7 @@ ha_innobase::get_auto_increment(
m_prebuilt->autoinc_offset = offset;
m_prebuilt->autoinc_increment = increment;
- dict_table_autoinc_unlock(m_prebuilt->table);
+ mutex_exit(&m_prebuilt->table->autoinc_mutex);
}
/*******************************************************************//**
@@ -17473,9 +17334,7 @@ fast_shutdown_validate(
uint new_val = *reinterpret_cast<uint*>(save);
if (srv_fast_shutdown && !new_val
- && !my_atomic_loadptr_explicit(reinterpret_cast<void**>
- (&srv_running),
- MY_MEMORY_ORDER_RELAXED)) {
+ && !srv_running.load(std::memory_order_relaxed)) {
return(1);
}
@@ -17685,7 +17544,7 @@ func_exit:
buf_block_t* block = buf_page_get(
page_id_t(space_id, srv_saved_page_number_debug),
- page_size_t(space->flags), RW_X_LATCH, &mtr);
+ space->zip_size(), RW_X_LATCH, &mtr);
if (block != NULL) {
byte* page = block->frame;
@@ -18879,123 +18738,32 @@ wsrep_innobase_kill_one_trx(
bf_trx ? bf_trx->id : 0);
DBUG_RETURN(1);
}
-
WSREP_LOG_CONFLICT(bf_thd, thd, TRUE);
-
+ wsrep_thd_LOCK(thd);
WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF
"), victim: (%lu) trx: " TRX_ID_FMT,
signal, bf_seqno,
thd_get_thread_id(thd),
victim_trx->id);
- WSREP_DEBUG("Aborting query: %s conf %d trx: %" PRId64,
+ WSREP_DEBUG("Aborting query: %s conf %s trx: %lld",
(thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void",
- wsrep_thd_conflict_state(thd, FALSE),
- wsrep_thd_ws_handle(thd)->trx_id);
-
- wsrep_thd_LOCK(thd);
- DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock",
- {
- const char act[]=
- "now "
- "wait_for signal.wsrep_after_BF_victim_lock";
- DBUG_ASSERT(!debug_sync_set_action(bf_thd,
- STRING_WITH_LEN(act)));
- };);
-
-
- if (wsrep_thd_query_state(thd) == QUERY_EXITING) {
- WSREP_DEBUG("kill trx EXITING for " TRX_ID_FMT,
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- DBUG_RETURN(0);
- }
-
- if (wsrep_thd_exec_mode(thd) != LOCAL_STATE) {
- WSREP_DEBUG("withdraw for BF trx: " TRX_ID_FMT ", state: %d",
- victim_trx->id,
- wsrep_thd_get_conflict_state(thd));
- }
-
- switch (wsrep_thd_get_conflict_state(thd)) {
- case NO_CONFLICT:
- wsrep_thd_set_conflict_state(thd, MUST_ABORT);
- break;
- case MUST_ABORT:
- WSREP_DEBUG("victim " TRX_ID_FMT " in MUST ABORT state",
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- DBUG_RETURN(0);
- break;
- case ABORTED:
- case ABORTING: // fall through
- default:
- WSREP_DEBUG("victim " TRX_ID_FMT " in state %d",
- victim_trx->id, wsrep_thd_get_conflict_state(thd));
- wsrep_thd_UNLOCK(thd);
- DBUG_RETURN(0);
- break;
- }
-
- switch (wsrep_thd_query_state(thd)) {
- case QUERY_COMMITTING:
- enum wsrep_status rcode;
-
- WSREP_DEBUG("kill query for: %ld",
- thd_get_thread_id(thd));
- WSREP_DEBUG("kill trx QUERY_COMMITTING for " TRX_ID_FMT,
- victim_trx->id);
-
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- } else {
- wsrep_t *wsrep= get_wsrep();
- rcode = wsrep->abort_pre_commit(
- wsrep, bf_seqno,
- (wsrep_trx_id_t)wsrep_thd_ws_handle(thd)->trx_id
- );
-
- switch (rcode) {
- case WSREP_WARNING:
- WSREP_DEBUG("cancel commit warning: "
- TRX_ID_FMT,
- victim_trx->id);
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- DBUG_RETURN(1);
- break;
- case WSREP_OK:
- break;
- default:
- WSREP_ERROR(
- "cancel commit bad exit: %d "
- TRX_ID_FMT,
- rcode, victim_trx->id);
- /* unable to interrupt, must abort */
- /* note: kill_mysql() will block, if we cannot.
- * kill the lock holder first.
- */
- abort();
- break;
- }
- }
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- break;
- case QUERY_EXEC:
- /* it is possible that victim trx is itself waiting for some
- * other lock. We need to cancel this waiting
- */
- WSREP_DEBUG("kill trx QUERY_EXEC for " TRX_ID_FMT,
- victim_trx->id);
-
- victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
-
+ wsrep_thd_transaction_state_str(thd),
+ wsrep_thd_transaction_id(thd));
+
+ /*
+ * we mark with was_chosen_as_deadlock_victim transaction,
+ * which is already marked as BF victim
+ * lock_sys is held until this vicitm has aborted
+ */
+ victim_trx->lock.was_chosen_as_wsrep_victim = TRUE;
+
+ wsrep_thd_UNLOCK(thd);
+ if (wsrep_thd_bf_abort(bf_thd, thd, signal))
+ {
if (victim_trx->lock.wait_lock) {
- WSREP_DEBUG("victim has wait flag: %ld",
- thd_get_thread_id(thd));
+ WSREP_DEBUG("victim has wait flag: %lu",
+ thd_get_thread_id(thd));
lock_t* wait_lock = victim_trx->lock.wait_lock;
if (wait_lock) {
@@ -19003,67 +18771,7 @@ wsrep_innobase_kill_one_trx(
victim_trx->lock.was_chosen_as_deadlock_victim= TRUE;
lock_cancel_waiting_and_release(wait_lock);
}
-
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
- } else {
- /* abort currently executing query */
- DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu",
- thd_get_thread_id(thd)));
- WSREP_DEBUG("kill query for: %ld",
- thd_get_thread_id(thd));
- /* Note that innobase_kill_query will take lock_mutex
- and trx_mutex */
- wsrep_thd_UNLOCK(thd);
- wsrep_thd_awake(thd, signal);
-
- /* for BF thd, we need to prevent him from committing */
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- }
- }
- break;
- case QUERY_IDLE:
- {
- WSREP_DEBUG("kill IDLE for " TRX_ID_FMT, victim_trx->id);
-
- if (wsrep_thd_exec_mode(thd) == REPL_RECV) {
- WSREP_DEBUG("kill BF IDLE, seqno: %lld",
- (long long)wsrep_thd_trx_seqno(thd));
- wsrep_thd_UNLOCK(thd);
- wsrep_abort_slave_trx(bf_seqno,
- wsrep_thd_trx_seqno(thd));
- DBUG_RETURN(0);
- }
- /* This will lock thd from proceeding after net_read() */
- wsrep_thd_set_conflict_state(thd, ABORTING);
-
- wsrep_lock_rollback();
-
- if (wsrep_aborting_thd_contains(thd)) {
- WSREP_WARN("duplicate thd aborter %lu",
- (ulong) thd_get_thread_id(thd));
- } else {
- wsrep_aborting_thd_enqueue(thd);
- DBUG_PRINT("wsrep",("enqueuing trx abort for %lu",
- thd_get_thread_id(thd)));
- WSREP_DEBUG("enqueuing trx abort for (%lu)",
- thd_get_thread_id(thd));
}
-
- DBUG_PRINT("wsrep",("signalling wsrep rollbacker"));
- WSREP_DEBUG("signaling aborter");
- wsrep_unlock_rollback();
- wsrep_thd_UNLOCK(thd);
-
- break;
- }
- default:
- WSREP_WARN("bad wsrep query state: %d",
- wsrep_thd_query_state(thd));
- wsrep_thd_UNLOCK(thd);
- break;
}
DBUG_RETURN(0);
@@ -19083,26 +18791,22 @@ wsrep_abort_transaction(
trx_t* victim_trx = thd_to_trx(victim_thd);
trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
- WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d",
+ WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s",
wsrep_thd_query(bf_thd),
wsrep_thd_query(victim_thd),
- wsrep_thd_conflict_state(victim_thd, FALSE));
+ wsrep_thd_transaction_state_str(victim_thd));
if (victim_trx) {
lock_mutex_enter();
trx_mutex_enter(victim_trx);
- int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
- victim_trx, signal);
- lock_mutex_exit();
+ int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
+ victim_trx, signal);
trx_mutex_exit(victim_trx);
+ lock_mutex_exit();
wsrep_srv_conc_cancel_wait(victim_trx);
DBUG_RETURN(rcode);
} else {
- WSREP_DEBUG("victim does not have transaction");
- wsrep_thd_LOCK(victim_thd);
- wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT);
- wsrep_thd_UNLOCK(victim_thd);
- wsrep_thd_awake(victim_thd, signal);
+ wsrep_thd_bf_abort(bf_thd, victim_thd, signal);
}
DBUG_RETURN(-1);
@@ -19138,15 +18842,6 @@ innobase_wsrep_get_checkpoint(
trx_rseg_read_wsrep_checkpoint(*xid);
return 0;
}
-
-static void wsrep_fake_trx_id(handlerton *, THD *thd)
-{
- trx_id_t trx_id = trx_sys.get_new_trx_id();
- WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s",
- trx_id, wsrep_thd_query(thd));
- wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id);
-}
-
#endif /* WITH_WSREP */
/* plugin options */
@@ -19154,7 +18849,11 @@ static void wsrep_fake_trx_id(handlerton *, THD *thd)
static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm,
PLUGIN_VAR_RQCMDARG,
"The algorithm InnoDB uses for page checksumming. Possible values are"
- " CRC32 (hardware accelerated if the CPU supports it)"
+ " FULL_CRC32"
+ " for new files, always use CRC-32C; for old, see CRC32 below;"
+ " STRICT_FULL_CRC32"
+ " for new files, always use CRC-32C; for old, see STRICT_CRC32 below;"
+ " CRC32"
" write crc32, allow any of the other checksums to match when reading;"
" STRICT_CRC32"
" write crc32, do not allow other algorithms to match when reading;"
@@ -19171,7 +18870,8 @@ static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm,
" write a constant magic number, do not allow values other than that"
" magic number when reading;"
" Files updated when this option is set to crc32 or strict_crc32 will"
- " not be readable by MariaDB versions older than 10.0.4",
+ " not be readable by MariaDB versions older than 10.0.4;"
+ " new files created with full_crc32 are readable by MariaDB 10.4.3+",
NULL, NULL, SRV_CHECKSUM_ALGORITHM_CRC32,
&innodb_checksum_algorithm_typelib);
@@ -19218,7 +18918,7 @@ static MYSQL_SYSVAR_BOOL(stats_include_delete_marked,
static MYSQL_SYSVAR_ENUM(instant_alter_column_allowed,
innodb_instant_alter_column_allowed,
PLUGIN_VAR_RQCMDARG,
- "File format constraint for ALTER TABLE", NULL, NULL, 1/*add_last*/,
+ "File format constraint for ALTER TABLE", NULL, NULL, 2/*add_drop_reorder*/,
&innodb_instant_alter_column_allowed_typelib);
static MYSQL_SYSVAR_ULONG(io_capacity, srv_io_capacity,
@@ -20748,20 +20448,6 @@ ha_innobase::multi_range_read_explain_info(
return m_ds_mrr.dsmrr_explain_info(mrr_mode, str, size);
}
-/**
-Index Condition Pushdown interface implementation */
-
-/*************************************************************//**
-InnoDB index push-down condition check
-@return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */
-ICP_RESULT
-innobase_index_cond(
-/*================*/
- void* file) /*!< in/out: pointer to ha_innobase */
-{
- return handler_index_cond_check(file);
-}
-
/** Parse the table file name into table name and database name.
@param[in] tbl_name InnoDB table name
@param[out] dbname database name buffer (NAME_LEN + 1 bytes)
@@ -20906,10 +20592,10 @@ static TABLE* innodb_find_table_for_vc(THD* thd, dict_table_t* table)
"SIGNAL got_no_such_table"))););
if (THDVAR(thd, background_thread)) {
- /* Purge thread acquires dict_operation_lock while
- processing undo log record. Release the dict_operation_lock
+ /* Purge thread acquires dict_sys.latch while
+ processing undo log record. Release it
before acquiring MDL on the table. */
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
return innodb_acquire_mdl(thd, table);
} else {
if (table->vc_templ->mysql_table_query_id
@@ -20955,9 +20641,9 @@ TABLE* innobase_init_vc_templ(dict_table_t* table)
DBUG_RETURN(NULL);
}
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
innobase_build_v_templ(mysql_table, table, table->vc_templ, NULL, true);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
DBUG_RETURN(mysql_table);
}
@@ -21153,9 +20839,9 @@ innobase_get_computed_value(
dfield_t* field;
ulint len;
- const page_size_t page_size = (old_table == NULL)
- ? dict_table_page_size(index->table)
- : dict_table_page_size(old_table);
+ const ulint zip_size = old_table
+ ? old_table->space->zip_size()
+ : dict_tf_get_zip_size(index->table->flags);
ulint ret = 0;
@@ -21180,7 +20866,7 @@ innobase_get_computed_value(
buf = rec_buf2;
}
- for (ulint i = 0; i < col->num_base; i++) {
+ for (ulint i = 0; i < unsigned{col->num_base}; i++) {
dict_col_t* base_col = col->base_col[i];
const dfield_t* row_field = NULL;
ulint col_no = base_col->ind;
@@ -21208,7 +20894,7 @@ innobase_get_computed_value(
}
data = btr_copy_externally_stored_field(
- &len, data, page_size,
+ &len, data, zip_size,
dfield_get_len(row_field), *local_heap);
}
@@ -21323,6 +21009,190 @@ ha_innobase::idx_cond_push(
DBUG_RETURN(NULL);
}
+
+/** Push a primary key filter.
+@param[in] pk_filter filter against which primary keys
+ are to be checked
+@retval false if pushed (always) */
+bool ha_innobase::rowid_filter_push(Rowid_filter* pk_filter)
+{
+ DBUG_ENTER("ha_innobase::rowid_filter_push");
+ DBUG_ASSERT(pk_filter != NULL);
+ pushed_rowid_filter= pk_filter;
+ DBUG_RETURN(false);
+}
+
+static bool
+is_part_of_a_primary_key(const Field* field)
+{
+ const TABLE_SHARE* s = field->table->s;
+
+ return s->primary_key != MAX_KEY
+ && field->part_of_key.is_set(s->primary_key);
+}
+
+bool
+ha_innobase::can_convert_string(const Field_string* field,
+ const Column_definition& new_type) const
+{
+ DBUG_ASSERT(!field->compression_method());
+ if (new_type.type_handler() != field->type_handler()) {
+ return false;
+ }
+
+ if (new_type.char_length < field->char_length()) {
+ return false;
+ }
+
+ if (new_type.charset != field->charset()) {
+ if (new_type.length != field->max_display_length()
+ && !m_prebuilt->table->not_redundant()) {
+ return IS_EQUAL_NO;
+ }
+
+ Charset field_cs(field->charset());
+ if (!field_cs.encoding_allows_reinterpret_as(
+ new_type.charset)) {
+ return false;
+ }
+
+ if (!field_cs.eq_collation_specific_names(new_type.charset)) {
+ return !is_part_of_a_primary_key(field);
+ }
+
+ return true;
+ }
+
+ if (new_type.length != field->max_display_length()) {
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+supports_enlarging(const dict_table_t* table, const Field_varstring* field,
+ const Column_definition& new_type)
+{
+ return field->field_length <= 127 || new_type.length <= 255
+ || field->field_length > 255 || !table->not_redundant();
+}
+
+bool
+ha_innobase::can_convert_varstring(const Field_varstring* field,
+ const Column_definition& new_type) const
+{
+ if (new_type.length < field->field_length) {
+ return false;
+ }
+
+ if (new_type.char_length < field->char_length()) {
+ return false;
+ }
+
+ if (!new_type.compression_method() != !field->compression_method()) {
+ return false;
+ }
+
+ if (new_type.type_handler() != field->type_handler()) {
+ return false;
+ }
+
+ if (new_type.charset != field->charset()) {
+ if (!supports_enlarging(m_prebuilt->table, field, new_type)) {
+ return false;
+ }
+
+ Charset field_cs(field->charset());
+ if (!field_cs.encoding_allows_reinterpret_as(
+ new_type.charset)) {
+ return false;
+ }
+
+ if (!field_cs.eq_collation_specific_names(new_type.charset)) {
+ return !is_part_of_a_primary_key(field);
+ }
+
+ return true;
+ }
+
+ if (new_type.length != field->field_length) {
+ if (!supports_enlarging(m_prebuilt->table, field, new_type)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ return true;
+}
+
+bool
+ha_innobase::can_convert_blob(const Field_blob* field,
+ const Column_definition& new_type) const
+{
+ if (new_type.type_handler() != field->type_handler()) {
+ return false;
+ }
+
+ if (!new_type.compression_method() != !field->compression_method()) {
+ return false;
+ }
+
+ if (new_type.pack_length != field->pack_length()) {
+ return false;
+ }
+
+ if (new_type.charset != field->charset()) {
+ Charset field_cs(field->charset());
+ if (!field_cs.encoding_allows_reinterpret_as(
+ new_type.charset)) {
+ return false;
+ }
+
+ if (!field_cs.eq_collation_specific_names(new_type.charset)) {
+ bool is_part_of_a_key
+ = !field->part_of_key.is_clear_all();
+ return !is_part_of_a_key;
+ }
+
+ return true;
+ }
+
+ return true;
+}
+
+Compare_keys ha_innobase::compare_key_parts(
+ const Field &old_field, const Column_definition &new_field,
+ const KEY_PART_INFO &old_part, const KEY_PART_INFO &new_part) const
+{
+ const bool is_equal= old_field.is_equal(new_field);
+ const CHARSET_INFO *old_cs= old_field.charset();
+ const CHARSET_INFO *new_cs= new_field.charset;
+
+ if (!is_equal)
+ {
+ if (!old_field.can_be_converted_by_engine(new_field))
+ return Compare_keys::NotEqual;
+
+ if (!Charset(old_cs).eq_collation_specific_names(new_cs))
+ return Compare_keys::NotEqual;
+ }
+
+ if (old_part.length / old_cs->mbmaxlen != new_part.length / new_cs->mbmaxlen)
+ {
+ if (old_part.length != old_field.field_length)
+ return Compare_keys::NotEqual;
+
+ if (old_part.length >= new_part.length)
+ return Compare_keys::NotEqual;
+
+ return Compare_keys::EqualButKeyPartLength;
+ }
+
+ return Compare_keys::Equal;
+}
+
/******************************************************************//**
Use this when the args are passed to the format string from
errmsg-utf8.txt directly as is.
@@ -21358,10 +21228,10 @@ ib_senderrf(
switch (level) {
case IB_LOG_LEVEL_INFO:
- l = ME_JUST_INFO;
+ l = ME_NOTE;
break;
case IB_LOG_LEVEL_WARN:
- l = ME_JUST_WARNING;
+ l = ME_WARNING;
break;
default:
l = 0;
diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h
index 8e513ddd692..3e3dffbc7a9 100644
--- a/storage/innobase/handler/ha_innodb.h
+++ b/storage/innobase/handler/ha_innodb.h
@@ -16,10 +16,9 @@ this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
*****************************************************************************/
-
#ifdef WITH_WSREP
-# include <mysql/service_wsrep.h>
-# include "../../../wsrep/wsrep_api.h"
+#include "wsrep_api.h"
+#include <mysql/service_wsrep.h>
#endif /* WITH_WSREP */
#include "table.h"
@@ -59,35 +58,33 @@ struct st_handler_tablename
const char *tablename;
};
/** The class defining a handle to an Innodb table */
-class ha_innobase: public handler
+class ha_innobase final: public handler
{
public:
ha_innobase(handlerton* hton, TABLE_SHARE* table_arg);
- ~ha_innobase();
+ ~ha_innobase() override;
/** Get the row type from the storage engine. If this method returns
ROW_TYPE_NOT_USED, the information in HA_CREATE_INFO should be used. */
- enum row_type get_row_type() const;
-
- const char* table_type() const;
+ enum row_type get_row_type() const override;
- const char* index_type(uint key_number);
+ const char* table_type() const;
- const char** bas_ext() const;
+ const char* index_type(uint key_number) override;
- Table_flags table_flags() const;
+ Table_flags table_flags() const override;
- ulong index_flags(uint idx, uint part, bool all_parts) const;
+ ulong index_flags(uint idx, uint part, bool all_parts) const override;
- uint max_supported_keys() const;
+ uint max_supported_keys() const override;
- uint max_supported_key_length() const;
+ uint max_supported_key_length() const override;
- uint max_supported_key_part_length() const;
+ uint max_supported_key_part_length() const override;
- const key_map* keys_to_use_for_scanning();
+ const key_map* keys_to_use_for_scanning() override;
- void column_bitmaps_signal();
+ void column_bitmaps_signal() override;
/** Opens dictionary table object using table name. For partition, we need to
try alternative lower/upper case names to support moving data files across
@@ -103,97 +100,97 @@ public:
bool is_partition,
dict_err_ignore_t ignore_err);
- int open(const char *name, int mode, uint test_if_locked);
+ int open(const char *name, int mode, uint test_if_locked) override;
- handler* clone(const char *name, MEM_ROOT *mem_root);
+ handler* clone(const char *name, MEM_ROOT *mem_root) override;
- int close(void);
+ int close(void) override;
- double scan_time();
+ double scan_time() override;
- double read_time(uint index, uint ranges, ha_rows rows);
+ double read_time(uint index, uint ranges, ha_rows rows) override;
- int delete_all_rows();
+ int delete_all_rows() override;
- int write_row(uchar * buf);
+ int write_row(const uchar * buf) override;
- int update_row(const uchar * old_data, const uchar * new_data);
+ int update_row(const uchar * old_data, const uchar * new_data) override;
- int delete_row(const uchar * buf);
+ int delete_row(const uchar * buf) override;
- bool was_semi_consistent_read();
+ bool was_semi_consistent_read() override;
- void try_semi_consistent_read(bool yes);
+ void try_semi_consistent_read(bool yes) override;
- void unlock_row();
+ void unlock_row() override;
- int index_init(uint index, bool sorted);
+ int index_init(uint index, bool sorted) override;
- int index_end();
+ int index_end() override;
int index_read(
uchar* buf,
const uchar* key,
uint key_len,
- ha_rkey_function find_flag);
+ ha_rkey_function find_flag) override;
- int index_read_last(uchar * buf, const uchar * key, uint key_len);
+ int index_read_last(uchar * buf, const uchar * key,
+ uint key_len) override;
- int index_next(uchar * buf);
+ int index_next(uchar * buf) override;
- int index_next_same(uchar * buf, const uchar *key, uint keylen);
+ int index_next_same(uchar * buf, const uchar * key,
+ uint keylen) override;
- int index_prev(uchar * buf);
+ int index_prev(uchar * buf) override;
- int index_first(uchar * buf);
+ int index_first(uchar * buf) override;
- int index_last(uchar * buf);
+ int index_last(uchar * buf) override;
/* Copy a cached MySQL row. If requested, also avoids
overwriting non-read columns. */
void copy_cached_row(uchar *to_rec, const uchar *from_rec,
uint rec_length);
- int rnd_init(bool scan);
+ int rnd_init(bool scan) override;
- int rnd_end();
+ int rnd_end() override;
- int rnd_next(uchar *buf);
+ int rnd_next(uchar *buf) override;
- int rnd_pos(uchar * buf, uchar *pos);
+ int rnd_pos(uchar * buf, uchar *pos) override;
- int ft_init();
- void ft_end() { rnd_end(); }
- FT_INFO *ft_init_ext(uint flags, uint inx, String* key);
- int ft_read(uchar* buf);
+ int ft_init() override;
+ void ft_end() override { rnd_end(); }
+ FT_INFO *ft_init_ext(uint flags, uint inx, String* key) override;
+ int ft_read(uchar* buf) override;
- void position(const uchar *record);
+ void position(const uchar *record) override;
- int info(uint);
+ int info(uint) override;
- int analyze(THD* thd,HA_CHECK_OPT* check_opt);
+ int analyze(THD* thd,HA_CHECK_OPT* check_opt) override;
- int optimize(THD* thd,HA_CHECK_OPT* check_opt);
+ int optimize(THD* thd,HA_CHECK_OPT* check_opt) override;
- int discard_or_import_tablespace(my_bool discard);
+ int discard_or_import_tablespace(my_bool discard) override;
- int extra(ha_extra_function operation);
+ int extra(ha_extra_function operation) override;
- int reset();
+ int reset() override;
- int external_lock(THD *thd, int lock_type);
+ int external_lock(THD *thd, int lock_type) override;
- int start_stmt(THD *thd, thr_lock_type lock_type);
-
- void position(uchar *record);
+ int start_stmt(THD *thd, thr_lock_type lock_type) override;
ha_rows records_in_range(
uint inx,
key_range* min_key,
- key_range* max_key);
+ key_range* max_key) override;
- ha_rows estimate_rows_upper_bound();
+ ha_rows estimate_rows_upper_bound() override;
- void update_create_info(HA_CREATE_INFO* create_info);
+ void update_create_info(HA_CREATE_INFO* create_info) override;
inline int create(
const char* name,
@@ -205,63 +202,57 @@ public:
int create(
const char* name,
TABLE* form,
- HA_CREATE_INFO* create_info);
-
- const char* check_table_options(THD *thd, TABLE* table,
- HA_CREATE_INFO* create_info, const bool use_tablespace, const ulint file_format);
+ HA_CREATE_INFO* create_info) override;
inline int delete_table(const char* name, enum_sql_command sqlcom);
- int truncate();
+ int truncate() override;
- int delete_table(const char *name);
+ int delete_table(const char *name) override;
- int rename_table(const char* from, const char* to);
+ int rename_table(const char* from, const char* to) override;
int defragment_table(const char* name, const char* index_name,
bool async);
- int check(THD* thd, HA_CHECK_OPT* check_opt);
- char* update_table_comment(const char* comment);
+ int check(THD* thd, HA_CHECK_OPT* check_opt) override;
+ char* update_table_comment(const char* comment) override;
- char* get_foreign_key_create_info();
+ char* get_foreign_key_create_info() override;
- int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
+ int get_foreign_key_list(THD *thd,
+ List<FOREIGN_KEY_INFO> *f_key_list) override;
int get_parent_foreign_key_list(
THD* thd,
- List<FOREIGN_KEY_INFO>* f_key_list);
- int get_cascade_foreign_key_table_list(
- THD* thd,
- List<st_handler_tablename>* fk_table_list);
+ List<FOREIGN_KEY_INFO>* f_key_list) override;
+ bool can_switch_engines() override;
- bool can_switch_engines();
+ uint referenced_by_foreign_key() override;
- uint referenced_by_foreign_key();
+ void free_foreign_key_create_info(char* str) override;
- void free_foreign_key_create_info(char* str);
-
- uint lock_count(void) const;
+ uint lock_count(void) const override;
THR_LOCK_DATA** store_lock(
THD* thd,
THR_LOCK_DATA** to,
- thr_lock_type lock_type);
+ thr_lock_type lock_type) override;
- void init_table_handle_for_HANDLER();
+ void init_table_handle_for_HANDLER() override;
- virtual void get_auto_increment(
+ void get_auto_increment(
ulonglong offset,
ulonglong increment,
ulonglong nb_desired_values,
ulonglong* first_value,
- ulonglong* nb_reserved_values);
- int reset_auto_increment(ulonglong value);
+ ulonglong* nb_reserved_values) override;
+ int reset_auto_increment(ulonglong value) override;
- virtual bool get_error_message(int error, String *buf);
+ bool get_error_message(int error, String *buf) override;
- virtual bool get_foreign_dup_key(char*, uint, char*, uint);
+ bool get_foreign_dup_key(char*, uint, char*, uint) override;
- uint8 table_cache_type();
+ uint8 table_cache_type() override;
/**
Ask handler about permission to cache table during query registration
@@ -271,11 +262,11 @@ public:
const char* table_key,
uint key_length,
qc_engine_callback* call_back,
- ulonglong* engine_data);
+ ulonglong* engine_data) override;
- bool primary_key_is_clustered();
+ bool primary_key_is_clustered() override;
- int cmp_ref(const uchar* ref1, const uchar* ref2);
+ int cmp_ref(const uchar* ref1, const uchar* ref2) override;
/** On-line ALTER TABLE interface @see handler0alter.cc @{ */
@@ -305,7 +296,7 @@ public:
enum_alter_inplace_result check_if_supported_inplace_alter(
TABLE* altered_table,
- Alter_inplace_info* ha_alter_info);
+ Alter_inplace_info* ha_alter_info) override;
/** Allows InnoDB to update internal structures with concurrent
writes blocked (provided that check_if_supported_inplace_alter()
@@ -321,7 +312,7 @@ public:
*/
bool prepare_inplace_alter_table(
TABLE* altered_table,
- Alter_inplace_info* ha_alter_info);
+ Alter_inplace_info* ha_alter_info) override;
/** Alter the table structure in-place with operations
specified using HA_ALTER_FLAGS and Alter_inplace_information.
@@ -337,7 +328,7 @@ public:
*/
bool inplace_alter_table(
TABLE* altered_table,
- Alter_inplace_info* ha_alter_info);
+ Alter_inplace_info* ha_alter_info) override;
/** Commit or rollback the changes made during
prepare_inplace_alter_table() and inplace_alter_table() inside
@@ -356,12 +347,12 @@ public:
bool commit_inplace_alter_table(
TABLE* altered_table,
Alter_inplace_info* ha_alter_info,
- bool commit);
+ bool commit) override;
/** @} */
bool check_if_incompatible_data(
HA_CREATE_INFO* info,
- uint table_changes);
+ uint table_changes) override;
/** @name Multi Range Read interface @{ */
@@ -376,11 +367,11 @@ public:
void* seq_init_param,
uint n_ranges,
uint mode,
- HANDLER_BUFFER* buf);
+ HANDLER_BUFFER* buf) override;
/** Process next multi range read @see DsMrr_impl::dsmrr_next
@param range_info */
- int multi_range_read_next(range_id_t *range_info);
+ int multi_range_read_next(range_id_t *range_info) override;
/** Initialize multi range read and get information.
@see ha_myisam::multi_range_read_info_const
@@ -399,7 +390,7 @@ public:
uint n_ranges,
uint* bufsz,
uint* flags,
- Cost_estimate* cost);
+ Cost_estimate* cost) override;
/** Initialize multi range read and get information.
@see DsMrr_impl::dsmrr_info
@@ -412,16 +403,16 @@ public:
@param cost */
ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
uint key_parts, uint* bufsz, uint* flags,
- Cost_estimate* cost);
+ Cost_estimate* cost) override;
int multi_range_read_explain_info(uint mrr_mode,
- char *str, size_t size);
+ char *str, size_t size) override;
/** Attempt to push down an index condition.
@param[in] keyno MySQL key number
@param[in] idx_cond Index condition to be checked
@return idx_cond if pushed; NULL if not pushed */
- Item* idx_cond_push(uint keyno, Item* idx_cond);
+ Item* idx_cond_push(uint keyno, Item* idx_cond) override;
/* @} */
/** Check if InnoDB is not storing virtual column metadata for a table.
@@ -432,13 +423,35 @@ public:
return s.frm_version<FRM_VER_EXPRESSSIONS && s.virtual_fields;
}
-protected:
- /**
- MySQL calls this method at the end of each statement. This method
- exists for readability only, called from reset(). The name reset()
- doesn't give any clue that it is called at the end of a statement. */
- int end_stmt();
+ /** Push a primary key filter.
+ @param[in] pk_filter filter against which primary keys
+ are to be checked
+ @retval false if pushed (always) */
+ bool rowid_filter_push(Rowid_filter *rowid_filter) override;
+
+ bool
+ can_convert_string(const Field_string* field,
+ const Column_definition& new_field) const override;
+ bool can_convert_varstring(
+ const Field_varstring* field,
+ const Column_definition& new_field) const override;
+ bool
+ can_convert_blob(const Field_blob* field,
+ const Column_definition& new_field) const override;
+
+ /** @return whether innodb_strict_mode is active */
+ static bool is_innodb_strict_mode(THD* thd);
+
+ /** @return whether innodb_strict_mode is active */
+ bool is_innodb_strict_mode()
+ { return is_innodb_strict_mode(m_user_thd); }
+ Compare_keys
+ compare_key_parts(const Field& old_field,
+ const Column_definition& new_field,
+ const KEY_PART_INFO& old_part,
+ const KEY_PART_INFO& new_part) const override;
+protected:
dberr_t innobase_get_autoinc(ulonglong* value);
dberr_t innobase_lock_autoinc();
ulonglong innobase_peek_autoinc();
@@ -457,8 +470,11 @@ protected:
dict_index_t* innobase_get_index(uint keynr);
#ifdef WITH_WSREP
- int wsrep_append_keys(THD *thd, wsrep_key_type key_type,
- const uchar* record0, const uchar* record1);
+ int wsrep_append_keys(
+ THD *thd,
+ Wsrep_service_key_type key_type,
+ const uchar* record0,
+ const uchar* record1);
#endif
/** Builds a 'template' to the prebuilt struct.
@@ -468,7 +484,7 @@ protected:
false if accessing individual fields is enough */
void build_template(bool whole_row);
- virtual int info_low(uint, bool);
+ int info_low(uint, bool);
/** The multi range read session object */
DsMrr_impl m_ds_mrr;
@@ -570,23 +586,8 @@ extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **
struct trx_t;
#ifdef WITH_WSREP
-//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2);
-
-extern "C" bool wsrep_thd_is_wsrep_on(THD *thd);
-
-
-extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode);
-extern "C" void wsrep_thd_set_query_state(
- THD *thd, enum wsrep_query_state state);
-
-extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id);
-
-extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd);
-extern "C" time_t wsrep_thd_query_start(THD *thd);
-extern "C" query_id_t wsrep_thd_query_id(THD *thd);
-extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd);
-extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id);
-#endif
+#include <mysql/service_wsrep.h>
+#endif /* WITH_WSREP */
extern const struct _ft_vft ft_vft_result;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index be6bc669349..9b5b4d6e566 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -109,10 +109,12 @@ static const alter_table_operations INNOBASE_INPLACE_IGNORE
| ALTER_PARTITIONED
| ALTER_COLUMN_COLUMN_FORMAT
| ALTER_COLUMN_STORAGE_TYPE
+ | ALTER_CONVERT_TO
| ALTER_VIRTUAL_GCOL_EXPR
| ALTER_DROP_CHECK_CONSTRAINT
| ALTER_RENAME
- | ALTER_COLUMN_INDEX_LENGTH;
+ | ALTER_COLUMN_INDEX_LENGTH
+ | ALTER_CHANGE_INDEX_COMMENT;
/** Operations on foreign key definitions (changing the schema only) */
static const alter_table_operations INNOBASE_FOREIGN_OPERATIONS
@@ -144,10 +146,722 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT
| ALTER_COLUMN_NAME
| ALTER_ADD_VIRTUAL_COLUMN
| INNOBASE_FOREIGN_OPERATIONS
- | ALTER_COLUMN_EQUAL_PACK_LENGTH
+ | ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
| ALTER_COLUMN_UNVERSIONED
+ | ALTER_RENAME_INDEX
| ALTER_DROP_VIRTUAL_COLUMN;
+/** Acquire a page latch on the possible metadata record,
+to prevent concurrent invocation of dict_index_t::clear_instant_alter()
+by purge when the table turns out to be empty.
+@param[in,out] index clustered index
+@param[in,out] mtr mini-transaction */
+static void instant_metadata_lock(dict_index_t& index, mtr_t& mtr)
+{
+ DBUG_ASSERT(index.is_primary());
+
+ if (!index.is_instant()) {
+ /* dict_index_t::clear_instant_alter() cannot be called.
+ No need for a latch. */
+ return;
+ }
+
+ btr_cur_t btr_cur;
+ btr_cur_open_at_index_side(true, &index, BTR_SEARCH_LEAF,
+ &btr_cur, 0, &mtr);
+ ut_ad(page_cur_is_before_first(btr_cur_get_page_cur(&btr_cur)));
+ ut_ad(page_is_leaf(btr_cur_get_page(&btr_cur)));
+ ut_ad(!page_has_prev(btr_cur_get_page(&btr_cur)));
+ ut_ad(!buf_block_get_page_zip(btr_cur_get_block(&btr_cur)));
+}
+
+/** Initialize instant->field_map.
+@param[in] table table definition to copy from */
+inline void dict_table_t::init_instant(const dict_table_t& table)
+{
+ const dict_index_t& oindex __attribute__((unused))= *table.indexes.start;
+ dict_index_t& index = *indexes.start;
+ const unsigned u = index.first_user_field();
+ DBUG_ASSERT(u == oindex.first_user_field());
+ DBUG_ASSERT(index.n_fields >= oindex.n_fields);
+
+ field_map_element_t* field_map_it = static_cast<field_map_element_t*>(
+ mem_heap_zalloc(heap, (index.n_fields - u)
+ * sizeof *field_map_it));
+ instant->field_map = field_map_it;
+
+ ut_d(unsigned n_drop = 0);
+ ut_d(unsigned n_nullable = 0);
+ for (unsigned i = u; i < index.n_fields; i++) {
+ auto& f = index.fields[i];
+ DBUG_ASSERT(dict_col_get_fixed_size(f.col, not_redundant())
+ <= DICT_MAX_FIXED_COL_LEN);
+ ut_d(n_nullable += f.col->is_nullable());
+
+ if (!f.col->is_dropped()) {
+ (*field_map_it++).set_ind(f.col->ind);
+ continue;
+ }
+
+ auto fixed_len = dict_col_get_fixed_size(
+ f.col, not_redundant());
+ field_map_it->set_dropped();
+ if (!f.col->is_nullable()) {
+ field_map_it->set_not_null();
+ }
+ field_map_it->set_ind(fixed_len
+ ? uint16_t(fixed_len + 1)
+ : DATA_BIG_COL(f.col));
+ field_map_it++;
+ ut_ad(f.col >= table.instant->dropped);
+ ut_ad(f.col < table.instant->dropped
+ + table.instant->n_dropped);
+ ut_d(n_drop++);
+ size_t d = f.col - table.instant->dropped;
+ ut_ad(f.col == &table.instant->dropped[d]);
+ ut_ad(d <= instant->n_dropped);
+ f.col = &instant->dropped[d];
+ }
+ ut_ad(n_drop == n_dropped());
+ ut_ad(field_map_it == &instant->field_map[index.n_fields - u]);
+ ut_ad(index.n_nullable == n_nullable);
+}
+
+/** Set is_instant() before instant_column().
+@param[in] old previous table definition
+@param[in] col_map map from old.cols[] and old.v_cols[] to this
+@param[out] first_alter_pos 0, or 1 + first changed column position */
+inline void dict_table_t::prepare_instant(const dict_table_t& old,
+ const ulint* col_map,
+ unsigned& first_alter_pos)
+{
+ DBUG_ASSERT(!is_instant());
+ DBUG_ASSERT(n_dropped() == 0);
+ DBUG_ASSERT(old.n_cols == old.n_def);
+ DBUG_ASSERT(n_cols == n_def);
+ DBUG_ASSERT(old.supports_instant());
+ DBUG_ASSERT(!persistent_autoinc
+ || persistent_autoinc == old.persistent_autoinc);
+ /* supports_instant() does not necessarily hold here,
+ in case ROW_FORMAT=COMPRESSED according to the
+ MariaDB data dictionary, and ALTER_OPTIONS was not set.
+ If that is the case, the instant ALTER TABLE would keep
+ the InnoDB table in its current format. */
+
+ dict_index_t& oindex = *old.indexes.start;
+ dict_index_t& index = *indexes.start;
+ first_alter_pos = 0;
+
+ mtr_t mtr;
+ mtr.start();
+ /* Protect oindex.n_core_fields and others, so that
+ purge cannot invoke dict_index_t::clear_instant_alter(). */
+ instant_metadata_lock(oindex, mtr);
+
+ for (unsigned i = 0; i + DATA_N_SYS_COLS < old.n_cols; i++) {
+ if (col_map[i] != i) {
+ first_alter_pos = 1 + i;
+ goto add_metadata;
+ }
+ }
+
+ if (!old.instant) {
+ /* Columns were not dropped or reordered.
+ Therefore columns must have been added at the end,
+ or modified instantly in place. */
+ DBUG_ASSERT(index.n_fields >= oindex.n_fields);
+ DBUG_ASSERT(index.n_fields > oindex.n_fields
+ || !not_redundant());
+#ifdef UNIV_DEBUG
+ if (index.n_fields == oindex.n_fields) {
+ ut_ad(!not_redundant());
+ for (unsigned i = index.n_fields; i--; ) {
+ ut_ad(index.fields[i].col->same_format(
+ *oindex.fields[i].col));
+ }
+ }
+#endif
+set_core_fields:
+ index.n_core_fields = oindex.n_core_fields;
+ index.n_core_null_bytes = oindex.n_core_null_bytes;
+ } else {
+add_metadata:
+ const unsigned n_old_drop = old.n_dropped();
+ unsigned n_drop = n_old_drop;
+ for (unsigned i = old.n_cols; i--; ) {
+ if (col_map[i] == ULINT_UNDEFINED) {
+ DBUG_ASSERT(i + DATA_N_SYS_COLS
+ < uint(old.n_cols));
+ n_drop++;
+ }
+ }
+
+ instant = new (mem_heap_alloc(heap, sizeof(dict_instant_t)))
+ dict_instant_t();
+ instant->n_dropped = n_drop;
+ if (n_drop) {
+ instant->dropped
+ = static_cast<dict_col_t*>(
+ mem_heap_alloc(heap, n_drop
+ * sizeof(dict_col_t)));
+ if (n_old_drop) {
+ memcpy(instant->dropped, old.instant->dropped,
+ n_old_drop * sizeof(dict_col_t));
+ }
+ } else {
+ instant->dropped = NULL;
+ }
+
+ for (unsigned i = 0, d = n_old_drop; i < old.n_cols; i++) {
+ if (col_map[i] == ULINT_UNDEFINED) {
+ (new (&instant->dropped[d++])
+ dict_col_t(old.cols[i]))->set_dropped();
+ }
+ }
+#ifndef DBUG_OFF
+ for (unsigned i = 0; i < n_drop; i++) {
+ DBUG_ASSERT(instant->dropped[i].is_dropped());
+ }
+#endif
+ const uint n_fields = index.n_fields + n_dropped();
+
+ DBUG_ASSERT(n_fields >= oindex.n_fields);
+ dict_field_t* fields = static_cast<dict_field_t*>(
+ mem_heap_zalloc(heap, n_fields * sizeof *fields));
+ uint i = 0, j = 0, n_nullable = 0;
+ ut_d(uint core_null = 0);
+ for (; i < oindex.n_fields; i++) {
+ DBUG_ASSERT(j <= i);
+ dict_field_t&f = fields[i] = oindex.fields[i];
+ if (f.col->is_dropped()) {
+ /* The column has been instantly
+ dropped earlier. */
+ DBUG_ASSERT(f.col >= old.instant->dropped);
+ {
+ size_t d = f.col
+ - old.instant->dropped;
+ DBUG_ASSERT(d < n_old_drop);
+ DBUG_ASSERT(&old.instant->dropped[d]
+ == f.col);
+ DBUG_ASSERT(!f.name);
+ f.col = instant->dropped + d;
+ }
+ if (f.col->is_nullable()) {
+found_nullable:
+ n_nullable++;
+ ut_d(core_null
+ += i < oindex.n_core_fields);
+ }
+ continue;
+ }
+
+ const ulint col_ind = col_map[f.col->ind];
+ if (col_ind != ULINT_UNDEFINED) {
+ if (index.fields[j].col->ind != col_ind) {
+ /* The fields for instantly
+ added columns must be placed
+ last in the clustered index.
+ Keep pre-existing fields in
+ the same position. */
+ uint k;
+ for (k = j + 1; k < index.n_fields;
+ k++) {
+ if (index.fields[k].col->ind
+ == col_ind) {
+ goto found_j;
+ }
+ }
+ DBUG_ASSERT(!"no such col");
+found_j:
+ std::swap(index.fields[j],
+ index.fields[k]);
+ }
+ DBUG_ASSERT(index.fields[j].col->ind
+ == col_ind);
+ fields[i] = index.fields[j++];
+ DBUG_ASSERT(!fields[i].col->is_dropped());
+ DBUG_ASSERT(fields[i].name
+ == fields[i].col->name(*this));
+ if (fields[i].col->is_nullable()) {
+ goto found_nullable;
+ }
+ continue;
+ }
+
+ /* This column is being dropped. */
+ unsigned d = n_old_drop;
+ for (unsigned c = 0; c < f.col->ind; c++) {
+ d += col_map[c] == ULINT_UNDEFINED;
+ }
+ DBUG_ASSERT(d < n_drop);
+ f.col = &instant->dropped[d];
+ f.name = NULL;
+ if (f.col->is_nullable()) {
+ goto found_nullable;
+ }
+ }
+ /* The n_core_null_bytes only matters for
+ ROW_FORMAT=COMPACT and ROW_FORMAT=DYNAMIC tables. */
+ ut_ad(UT_BITS_IN_BYTES(core_null) == oindex.n_core_null_bytes
+ || !not_redundant());
+ DBUG_ASSERT(i >= oindex.n_core_fields);
+ DBUG_ASSERT(j <= i);
+ DBUG_ASSERT(n_fields - (i - j) == index.n_fields);
+ std::sort(index.fields + j, index.fields + index.n_fields,
+ [](const dict_field_t& a, const dict_field_t& b)
+ { return a.col->ind < b.col->ind; });
+ for (; i < n_fields; i++) {
+ fields[i] = index.fields[j++];
+ n_nullable += fields[i].col->is_nullable();
+ DBUG_ASSERT(!fields[i].col->is_dropped());
+ DBUG_ASSERT(fields[i].name
+ == fields[i].col->name(*this));
+ }
+ DBUG_ASSERT(j == index.n_fields);
+ index.n_fields = index.n_def = n_fields;
+ index.fields = fields;
+ DBUG_ASSERT(n_nullable >= index.n_nullable);
+ DBUG_ASSERT(n_nullable >= oindex.n_nullable);
+ index.n_nullable = n_nullable;
+ goto set_core_fields;
+ }
+
+ DBUG_ASSERT(n_cols + n_dropped() >= old.n_cols + old.n_dropped());
+ DBUG_ASSERT(n_dropped() >= old.n_dropped());
+ DBUG_ASSERT(index.n_core_fields == oindex.n_core_fields);
+ DBUG_ASSERT(index.n_core_null_bytes == oindex.n_core_null_bytes);
+ mtr.commit();
+}
+
+/** Adjust index metadata for instant ADD/DROP/reorder COLUMN.
+@param[in] clustered index definition after instant ALTER TABLE */
+inline void dict_index_t::instant_add_field(const dict_index_t& instant)
+{
+ DBUG_ASSERT(is_primary());
+ DBUG_ASSERT(instant.is_primary());
+ DBUG_ASSERT(!has_virtual());
+ DBUG_ASSERT(!instant.has_virtual());
+ DBUG_ASSERT(instant.n_core_fields <= instant.n_fields);
+ DBUG_ASSERT(n_def == n_fields);
+ DBUG_ASSERT(instant.n_def == instant.n_fields);
+ DBUG_ASSERT(type == instant.type);
+ DBUG_ASSERT(trx_id_offset == instant.trx_id_offset);
+ DBUG_ASSERT(n_user_defined_cols == instant.n_user_defined_cols);
+ DBUG_ASSERT(n_uniq == instant.n_uniq);
+ DBUG_ASSERT(instant.n_fields >= n_fields);
+ DBUG_ASSERT(instant.n_nullable >= n_nullable);
+ /* dict_table_t::prepare_instant() initialized n_core_fields
+ to be equal. However, after that purge could have emptied the
+ table and invoked dict_index_t::clear_instant_alter(). */
+ DBUG_ASSERT(instant.n_core_fields <= n_core_fields);
+ DBUG_ASSERT(instant.n_core_null_bytes <= n_core_null_bytes);
+ DBUG_ASSERT(instant.n_core_fields == n_core_fields
+ || (!is_instant() && instant.is_instant()));
+ DBUG_ASSERT(instant.n_core_null_bytes == n_core_null_bytes
+ || (!is_instant() && instant.is_instant()));
+
+ /* instant will have all fields (including ones for columns
+ that have been or are being instantly dropped) in the same position
+ as this index. Fields for any added columns are appended at the end. */
+#ifndef DBUG_OFF
+ for (unsigned i = 0; i < n_fields; i++) {
+ DBUG_ASSERT(fields[i].same(instant.fields[i]));
+ DBUG_ASSERT(instant.fields[i].col->same_format(*fields[i]
+ .col));
+ /* Instant conversion from NULL to NOT NULL is not allowed. */
+ DBUG_ASSERT(!fields[i].col->is_nullable()
+ || instant.fields[i].col->is_nullable());
+ DBUG_ASSERT(fields[i].col->is_nullable()
+ == instant.fields[i].col->is_nullable()
+ || !table->not_redundant());
+ }
+#endif
+ n_fields = instant.n_fields;
+ n_def = instant.n_def;
+ n_nullable = instant.n_nullable;
+ fields = static_cast<dict_field_t*>(
+ mem_heap_dup(heap, instant.fields, n_fields * sizeof *fields));
+
+ ut_d(unsigned n_null = 0);
+ ut_d(unsigned n_dropped = 0);
+
+ for (unsigned i = 0; i < n_fields; i++) {
+ const dict_col_t* icol = instant.fields[i].col;
+ dict_field_t& f = fields[i];
+ ut_d(n_null += icol->is_nullable());
+ DBUG_ASSERT(!icol->is_virtual());
+ if (icol->is_dropped()) {
+ ut_d(n_dropped++);
+ f.col->set_dropped();
+ f.name = NULL;
+ } else {
+ f.col = &table->cols[icol - instant.table->cols];
+ f.name = f.col->name(*table);
+ }
+ }
+
+ ut_ad(n_null == n_nullable);
+ ut_ad(n_dropped == instant.table->n_dropped());
+}
+
+/** Adjust table metadata for instant ADD/DROP/reorder COLUMN.
+@param[in] table altered table (with dropped columns)
+@param[in] col_map mapping from cols[] and v_cols[] to table
+@return whether the metadata record must be updated */
+inline bool dict_table_t::instant_column(const dict_table_t& table,
+ const ulint* col_map)
+{
+ DBUG_ASSERT(!table.cached);
+ DBUG_ASSERT(table.n_def == table.n_cols);
+ DBUG_ASSERT(table.n_t_def == table.n_t_cols);
+ DBUG_ASSERT(n_def == n_cols);
+ DBUG_ASSERT(n_t_def == n_t_cols);
+ DBUG_ASSERT(n_v_def == n_v_cols);
+ DBUG_ASSERT(table.n_v_def == table.n_v_cols);
+ DBUG_ASSERT(table.n_cols + table.n_dropped() >= n_cols + n_dropped());
+ DBUG_ASSERT(!table.persistent_autoinc
+ || persistent_autoinc == table.persistent_autoinc);
+ ut_ad(mutex_own(&dict_sys.mutex));
+
+ {
+ const char* end = table.col_names;
+ for (unsigned i = table.n_cols; i--; ) end += strlen(end) + 1;
+
+ col_names = static_cast<char*>(
+ mem_heap_dup(heap, table.col_names,
+ ulint(end - table.col_names)));
+ }
+ const dict_col_t* const old_cols = cols;
+ cols = static_cast<dict_col_t*>(mem_heap_dup(heap, table.cols,
+ table.n_cols
+ * sizeof *cols));
+
+ /* Preserve the default values of previously instantly added
+ columns, or copy the new default values to this->heap. */
+ for (ulint i = 0; i < ulint(table.n_cols); i++) {
+ dict_col_t& c = cols[i];
+
+ if (const dict_col_t* o = find(old_cols, col_map, n_cols, i)) {
+ c.def_val = o->def_val;
+ DBUG_ASSERT(!((c.prtype ^ o->prtype)
+ & ~(DATA_NOT_NULL | DATA_VERSIONED
+ | CHAR_COLL_MASK << 16
+ | DATA_LONG_TRUE_VARCHAR)));
+ DBUG_ASSERT(c.same_type(*o));
+ DBUG_ASSERT(c.len >= o->len);
+
+ if (o->vers_sys_start()) {
+ ut_ad(o->ind == vers_start);
+ vers_start = i;
+ } else if (o->vers_sys_end()) {
+ ut_ad(o->ind == vers_end);
+ vers_end = i;
+ }
+ continue;
+ }
+
+ DBUG_ASSERT(c.is_added());
+ if (c.def_val.len <= sizeof field_ref_zero
+ && (!c.def_val.len
+ || !memcmp(c.def_val.data, field_ref_zero,
+ c.def_val.len))) {
+ c.def_val.data = field_ref_zero;
+ } else if (const void*& d = c.def_val.data) {
+ d = mem_heap_dup(heap, d, c.def_val.len);
+ } else {
+ DBUG_ASSERT(c.def_val.len == UNIV_SQL_NULL);
+ }
+ }
+
+ n_t_def += table.n_cols - n_cols;
+ n_t_cols += table.n_cols - n_cols;
+ n_def = table.n_cols;
+
+ const dict_v_col_t* const old_v_cols = v_cols;
+
+ if (const char* end = table.v_col_names) {
+ for (unsigned i = table.n_v_cols; i--; ) {
+ end += strlen(end) + 1;
+ }
+
+ v_col_names = static_cast<char*>(
+ mem_heap_dup(heap, table.v_col_names,
+ ulint(end - table.v_col_names)));
+ v_cols = static_cast<dict_v_col_t*>(
+ mem_heap_dup(heap, table.v_cols,
+ table.n_v_cols * sizeof *v_cols));
+ } else {
+ ut_ad(table.n_v_cols == 0);
+ v_col_names = NULL;
+ v_cols = NULL;
+ }
+
+ n_t_def += table.n_v_cols - n_v_cols;
+ n_t_cols += table.n_v_cols - n_v_cols;
+ n_v_def = table.n_v_cols;
+
+ for (unsigned i = 0; i < n_v_def; i++) {
+ dict_v_col_t& v = v_cols[i];
+ DBUG_ASSERT(v.v_indexes.empty());
+ v.n_v_indexes = 0;
+ v.base_col = static_cast<dict_col_t**>(
+ mem_heap_dup(heap, v.base_col,
+ v.num_base * sizeof *v.base_col));
+
+ for (ulint n = v.num_base; n--; ) {
+ dict_col_t*& base = v.base_col[n];
+ if (base->is_virtual()) {
+ } else if (base >= table.cols
+ && base < table.cols + table.n_cols) {
+ /* The base column was instantly added. */
+ size_t c = base - table.cols;
+ DBUG_ASSERT(base == &table.cols[c]);
+ base = &cols[c];
+ } else {
+ DBUG_ASSERT(base >= old_cols);
+ size_t c = base - old_cols;
+ DBUG_ASSERT(c + DATA_N_SYS_COLS < n_cols);
+ DBUG_ASSERT(base == &old_cols[c]);
+ DBUG_ASSERT(col_map[c] + DATA_N_SYS_COLS
+ < n_cols);
+ base = &cols[col_map[c]];
+ }
+ }
+ }
+
+ dict_index_t* index = dict_table_get_first_index(this);
+ bool metadata_changed;
+ {
+ const dict_index_t& i = *dict_table_get_first_index(&table);
+ metadata_changed = i.n_fields > index->n_fields;
+ ut_ad(i.n_fields >= index->n_fields);
+ index->instant_add_field(i);
+ }
+
+ if (instant || table.instant) {
+ const auto old_instant = instant;
+ /* FIXME: add instant->heap, and transfer ownership here */
+ if (!instant) {
+ instant = new (mem_heap_zalloc(heap, sizeof *instant))
+ dict_instant_t();
+ goto dup_dropped;
+ } else if (n_dropped() < table.n_dropped()) {
+dup_dropped:
+ instant->dropped = static_cast<dict_col_t*>(
+ mem_heap_dup(heap, table.instant->dropped,
+ table.instant->n_dropped
+ * sizeof *instant->dropped));
+ instant->n_dropped = table.instant->n_dropped;
+ } else if (table.instant->n_dropped) {
+ memcpy(instant->dropped, table.instant->dropped,
+ table.instant->n_dropped
+ * sizeof *instant->dropped);
+ }
+
+ const field_map_element_t* field_map = old_instant
+ ? old_instant->field_map : NULL;
+
+ init_instant(table);
+
+ if (!metadata_changed) {
+ metadata_changed = !field_map
+ || memcmp(field_map,
+ instant->field_map,
+ (index->n_fields
+ - index->first_user_field())
+ * sizeof *field_map);
+ }
+ }
+
+ while ((index = dict_table_get_next_index(index)) != NULL) {
+ if (index->to_be_dropped) {
+ continue;
+ }
+ for (unsigned i = 0; i < index->n_fields; i++) {
+ dict_field_t& f = index->fields[i];
+ if (f.col >= table.cols
+ && f.col < table.cols + table.n_cols) {
+ /* This is an instantly added column
+ in a newly added index. */
+ DBUG_ASSERT(!f.col->is_virtual());
+ size_t c = f.col - table.cols;
+ DBUG_ASSERT(f.col == &table.cols[c]);
+ f.col = &cols[c];
+ } else if (f.col >= &table.v_cols->m_col
+ && f.col < &table.v_cols[n_v_cols].m_col) {
+ /* This is an instantly added virtual column
+ in a newly added index. */
+ DBUG_ASSERT(f.col->is_virtual());
+ size_t c = reinterpret_cast<dict_v_col_t*>(
+ f.col) - table.v_cols;
+ DBUG_ASSERT(f.col == &table.v_cols[c].m_col);
+ f.col = &v_cols[c].m_col;
+ } else if (f.col < old_cols
+ || f.col >= old_cols + n_cols) {
+ DBUG_ASSERT(f.col->is_virtual());
+ f.col = &v_cols[col_map[
+ reinterpret_cast<dict_v_col_t*>(
+ f.col)
+ - old_v_cols + n_cols]].m_col;
+ } else {
+ f.col = &cols[col_map[f.col - old_cols]];
+ DBUG_ASSERT(!f.col->is_virtual());
+ }
+ f.name = f.col->name(*this);
+ if (f.col->is_virtual()) {
+ dict_v_col_t* v_col = reinterpret_cast
+ <dict_v_col_t*>(f.col);
+ v_col->v_indexes.push_front(
+ dict_v_idx_t(index, i));
+ v_col->n_v_indexes++;
+ }
+ }
+ }
+
+ n_cols = table.n_cols;
+ n_v_cols = table.n_v_cols;
+ return metadata_changed;
+}
+
+/** Find the old column number for the given new column position.
+@param[in] col_map column map from old column to new column
+@param[in] pos new column position
+@param[in] n number of columns present in the column map
+@return old column position for the given new column position. */
+static ulint find_old_col_no(const ulint* col_map, ulint pos, ulint n)
+{
+ do {
+ ut_ad(n);
+ } while (col_map[--n] != pos);
+ return n;
+}
+
+/** Roll back instant_column().
+@param[in] old_n_cols original n_cols
+@param[in] old_cols original cols
+@param[in] old_col_names original col_names
+@param[in] old_instant original instant structure
+@param[in] old_fields original fields
+@param[in] old_n_fields original number of fields
+@param[in] old_n_core_fields original number of core fields
+@param[in] old_n_v_cols original n_v_cols
+@param[in] old_v_cols original v_cols
+@param[in] old_v_col_names original v_col_names
+@param[in] col_map column map */
+inline void dict_table_t::rollback_instant(
+ unsigned old_n_cols,
+ dict_col_t* old_cols,
+ const char* old_col_names,
+ dict_instant_t* old_instant,
+ dict_field_t* old_fields,
+ unsigned old_n_fields,
+ unsigned old_n_core_fields,
+ unsigned old_n_v_cols,
+ dict_v_col_t* old_v_cols,
+ const char* old_v_col_names,
+ const ulint* col_map)
+{
+ ut_d(dict_sys.assert_locked());
+ dict_index_t* index = indexes.start;
+ mtr_t mtr;
+ mtr.start();
+ /* Prevent concurrent execution of dict_index_t::clear_instant_alter()
+ by acquiring a latch on the leftmost leaf page. */
+ instant_metadata_lock(*index, mtr);
+ /* index->is_instant() does not necessarily hold here, because
+ the table may have been emptied */
+ DBUG_ASSERT(old_n_cols >= DATA_N_SYS_COLS);
+ DBUG_ASSERT(n_cols == n_def);
+ DBUG_ASSERT(index->n_def == index->n_fields);
+ DBUG_ASSERT(index->n_core_fields <= index->n_fields);
+ DBUG_ASSERT(old_n_core_fields <= old_n_fields);
+ DBUG_ASSERT(instant || !old_instant);
+
+ instant = old_instant;
+
+ index->n_nullable = 0;
+
+ for (unsigned i = old_n_fields; i--; ) {
+ if (old_fields[i].col->is_nullable()) {
+ index->n_nullable++;
+ }
+ }
+
+ for (unsigned i = n_v_cols; i--; ) {
+ v_cols[i].~dict_v_col_t();
+ }
+
+ index->n_core_fields = (index->n_fields == index->n_core_fields)
+ ? old_n_fields
+ : old_n_core_fields;
+ index->n_def = index->n_fields = old_n_fields;
+ index->n_core_null_bytes = UT_BITS_IN_BYTES(
+ index->get_n_nullable(index->n_core_fields));
+
+ const dict_col_t* const new_cols = cols;
+ const dict_col_t* const new_cols_end __attribute__((unused)) = cols + n_cols;
+ const dict_v_col_t* const new_v_cols = v_cols;
+ const dict_v_col_t* const new_v_cols_end __attribute__((unused))= v_cols + n_v_cols;
+
+ cols = old_cols;
+ col_names = old_col_names;
+ v_cols = old_v_cols;
+ v_col_names = old_v_col_names;
+ n_def = n_cols = old_n_cols;
+ n_v_def = n_v_cols = old_n_v_cols;
+ n_t_def = n_t_cols = n_cols + n_v_cols;
+
+ if (versioned()) {
+ for (unsigned i = 0; i < n_cols; ++i) {
+ if (cols[i].vers_sys_start()) {
+ vers_start = i;
+ } else if (cols[i].vers_sys_end()) {
+ vers_end = i;
+ }
+ }
+ }
+
+ index->fields = old_fields;
+ mtr.commit();
+
+ while ((index = dict_table_get_next_index(index)) != NULL) {
+ if (index->to_be_dropped) {
+ /* instant_column() did not adjust these indexes. */
+ continue;
+ }
+
+ for (unsigned i = 0; i < index->n_fields; i++) {
+ dict_field_t& f = index->fields[i];
+ if (f.col->is_virtual()) {
+ DBUG_ASSERT(f.col >= &new_v_cols->m_col);
+ DBUG_ASSERT(f.col < &new_v_cols_end->m_col);
+ size_t n = size_t(
+ reinterpret_cast<dict_v_col_t*>(f.col)
+ - new_v_cols);
+ DBUG_ASSERT(n <= n_v_cols);
+
+ ulint old_col_no = find_old_col_no(
+ col_map + n_cols, n, n_v_cols);
+ DBUG_ASSERT(old_col_no <= n_v_cols);
+ f.col = &v_cols[old_col_no].m_col;
+ DBUG_ASSERT(f.col->is_virtual());
+ } else {
+ DBUG_ASSERT(f.col >= new_cols);
+ DBUG_ASSERT(f.col < new_cols_end);
+ size_t n = size_t(f.col - new_cols);
+ DBUG_ASSERT(n <= n_cols);
+
+ ulint old_col_no = find_old_col_no(col_map,
+ n, n_cols);
+ DBUG_ASSERT(old_col_no < n_cols);
+ f.col = &cols[old_col_no];
+ DBUG_ASSERT(!f.col->is_virtual());
+ }
+ f.name = f.col->name(*this);
+ }
+ }
+}
+
struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
{
/** Dummy query graph */
@@ -164,10 +878,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
dict_index_t** drop_index;
/** number of InnoDB indexes being dropped */
const ulint num_to_drop_index;
- /** InnoDB indexes being renamed */
- dict_index_t** rename;
- /** number of InnoDB indexes being renamed */
- const ulint num_to_rename;
/** InnoDB foreign key constraints being dropped */
dict_foreign_t** drop_fk;
/** number of InnoDB foreign key constraints being dropped */
@@ -186,7 +896,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
dict_table_t* old_table;
/** table where the indexes are being created or dropped */
dict_table_t* new_table;
- /** table definition for instant ADD COLUMN */
+ /** table definition for instant ADD/DROP/reorder COLUMN */
dict_table_t* instant_table;
/** mapping of old column numbers to new ones, or NULL */
const ulint* col_map;
@@ -220,7 +930,22 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
dict_col_t* const old_cols;
/** original column names of the table */
const char* const old_col_names;
-
+ /** original instantly dropped or reordered columns */
+ dict_instant_t* const old_instant;
+ /** original index fields */
+ dict_field_t* const old_fields;
+ /** size of old_fields */
+ const unsigned old_n_fields;
+ /** original old_table->n_core_fields */
+ const unsigned old_n_core_fields;
+ /** original number of virtual columns in the table */
+ const unsigned old_n_v_cols;
+ /** original virtual columns of the table */
+ dict_v_col_t* const old_v_cols;
+ /** original virtual column names of the table */
+ const char* const old_v_col_names;
+ /** 0, or 1 + first column whose position changes in instant ALTER */
+ unsigned first_alter_pos;
/** Allow non-null conversion.
(1) Alter ignore should allow the conversion
irrespective of sql mode.
@@ -234,8 +959,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg,
dict_index_t** drop_arg,
ulint num_to_drop_arg,
- dict_index_t** rename_arg,
- ulint num_to_rename_arg,
dict_foreign_t** drop_fk_arg,
ulint num_to_drop_fk_arg,
dict_foreign_t** add_fk_arg,
@@ -254,7 +977,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
prebuilt (prebuilt_arg),
add_index (0), add_key_numbers (0), num_to_add_index (0),
drop_index (drop_arg), num_to_drop_index (num_to_drop_arg),
- rename (rename_arg), num_to_rename (num_to_rename_arg),
drop_fk (drop_fk_arg), num_to_drop_fk (num_to_drop_fk_arg),
add_fk (add_fk_arg), num_to_add_fk (num_to_add_fk_arg),
online (online_arg), heap (heap_arg), trx (0),
@@ -277,6 +999,15 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
old_n_cols(prebuilt_arg->table->n_cols),
old_cols(prebuilt_arg->table->cols),
old_col_names(prebuilt_arg->table->col_names),
+ old_instant(prebuilt_arg->table->instant),
+ old_fields(prebuilt_arg->table->indexes.start->fields),
+ old_n_fields(prebuilt_arg->table->indexes.start->n_fields),
+ old_n_core_fields(prebuilt_arg->table->indexes.start
+ ->n_core_fields),
+ old_n_v_cols(prebuilt_arg->table->n_v_cols),
+ old_v_cols(prebuilt_arg->table->v_cols),
+ old_v_col_names(prebuilt_arg->table->v_col_names),
+ first_alter_pos(0),
allow_not_null(allow_not_null_flag),
page_compression_level(page_compressed
? (page_compression_level_arg
@@ -310,6 +1041,9 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
rw_lock_free(&index->lock);
dict_mem_index_free(index);
}
+ for (unsigned i = old_n_v_cols; i--; ) {
+ old_v_cols[i].~dict_v_col_t();
+ }
if (instant_table->fts) {
fts_free(instant_table);
}
@@ -337,14 +1071,24 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
{
DBUG_ASSERT(need_rebuild());
DBUG_ASSERT(!is_instant());
- DBUG_ASSERT(old_table->n_cols == old_table->n_def);
- DBUG_ASSERT(new_table->n_cols == new_table->n_def);
DBUG_ASSERT(old_table->n_cols == old_n_cols);
- DBUG_ASSERT(new_table->n_cols > old_table->n_cols);
- instant_table = new_table;
+ instant_table = new_table;
new_table = old_table;
export_vars.innodb_instant_alter_column++;
+
+ instant_table->prepare_instant(*old_table, col_map,
+ first_alter_pos);
+ }
+
+ /** Adjust table metadata for instant ADD/DROP/reorder COLUMN.
+ @return whether the metadata record must be updated */
+ bool instant_column()
+ {
+ DBUG_ASSERT(is_instant());
+ DBUG_ASSERT(old_n_fields
+ == old_table->indexes.start->n_fields);
+ return old_table->instant_column(*instant_table, col_map);
}
/** Revert prepare_instant() if the transaction is rolled back. */
@@ -352,7 +1096,13 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
{
if (!is_instant()) return;
old_table->rollback_instant(old_n_cols,
- old_cols, old_col_names);
+ old_cols, old_col_names,
+ old_instant,
+ old_fields, old_n_fields,
+ old_n_core_fields,
+ old_n_v_cols, old_v_cols,
+ old_v_col_names,
+ col_map);
}
/** @return whether this is instant ALTER TABLE */
@@ -362,6 +1112,40 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
return instant_table;
}
+ /** Create an index table where indexes are ordered as follows:
+
+ IF a new primary key is defined for the table THEN
+
+ 1) New primary key
+ 2) The remaining keys in key_info
+
+ ELSE
+
+ 1) All new indexes in the order they arrive from MySQL
+
+ ENDIF
+
+ @return key definitions */
+ MY_ATTRIBUTE((nonnull, warn_unused_result, malloc))
+ inline index_def_t*
+ create_key_defs(
+ const Alter_inplace_info* ha_alter_info,
+ /*!< in: alter operation */
+ const TABLE* altered_table,
+ /*!< in: MySQL table that is being altered */
+ ulint& n_fts_add,
+ /*!< out: number of FTS indexes to be created */
+ ulint& fts_doc_id_col,
+ /*!< in: The column number for Doc ID */
+ bool& add_fts_doc_id,
+ /*!< in: whether we need to add new DOC ID
+ column for FTS index */
+ bool& add_fts_doc_idx,
+ /*!< in: whether we need to add new DOC ID
+ index for FTS index */
+ const TABLE* table);
+ /*!< in: MySQL table that is being altered */
+
/** Share context between partitions.
@param[in] ctx context from another partition of the table */
void set_shared_data(const inplace_alter_handler_ctx& ctx)
@@ -620,18 +1404,14 @@ check_v_col_in_order(
& ALTER_ADD_VIRTUAL_COLUMN) {
bool has_new = false;
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
-
- cf_it.rewind();
-
- while (const Create_field* new_field = cf_it++) {
- if (new_field->stored_in_db()) {
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
+ if (new_field.stored_in_db()) {
continue;
}
/* Found a new added virtual column. */
- if (!new_field->field) {
+ if (!new_field.field) {
has_new = true;
continue;
}
@@ -695,20 +1475,237 @@ check_v_col_in_order(
}
/** Determine if an instant operation is possible for altering columns.
+@param[in] ib_table InnoDB table definition
@param[in] ha_alter_info the ALTER TABLE operation
-@param[in] table table definition before ALTER TABLE */
+@param[in] table table definition before ALTER TABLE
+@param[in] altered_table table definition after ALTER TABLE
+@param[in] strict whether to ensure that user records fit */
static
bool
instant_alter_column_possible(
+ const dict_table_t& ib_table,
const Alter_inplace_info* ha_alter_info,
- const TABLE* table)
+ const TABLE* table,
+ const TABLE* altered_table,
+ bool strict)
{
+ const dict_index_t* const pk = ib_table.indexes.start;
+ ut_ad(pk->is_primary());
+ ut_ad(!pk->has_virtual());
+
+ if (ha_alter_info->handler_flags
+ & (ALTER_STORED_COLUMN_ORDER | ALTER_DROP_STORED_COLUMN
+ | ALTER_ADD_STORED_BASE_COLUMN)) {
+#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
+ if (ib_table.fts || innobase_fulltext_exist(altered_table))
+ return false;
+#endif
+#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
+ for (const dict_index_t* index = ib_table.indexes.start;
+ index; index = index->indexes.next) {
+ if (index->has_virtual()) {
+ ut_ad(ib_table.n_v_cols);
+ return false;
+ }
+ }
+#endif
+ uint n_add = 0, n_nullable = 0, lenlen = 0;
+ const uint blob_prefix = dict_table_has_atomic_blobs(&ib_table)
+ ? 0
+ : REC_ANTELOPE_MAX_INDEX_COL_LEN;
+ const uint min_local_len = blob_prefix
+ ? blob_prefix + FIELD_REF_SIZE
+ : 2 * FIELD_REF_SIZE;
+ size_t min_size = 0, max_size = 0;
+ Field** af = altered_table->field;
+ Field** const end = altered_table->field
+ + altered_table->s->fields;
+ List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list);
+
+ for (; af < end; af++) {
+ const Create_field* cf = cf_it++;
+ if (!(*af)->stored_in_db() || cf->field) {
+ /* Virtual or pre-existing column */
+ continue;
+ }
+ const bool nullable = (*af)->real_maybe_null();
+ const bool is_null = (*af)->is_real_null();
+ ut_ad(!is_null || nullable);
+ n_nullable += nullable;
+ n_add++;
+ uint l;
+ switch ((*af)->type()) {
+ case MYSQL_TYPE_VARCHAR:
+ l = reinterpret_cast<const Field_varstring*>
+ (*af)->get_length();
+ variable_length:
+ if (l >= min_local_len) {
+ max_size += blob_prefix
+ + FIELD_REF_SIZE;
+ if (!is_null) {
+ min_size += blob_prefix
+ + FIELD_REF_SIZE;
+ }
+ lenlen += 2;
+ } else {
+ if (!is_null) {
+ min_size += l;
+ }
+ l = (*af)->pack_length();
+ max_size += l;
+ lenlen += l > 255 ? 2 : 1;
+ }
+ break;
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ l = reinterpret_cast<const Field_blob*>
+ ((*af))->get_length();
+ goto variable_length;
+ default:
+ l = (*af)->pack_length();
+ if (l > 255 && ib_table.not_redundant()) {
+ goto variable_length;
+ }
+ max_size += l;
+ if (!is_null) {
+ min_size += l;
+ }
+ }
+ }
+
+ ulint n_fields = pk->n_fields + n_add;
+
+ if (n_fields >= REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS) {
+ return false;
+ }
+
+ if (pk->is_gen_clust()) {
+ min_size += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN
+ + DATA_ROW_ID_LEN;
+ max_size += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN
+ + DATA_ROW_ID_LEN;
+ } else {
+ min_size += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
+ max_size += DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
+ }
+
+ uint i = pk->n_fields;
+ while (i-- > pk->n_core_fields) {
+ const dict_field_t& f = pk->fields[i];
+ if (f.col->is_nullable()) {
+ n_nullable++;
+ if (!f.col->is_dropped()
+ && f.col->def_val.data) {
+ goto instantly_added_column;
+ }
+ } else if (f.fixed_len
+ && (f.fixed_len <= 255
+ || !ib_table.not_redundant())) {
+ if (ib_table.not_redundant()
+ || !f.col->is_dropped()) {
+ min_size += f.fixed_len;
+ max_size += f.fixed_len;
+ }
+ } else if (f.col->is_dropped() || !f.col->is_added()) {
+ lenlen++;
+ goto set_max_size;
+ } else {
+instantly_added_column:
+ ut_ad(f.col->is_added());
+ if (f.col->def_val.len >= min_local_len) {
+ min_size += blob_prefix
+ + FIELD_REF_SIZE;
+ lenlen += 2;
+ } else {
+ min_size += f.col->def_val.len;
+ lenlen += f.col->def_val.len
+ > 255 ? 2 : 1;
+ }
+set_max_size:
+ if (f.fixed_len
+ && (f.fixed_len <= 255
+ || !ib_table.not_redundant())) {
+ max_size += f.fixed_len;
+ } else if (f.col->len >= min_local_len) {
+ max_size += blob_prefix
+ + FIELD_REF_SIZE;
+ } else {
+ max_size += f.col->len;
+ }
+ }
+ }
+
+ do {
+ const dict_field_t& f = pk->fields[i];
+ if (f.col->is_nullable()) {
+ n_nullable++;
+ } else if (f.fixed_len) {
+ min_size += f.fixed_len;
+ } else {
+ lenlen++;
+ }
+ } while (i--);
+
+ if (ib_table.instant
+ || (ha_alter_info->handler_flags
+ & (ALTER_STORED_COLUMN_ORDER
+ | ALTER_DROP_STORED_COLUMN))) {
+ n_fields++;
+ lenlen += 2;
+ min_size += FIELD_REF_SIZE;
+ }
+
+ if (ib_table.not_redundant()) {
+ min_size += REC_N_NEW_EXTRA_BYTES
+ + UT_BITS_IN_BYTES(n_nullable)
+ + lenlen;
+ } else {
+ min_size += (n_fields > 255 || min_size > 255)
+ ? n_fields * 2 : n_fields;
+ min_size += REC_N_OLD_EXTRA_BYTES;
+ }
+
+ if (page_zip_rec_needs_ext(min_size, ib_table.not_redundant(),
+ 0, 0)) {
+ return false;
+ }
+
+ if (strict && page_zip_rec_needs_ext(max_size,
+ ib_table.not_redundant(),
+ 0, 0)) {
+ return false;
+ }
+ }
// Making table system-versioned instantly is not implemented yet.
if (ha_alter_info->handler_flags & ALTER_ADD_SYSTEM_VERSIONING) {
return false;
}
- if (~ha_alter_info->handler_flags & ALTER_ADD_STORED_BASE_COLUMN) {
+ static constexpr alter_table_operations avoid_rebuild
+ = ALTER_ADD_STORED_BASE_COLUMN
+ | ALTER_DROP_STORED_COLUMN
+ | ALTER_STORED_COLUMN_ORDER
+ | ALTER_COLUMN_NULLABLE;
+
+ if (!(ha_alter_info->handler_flags & avoid_rebuild)) {
+ alter_table_operations flags = ha_alter_info->handler_flags
+ & ~avoid_rebuild;
+ /* None of the flags are set that we can handle
+ specially to avoid rebuild. In this case, we can
+ allow ALGORITHM=INSTANT, except if some requested
+ operation requires that the table be rebuilt. */
+ if (flags & INNOBASE_ALTER_REBUILD) {
+ return false;
+ }
+ if ((flags & ALTER_OPTIONS)
+ && alter_options_need_rebuild(ha_alter_info, table)) {
+ return false;
+ }
+ } else if (!ib_table.supports_instant()) {
return false;
}
@@ -731,12 +1728,59 @@ instant_alter_column_possible(
columns. */
if (ha_alter_info->handler_flags
& ((INNOBASE_ALTER_REBUILD | INNOBASE_ONLINE_CREATE)
- & ~ALTER_ADD_STORED_BASE_COLUMN & ~ALTER_OPTIONS)) {
+ & ~ALTER_DROP_STORED_COLUMN
+ & ~ALTER_STORED_COLUMN_ORDER
+ & ~ALTER_ADD_STORED_BASE_COLUMN
+ & ~ALTER_COLUMN_NULLABLE
+ & ~ALTER_OPTIONS)) {
+ return false;
+ }
+
+ if ((ha_alter_info->handler_flags & ALTER_OPTIONS)
+ && alter_options_need_rebuild(ha_alter_info, table)) {
return false;
}
- return !(ha_alter_info->handler_flags & ALTER_OPTIONS)
- || !alter_options_need_rebuild(ha_alter_info, table);
+ if (ha_alter_info->handler_flags & ALTER_COLUMN_NULLABLE) {
+ if (ib_table.not_redundant()) {
+ /* Instantaneous removal of NOT NULL is
+ only supported for ROW_FORMAT=REDUNDANT. */
+ return false;
+ }
+ if (ib_table.fts_doc_id_index
+ && !innobase_fulltext_exist(altered_table)) {
+ /* Removing hidden FTS_DOC_ID_INDEX(FTS_DOC_ID)
+ requires that the table be rebuilt. */
+ return false;
+ }
+
+ Field** af = altered_table->field;
+ Field** const end = altered_table->field
+ + altered_table->s->fields;
+ for (unsigned c = 0; af < end; af++) {
+ if (!(*af)->stored_in_db()) {
+ continue;
+ }
+
+ const dict_col_t* col = dict_table_get_nth_col(
+ &ib_table, c++);
+
+ if (!col->ord_part || col->is_nullable()
+ || !(*af)->real_maybe_null()) {
+ continue;
+ }
+
+ /* The column would be changed from NOT NULL.
+ Ensure that it is not a clustered index key. */
+ for (auto i = pk->n_uniq; i--; ) {
+ if (pk->fields[i].col == col) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
}
/** Check whether the non-const default value for the field
@@ -959,10 +2003,13 @@ ha_innobase::check_if_supported_inplace_alter(
switch (innodb_instant_alter_column_allowed) {
case 0: /* never */
if ((ha_alter_info->handler_flags
- & ALTER_ADD_STORED_BASE_COLUMN)
+ & (ALTER_ADD_STORED_BASE_COLUMN
+ | ALTER_STORED_COLUMN_ORDER
+ | ALTER_DROP_STORED_COLUMN))
|| m_prebuilt->table->is_instant()) {
reason_rebuild =
"innodb_instant_alter_column_allowed=never";
+innodb_instant_alter_column_allowed_reason:
if (ha_alter_info->handler_flags
& ALTER_RECREATE_TABLE) {
reason_rebuild = NULL;
@@ -974,6 +2021,14 @@ ha_innobase::check_if_supported_inplace_alter(
}
}
break;
+ case 1: /* add_last */
+ if ((ha_alter_info->handler_flags
+ & (ALTER_STORED_COLUMN_ORDER | ALTER_DROP_STORED_COLUMN))
+ || m_prebuilt->table->instant) {
+ reason_rebuild = "innodb_instant_atler_column_allowed="
+ "add_last";
+ goto innodb_instant_alter_column_allowed_reason;
+ }
}
switch (ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) {
@@ -1078,55 +2133,16 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
- bool add_drop_v_cols = false;
-
- /* If there is add or drop virtual columns, we will support operations
- with these 2 options alone with inplace interface for now */
-
- if (ha_alter_info->handler_flags
- & (ALTER_ADD_VIRTUAL_COLUMN
- | ALTER_DROP_VIRTUAL_COLUMN
- | ALTER_VIRTUAL_COLUMN_ORDER)) {
- ulonglong flags = ha_alter_info->handler_flags;
-
- /* TODO: uncomment the flags below, once we start to
- support them */
-
- flags &= ~(ALTER_ADD_VIRTUAL_COLUMN
- | ALTER_DROP_VIRTUAL_COLUMN
- | ALTER_VIRTUAL_COLUMN_ORDER
- | ALTER_VIRTUAL_GCOL_EXPR
- | ALTER_COLUMN_VCOL
- /*
- | ALTER_ADD_STORED_BASE_COLUMN
- | ALTER_DROP_STORED_COLUMN
- | ALTER_STORED_COLUMN_ORDER
- | ALTER_ADD_UNIQUE_INDEX
- */
- | ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX
- | ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX);
-
- if (flags != 0
- || IF_PARTITIONING((altered_table->s->partition_info_str
- && altered_table->s->partition_info_str_len), 0)
- || (!check_v_col_in_order(
- this->table, altered_table, ha_alter_info))) {
- ha_alter_info->unsupported_reason =
- MSG_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN;
- DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
- }
-
- add_drop_v_cols = true;
- }
+ const bool add_drop_v_cols = !!(ha_alter_info->handler_flags
+ & (ALTER_ADD_VIRTUAL_COLUMN
+ | ALTER_DROP_VIRTUAL_COLUMN
+ | ALTER_VIRTUAL_COLUMN_ORDER));
/* We should be able to do the operation in-place.
See if we can do it online (LOCK=NONE) or without rebuild. */
bool online = true, need_rebuild = false;
const uint fulltext_indexes = innobase_fulltext_exist(altered_table);
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
-
/* Fix the key parts. */
for (KEY* new_key = ha_alter_info->key_info_buffer;
new_key < ha_alter_info->key_info_buffer
@@ -1147,18 +2163,12 @@ ha_innobase::check_if_supported_inplace_alter(
key_part < (new_key->key_part
+ new_key->user_defined_key_parts);
key_part++) {
- const Create_field* new_field;
-
DBUG_ASSERT(key_part->fieldnr
< altered_table->s->fields);
- cf_it.rewind();
- for (uint fieldnr = 0; (new_field = cf_it++);
- fieldnr++) {
- if (fieldnr == key_part->fieldnr) {
- break;
- }
- }
+ const Create_field* new_field
+ = ha_alter_info->alter_info->create_list.elem(
+ key_part->fieldnr);
DBUG_ASSERT(new_field);
@@ -1285,17 +2295,17 @@ ha_innobase::check_if_supported_inplace_alter(
DEFAULT value, ensure that the DEFAULT expression is a constant.
Also, in ADD COLUMN, for now we only support a
constant DEFAULT expression. */
- cf_it.rewind();
Field **af = altered_table->field;
- bool add_column_not_last = false;
- uint n_stored_cols = 0, n_add_cols = 0;
+ bool fts_need_rebuild = false;
+ need_rebuild = need_rebuild
+ || innobase_need_rebuild(ha_alter_info, table);
- while (Create_field* cf = cf_it++) {
- DBUG_ASSERT(cf->field
+ for (Create_field& cf : ha_alter_info->alter_info->create_list) {
+ DBUG_ASSERT(cf.field
|| (ha_alter_info->handler_flags
& ALTER_ADD_COLUMN));
- if (const Field* f = cf->field) {
+ if (const Field* f = cf.field) {
if (!f->real_maybe_null() || (*af)->real_maybe_null())
goto next_column;
/* We are changing an existing column
@@ -1337,43 +2347,73 @@ ha_innobase::check_if_supported_inplace_alter(
ha_alter_info->unsupported_reason = my_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_NOT_NULL);
- } else if (!is_non_const_value(*af)) {
-
- n_add_cols++;
-
- if (af < &altered_table->field[table_share->fields]) {
- add_column_not_last = true;
- }
-
- if (set_default_value(*af)) {
- goto next_column;
+ } else if (!is_non_const_value(*af)
+ && set_default_value(*af)) {
+ if (fulltext_indexes > 1
+ && !my_strcasecmp(system_charset_info,
+ (*af)->field_name.str,
+ FTS_DOC_ID_COL_NAME)) {
+ /* If a hidden FTS_DOC_ID column exists
+ (because of FULLTEXT INDEX), it cannot
+ be replaced with a user-created one
+ except when using ALGORITHM=COPY. */
+ ha_alter_info->unsupported_reason =
+ my_get_err_msg(ER_INNODB_FT_LIMIT);
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
+ goto next_column;
}
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
next_column:
- n_stored_cols += (*af++)->stored_in_db();
+ af++;
}
- if (!add_column_not_last
- && uint(m_prebuilt->table->n_cols) - DATA_N_SYS_COLS + n_add_cols
- == n_stored_cols
- && m_prebuilt->table->supports_instant()
- && instant_alter_column_possible(ha_alter_info, table)) {
+ const bool supports_instant = instant_alter_column_possible(
+ *m_prebuilt->table, ha_alter_info, table, altered_table,
+ is_innodb_strict_mode());
+ if (add_drop_v_cols) {
+ ulonglong flags = ha_alter_info->handler_flags;
- DBUG_RETURN(HA_ALTER_INPLACE_INSTANT);
+ /* TODO: uncomment the flags below, once we start to
+ support them */
+
+ flags &= ~(ALTER_ADD_VIRTUAL_COLUMN
+ | ALTER_DROP_VIRTUAL_COLUMN
+ | ALTER_VIRTUAL_COLUMN_ORDER
+ | ALTER_VIRTUAL_GCOL_EXPR
+ | ALTER_COLUMN_VCOL
+ /*
+ | ALTER_ADD_STORED_BASE_COLUMN
+ | ALTER_DROP_STORED_COLUMN
+ | ALTER_STORED_COLUMN_ORDER
+ | ALTER_ADD_UNIQUE_INDEX
+ */
+ | ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX
+ | ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX);
+ if (supports_instant) {
+ flags &= ~(ALTER_DROP_STORED_COLUMN
+#if 0 /* MDEV-17468: remove check_v_col_in_order() and fix the code */
+ | ALTER_ADD_STORED_BASE_COLUMN
+#endif
+ | ALTER_STORED_COLUMN_ORDER);
+ }
+ if (flags != 0
+ || IF_PARTITIONING((altered_table->s->partition_info_str
+ && altered_table->s->partition_info_str_len), 0)
+ || (!check_v_col_in_order(
+ this->table, altered_table, ha_alter_info))) {
+ ha_alter_info->unsupported_reason =
+ MSG_UNSUPPORTED_ALTER_ONLINE_ON_VIRTUAL_COLUMN;
+ DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+ }
}
- if (!(ha_alter_info->handler_flags & ~(INNOBASE_ALTER_INSTANT
- | INNOBASE_INPLACE_IGNORE))) {
+ if (supports_instant) {
DBUG_RETURN(HA_ALTER_INPLACE_INSTANT);
}
- bool fts_need_rebuild = false;
- need_rebuild = need_rebuild
- || innobase_need_rebuild(ha_alter_info, table);
-
if (need_rebuild
&& (fulltext_indexes
|| innobase_spatial_exist(altered_table)
@@ -1524,7 +2564,7 @@ innobase_init_foreign(
ulint referenced_num_field) /*!< in: number of referenced
columns */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (constraint_name) {
ulint db_len;
@@ -1858,8 +2898,6 @@ innobase_get_foreign_key_info(
const trx_t* trx,
dict_s_col_list*s_cols)
{
- Key* key;
- Foreign_key* fk_key;
dict_table_t* referenced_table = NULL;
char* referenced_table_name = NULL;
ulint num_fk = 0;
@@ -1869,10 +2907,8 @@ innobase_get_foreign_key_info(
*n_add_fk = 0;
- List_iterator<Key> key_iterator(alter_info->key_list);
-
- while ((key=key_iterator++)) {
- if (key->type != Key::FOREIGN_KEY) {
+ for (Key& key : alter_info->key_list) {
+ if (key.type != Key::FOREIGN_KEY) {
continue;
}
@@ -1890,18 +2926,15 @@ innobase_get_foreign_key_info(
char db_name[MAX_DATABASE_NAME_LEN];
char tbl_name[MAX_TABLE_NAME_LEN];
- fk_key = static_cast<Foreign_key*>(key);
+ Foreign_key* fk_key = static_cast<Foreign_key*>(&key);
if (fk_key->columns.elements > 0) {
ulint i = 0;
- Key_part_spec* column;
- List_iterator<Key_part_spec> key_part_iterator(
- fk_key->columns);
/* Get all the foreign key column info for the
current table */
- while ((column = key_part_iterator++)) {
- column_names[i] = column->field_name.str;
+ for (const Key_part_spec& column : fk_key->columns) {
+ column_names[i] = column.field_name.str;
ut_ad(i < MAX_NUM_FK_COLUMNS);
i++;
}
@@ -1968,7 +3001,7 @@ innobase_get_foreign_key_info(
db_namep = &db_name[0];
}
#endif
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
referenced_table_name = dict_get_referenced_table(
table->name.m_name,
@@ -1986,7 +3019,7 @@ innobase_get_foreign_key_info(
referenced_table = NULL;);
if (!referenced_table && trx->check_foreigns) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
my_error(ER_FK_CANNOT_OPEN_PARENT,
MYF(0), tbl_namep);
@@ -1995,13 +3028,10 @@ innobase_get_foreign_key_info(
if (fk_key->ref_columns.elements > 0) {
ulint i = 0;
- Key_part_spec* column;
- List_iterator<Key_part_spec> key_part_iterator(
- fk_key->ref_columns);
- while ((column = key_part_iterator++)) {
+ for (Key_part_spec &column : fk_key->ref_columns) {
referenced_column_names[i] =
- column->field_name.str;
+ column.field_name.str;
ut_ad(i < MAX_NUM_FK_COLUMNS);
i++;
}
@@ -2022,7 +3052,7 @@ innobase_get_foreign_key_info(
/* Check whether there exist such
index in the the index create clause */
if (!referenced_index) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
my_error(ER_FK_NO_INDEX_PARENT, MYF(0),
fk_key->name.str
? fk_key->name.str : "",
@@ -2037,7 +3067,7 @@ innobase_get_foreign_key_info(
} else {
/* Not possible to add a foreign key without a
referenced column */
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
my_error(ER_CANNOT_ADD_FOREIGN, MYF(0), tbl_namep);
goto err_exit;
}
@@ -2048,7 +3078,7 @@ innobase_get_foreign_key_info(
num_col, referenced_table_name,
referenced_table, referenced_index,
referenced_column_names, referenced_num_col)) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
my_error(
ER_DUP_CONSTRAINT_NAME,
MYF(0),
@@ -2056,7 +3086,7 @@ innobase_get_foreign_key_info(
goto err_exit;
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
correct_option = innobase_set_foreign_key_option(
add_fk[num_fk], fk_key);
@@ -2336,9 +3366,9 @@ innobase_row_to_mysql(
}
}
if (table->vfield) {
- my_bitmap_map* old_vcol_set = tmp_use_all_columns(table, table->vcol_set);
+ my_bitmap_map* old_read_set = tmp_use_all_columns(table, table->read_set);
table->update_virtual_fields(table->file, VCOL_UPDATE_FOR_READ);
- tmp_restore_column_map(table->vcol_set, old_vcol_set);
+ tmp_restore_column_map(table->read_set, old_read_set);
}
}
@@ -2413,7 +3443,6 @@ innobase_check_index_keys(
}
}
-
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
key.name.str);
return(ER_WRONG_NAME_FOR_INDEX);
@@ -2766,8 +3795,7 @@ innobase_fts_check_doc_id_index_in_def(
return(FTS_NOT_EXIST_DOC_ID_INDEX);
}
-/*******************************************************************//**
-Create an index table where indexes are ordered as follows:
+/** Create an index table where indexes are ordered as follows:
IF a new primary key is defined for the table THEN
@@ -2781,23 +3809,15 @@ ELSE
ENDIF
@return key definitions */
-static MY_ATTRIBUTE((nonnull, warn_unused_result, malloc))
-index_def_t*
-innobase_create_key_defs(
-/*=====================*/
- mem_heap_t* heap,
- /*!< in/out: memory heap where space for key
- definitions are allocated */
+MY_ATTRIBUTE((nonnull, warn_unused_result, malloc))
+inline index_def_t*
+ha_innobase_inplace_ctx::create_key_defs(
const Alter_inplace_info* ha_alter_info,
/*!< in: alter operation */
const TABLE* altered_table,
/*!< in: MySQL table that is being altered */
- ulint& n_add,
- /*!< in/out: number of indexes to be created */
ulint& n_fts_add,
/*!< out: number of FTS indexes to be created */
- bool got_default_clust,
- /*!< in: whether the table lacks a primary key */
ulint& fts_doc_id_col,
/*!< in: The column number for Doc ID */
bool& add_fts_doc_id,
@@ -2809,6 +3829,9 @@ innobase_create_key_defs(
const TABLE* table)
/*!< in: MySQL table that is being altered */
{
+ ulint& n_add = num_to_add_index;
+ const bool got_default_clust = new_table->indexes.start->is_gen_clust();
+
index_def_t* indexdef;
index_def_t* indexdefs;
bool new_primary;
@@ -2817,7 +3840,7 @@ innobase_create_key_defs(
const KEY*const key_info
= ha_alter_info->key_info_buffer;
- DBUG_ENTER("innobase_create_key_defs");
+ DBUG_ENTER("ha_innobase_inplace_ctx::create_key_defs");
DBUG_ASSERT(!add_fts_doc_id || add_fts_doc_idx);
DBUG_ASSERT(ha_alter_info->index_add_count == n_add);
@@ -3000,7 +4023,7 @@ online_retry_drop_indexes_low(
dict_table_t* table, /*!< in/out: table */
trx_t* trx) /*!< in/out: transaction */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
@@ -3037,9 +4060,9 @@ online_retry_drop_indexes(
trx_free(trx);
}
- ut_d(mutex_enter(&dict_sys->mutex));
+ ut_d(mutex_enter(&dict_sys.mutex));
ut_d(dict_table_check_for_dup_indexes(table, CHECK_ALL_COMPLETE));
- ut_d(mutex_exit(&dict_sys->mutex));
+ ut_d(mutex_exit(&dict_sys.mutex));
ut_ad(!table->drop_aborted);
}
@@ -3114,7 +4137,7 @@ innobase_check_foreigns_low(
bool drop)
{
dict_foreign_t* foreign;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* Check if any FOREIGN KEY constraints are defined on this
column. */
@@ -3213,26 +4236,21 @@ innobase_check_foreigns(
dict_foreign_t** drop_fk,
ulint n_drop_fk)
{
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
-
for (Field** fp = old_table->field; *fp; fp++) {
- cf_it.rewind();
- const Create_field* new_field;
-
ut_ad(!(*fp)->real_maybe_null()
== !!((*fp)->flags & NOT_NULL_FLAG));
- while ((new_field = cf_it++)) {
- if (new_field->field == *fp) {
- break;
- }
- }
+ auto end = ha_alter_info->alter_info->create_list.end();
+ auto it = std::find_if(
+ ha_alter_info->alter_info->create_list.begin(), end,
+ [fp](const Create_field& field) {
+ return field.field == *fp;
+ });
- if (!new_field || (new_field->flags & NOT_NULL_FLAG)) {
+ if (it == end || (it->flags & NOT_NULL_FLAG)) {
if (innobase_check_foreigns_low(
user_table, drop_fk, n_drop_fk,
- (*fp)->field_name.str, !new_field)) {
+ (*fp)->field_name.str, it == end)) {
return(true);
}
}
@@ -3245,7 +4263,7 @@ innobase_check_foreigns(
@param[in,out] heap Memory heap where allocated
@param[out] dfield InnoDB data field to copy to
@param[in] field MySQL value for the column
-@param[in] old_field Old field or NULL if new col is added
+@param[in] old_field Old column if altering; NULL for ADD COLUMN
@param[in] comp nonzero if in compact format. */
static void innobase_build_col_map_add(
mem_heap_t* heap,
@@ -3264,14 +4282,13 @@ static void innobase_build_col_map_add(
return;
}
- ulint size = field->pack_length();
+ const Field& from = old_field ? *old_field : *field;
+ ulint size = from.pack_length();
byte* buf = static_cast<byte*>(mem_heap_alloc(heap, size));
- const byte* mysql_data = old_field ? old_field->ptr : field->ptr;
-
row_mysql_store_col_in_innobase_format(
- dfield, buf, true, mysql_data, size, comp);
+ dfield, buf, true, from.ptr, size, comp);
}
/** Construct the translation table for reordering, dropping or
@@ -3293,7 +4310,7 @@ innobase_build_col_map(
Alter_inplace_info* ha_alter_info,
const TABLE* altered_table,
const TABLE* table,
- const dict_table_t* new_table,
+ dict_table_t* new_table,
const dict_table_t* old_table,
dtuple_t* defaults,
mem_heap_t* heap)
@@ -3324,8 +4341,6 @@ innobase_build_col_map(
heap, (size_t(old_table->n_cols) + old_n_v_cols)
* sizeof *col_map));
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
uint i = 0;
uint num_v = 0;
@@ -3341,14 +4356,15 @@ innobase_build_col_map(
const bool omits_virtual = ha_innobase::omits_virtual_cols(*table->s);
- while (const Create_field* new_field = cf_it++) {
- bool is_v = !new_field->stored_in_db();
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
+ bool is_v = !new_field.stored_in_db();
ulint num_old_v = 0;
for (uint old_i = 0; table->field[old_i]; old_i++) {
const Field* field = table->field[old_i];
if (!field->stored_in_db()) {
- if (is_v && new_field->field == field) {
+ if (is_v && new_field.field == field) {
if (!omits_virtual) {
col_map[old_table->n_cols
+ num_v]
@@ -3361,7 +4377,7 @@ innobase_build_col_map(
continue;
}
- if (new_field->field == field) {
+ if (new_field.field == field) {
const Field* altered_field =
altered_table->field[i + num_v];
@@ -3378,16 +4394,25 @@ innobase_build_col_map(
}
col_map[old_i - num_old_v] = i;
+ if (old_table->versioned()
+ && altered_table->versioned()) {
+ if (old_i == old_table->vers_start) {
+ new_table->vers_start = i + num_v;
+ } else if (old_i == old_table->vers_end) {
+ new_table->vers_end = i + num_v;
+ }
+ }
goto found_col;
}
}
- ut_ad(!is_v);
- innobase_build_col_map_add(
- heap, dtuple_get_nth_field(defaults, i),
- altered_table->field[i + num_v],
- NULL,
- dict_table_is_comp(new_table));
+ if (!is_v) {
+ innobase_build_col_map_add(
+ heap, dtuple_get_nth_field(defaults, i),
+ altered_table->field[i + num_v],
+ NULL,
+ dict_table_is_comp(new_table));
+ }
found_col:
if (is_v) {
num_v++;
@@ -3504,21 +4529,20 @@ innobase_get_col_names(
mem_heap_zalloc(heap, user_table->n_def * sizeof *cols));
i = 0;
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
- while (const Create_field* new_field = cf_it++) {
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
ulint num_v = 0;
DBUG_ASSERT(i < altered_table->s->fields);
- if (!new_field->stored_in_db()) {
+ if (!new_field.stored_in_db()) {
continue;
}
for (uint old_i = 0; table->field[old_i]; old_i++) {
num_v += !table->field[old_i]->stored_in_db();
- if (new_field->field == table->field[old_i]) {
- cols[old_i - num_v] = new_field->field_name.str;
+ if (new_field.field == table->field[old_i]) {
+ cols[old_i - num_v] = new_field.field_name.str;
break;
}
}
@@ -3739,8 +4763,7 @@ innobase_update_gis_column_type(
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
info = pars_info_create();
@@ -3853,13 +4876,12 @@ prepare_inplace_add_virtual(
ha_innobase_inplace_ctx* ctx;
ulint i = 0;
ulint j = 0;
- const Create_field* new_field;
ctx = static_cast<ha_innobase_inplace_ctx*>
(ha_alter_info->handler_ctx);
- ctx->num_to_add_vcol = altered_table->s->fields
- + ctx->num_to_drop_vcol - table->s->fields;
+ ctx->num_to_add_vcol = altered_table->s->virtual_fields
+ + ctx->num_to_drop_vcol - table->s->virtual_fields;
ctx->add_vcol = static_cast<dict_v_col_t*>(
mem_heap_zalloc(ctx->heap, ctx->num_to_add_vcol
@@ -3868,46 +4890,22 @@ prepare_inplace_add_virtual(
mem_heap_alloc(ctx->heap, ctx->num_to_add_vcol
* sizeof *ctx->add_vcol_name));
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
+ const Field* field = altered_table->field[i++];
- while ((new_field = (cf_it++)) != NULL) {
- const Field* field = new_field->field;
- ulint old_i;
-
- for (old_i = 0; table->field[old_i]; old_i++) {
- const Field* n_field = table->field[old_i];
- if (field == n_field) {
- break;
- }
- }
-
- i++;
-
- if (table->field[old_i]) {
+ if (new_field.field || field->stored_in_db()) {
continue;
}
- ut_ad(!field);
-
- ulint col_len;
ulint is_unsigned;
- ulint field_type;
ulint charset_no;
-
- field = altered_table->field[i - 1];
-
ulint col_type
= get_innobase_type_from_mysql_type(
&is_unsigned, field);
-
- if (field->stored_in_db()) {
- continue;
- }
-
- col_len = field->pack_length();
- field_type = (ulint) field->type();
+ ulint col_len = field->pack_length();
+ ulint field_type = (ulint) field->type();
if (!field->real_maybe_null()) {
field_type |= DATA_NOT_NULL;
@@ -3949,7 +4947,7 @@ prepare_inplace_add_virtual(
}
}
-
+ new (&ctx->add_vcol[j]) dict_v_col_t();
ctx->add_vcol[j].m_col.prtype = dtype_form_prtype(
field_type, charset_no);
@@ -3966,8 +4964,8 @@ prepare_inplace_add_virtual(
ctx->add_vcol[j].v_pos = ctx->old_table->n_v_cols
- ctx->num_to_drop_vcol + j;
- /* No need to track the list */
- ctx->add_vcol[j].v_indexes = NULL;
+ ctx->add_vcol[j].n_v_indexes = 0;
+ /* MDEV-17468: Do this on ctx->instant_table later */
innodb_base_col_setup(ctx->old_table, field, &ctx->add_vcol[j]);
j++;
}
@@ -4094,33 +5092,96 @@ prepare_inplace_drop_virtual(
@param[in] pos virtual column column no
@param[in] base_pos base column pos
@param[in] trx transaction
-@return DB_SUCCESS if successful, otherwise error code */
-static
-dberr_t
-innobase_insert_sys_virtual(
+@retval false on success
+@retval true on failure (my_error() will have been called) */
+static bool innobase_insert_sys_virtual(
const dict_table_t* table,
ulint pos,
ulint base_pos,
trx_t* trx)
{
pars_info_t* info = pars_info_create();
-
pars_info_add_ull_literal(info, "id", table->id);
+ pars_info_add_int4_literal(info, "pos", pos);
+ pars_info_add_int4_literal(info, "base_pos", base_pos);
+ if (DB_SUCCESS != que_eval_sql(
+ info,
+ "PROCEDURE P () IS\n"
+ "BEGIN\n"
+ "INSERT INTO SYS_VIRTUAL VALUES (:id, :pos, :base_pos);\n"
+ "END;\n",
+ FALSE, trx)) {
+ my_error(ER_INTERNAL_ERROR, MYF(0),
+ "InnoDB: ADD COLUMN...VIRTUAL");
+ return true;
+ }
+
+ return false;
+}
+
+/** Insert a record to the SYS_COLUMNS dictionary table.
+@param[in] table_id table id
+@param[in] pos position of the column
+@param[in] field_name field name
+@param[in] mtype main type
+@param[in] prtype precise type
+@param[in] len fixed length in bytes, or 0
+@param[in] n_base number of base columns of virtual columns, or 0
+@param[in] update whether to update instead of inserting
+@retval false on success
+@retval true on failure (my_error() will have been called) */
+static bool innodb_insert_sys_columns(
+ table_id_t table_id,
+ ulint pos,
+ const char* field_name,
+ ulint mtype,
+ ulint prtype,
+ ulint len,
+ ulint n_base,
+ trx_t* trx,
+ bool update = false)
+{
+ pars_info_t* info = pars_info_create();
+ pars_info_add_ull_literal(info, "id", table_id);
pars_info_add_int4_literal(info, "pos", pos);
+ pars_info_add_str_literal(info, "name", field_name);
+ pars_info_add_int4_literal(info, "mtype", mtype);
+ pars_info_add_int4_literal(info, "prtype", prtype);
+ pars_info_add_int4_literal(info, "len", len);
+ pars_info_add_int4_literal(info, "base", n_base);
+
+ if (update) {
+ if (DB_SUCCESS != que_eval_sql(
+ info,
+ "PROCEDURE UPD_COL () IS\n"
+ "BEGIN\n"
+ "UPDATE SYS_COLUMNS SET\n"
+ "NAME=:name, MTYPE=:mtype, PRTYPE=:prtype, "
+ "LEN=:len, PREC=:base\n"
+ "WHERE TABLE_ID=:id AND POS=:pos;\n"
+ "END;\n", FALSE, trx)) {
+ my_error(ER_INTERNAL_ERROR, MYF(0),
+ "InnoDB: Updating SYS_COLUMNS failed");
+ return true;
+ }
- pars_info_add_int4_literal(info, "base_pos", base_pos);
+ return false;
+ }
- dberr_t error = que_eval_sql(
- info,
- "PROCEDURE P () IS\n"
- "BEGIN\n"
- "INSERT INTO SYS_VIRTUAL VALUES"
- "(:id, :pos, :base_pos);\n"
- "END;\n",
- FALSE, trx);
+ if (DB_SUCCESS != que_eval_sql(
+ info,
+ "PROCEDURE ADD_COL () IS\n"
+ "BEGIN\n"
+ "INSERT INTO SYS_COLUMNS VALUES"
+ "(:id,:pos,:name,:mtype,:prtype,:len,:base);\n"
+ "END;\n", FALSE, trx)) {
+ my_error(ER_INTERNAL_ERROR, MYF(0),
+ "InnoDB: Insert into SYS_COLUMNS failed");
+ return true;
+ }
- return(error);
+ return false;
}
/** Update INNODB SYS_COLUMNS on new virtual columns
@@ -4128,10 +5189,9 @@ innobase_insert_sys_virtual(
@param[in] col_name column name
@param[in] vcol virtual column
@param[in] trx transaction
-@return DB_SUCCESS if successful, otherwise error code */
-static
-dberr_t
-innobase_add_one_virtual(
+@retval false on success
+@retval true on failure (my_error() will have been called) */
+static bool innobase_add_one_virtual(
const dict_table_t* table,
const char* col_name,
dict_v_col_t* vcol,
@@ -4139,67 +5199,41 @@ innobase_add_one_virtual(
{
ulint pos = dict_create_v_col_pos(vcol->v_pos,
vcol->m_col.ind);
- ulint mtype = vcol->m_col.mtype;
- ulint prtype = vcol->m_col.prtype;
- ulint len = vcol->m_col.len;
- pars_info_t* info = pars_info_create();
-
- pars_info_add_ull_literal(info, "id", table->id);
- pars_info_add_int4_literal(info, "pos", pos);
-
- pars_info_add_str_literal(info, "name", col_name);
- pars_info_add_int4_literal(info, "mtype", mtype);
- pars_info_add_int4_literal(info, "prtype", prtype);
- pars_info_add_int4_literal(info, "len", len);
- pars_info_add_int4_literal(info, "prec", vcol->num_base);
-
- dberr_t error = que_eval_sql(
- info,
- "PROCEDURE P () IS\n"
- "BEGIN\n"
- "INSERT INTO SYS_COLUMNS VALUES"
- "(:id, :pos, :name, :mtype, :prtype, :len, :prec);\n"
- "END;\n",
- FALSE, trx);
-
- if (error != DB_SUCCESS) {
- return(error);
+ if (innodb_insert_sys_columns(table->id, pos, col_name,
+ vcol->m_col.mtype, vcol->m_col.prtype,
+ vcol->m_col.len, vcol->num_base, trx)) {
+ return true;
}
- for (ulint i = 0; i < vcol->num_base; i++) {
- error = innobase_insert_sys_virtual(
- table, pos, vcol->base_col[i]->ind, trx);
- if (error != DB_SUCCESS) {
- return(error);
+ for (ulint i = 0; i < unsigned{vcol->num_base}; i++) {
+ if (innobase_insert_sys_virtual(
+ table, pos, vcol->base_col[i]->ind, trx)) {
+ return true;
}
}
- return(error);
+ return false;
}
/** Update SYS_TABLES.N_COLS in the data dictionary.
@param[in] user_table InnoDB table
-@param[in] n_cols the new value of SYS_TABLES.N_COLS
+@param[in] n the new value of SYS_TABLES.N_COLS
@param[in] trx transaction
@return whether the operation failed */
-static
-bool
-innodb_update_n_cols(const dict_table_t* table, ulint n_cols, trx_t* trx)
+static bool innodb_update_cols(const dict_table_t* table, ulint n, trx_t* trx)
{
pars_info_t* info = pars_info_create();
- pars_info_add_int4_literal(info, "n", n_cols);
+ pars_info_add_int4_literal(info, "n", n);
pars_info_add_ull_literal(info, "id", table->id);
- dberr_t err = que_eval_sql(info,
- "PROCEDURE UPDATE_N_COLS () IS\n"
- "BEGIN\n"
- "UPDATE SYS_TABLES SET N_COLS = :n"
- " WHERE ID = :id;\n"
- "END;\n", FALSE, trx);
-
- if (err != DB_SUCCESS) {
+ if (DB_SUCCESS != que_eval_sql(info,
+ "PROCEDURE UPDATE_N_COLS () IS\n"
+ "BEGIN\n"
+ "UPDATE SYS_TABLES SET N_COLS = :n"
+ " WHERE ID = :id;\n"
+ "END;\n", FALSE, trx)) {
my_error(ER_INTERNAL_ERROR, MYF(0),
"InnoDB: Updating SYS_TABLES.N_COLS failed");
return true;
@@ -4217,290 +5251,47 @@ innodb_update_n_cols(const dict_table_t* table, ulint n_cols, trx_t* trx)
static
bool
innobase_add_virtual_try(
- Alter_inplace_info* ha_alter_info,
- const dict_table_t* user_table,
- trx_t* trx)
+ const Alter_inplace_info* ha_alter_info,
+ const dict_table_t* user_table,
+ trx_t* trx)
{
- ha_innobase_inplace_ctx* ctx;
- dberr_t err = DB_SUCCESS;
-
- ctx = static_cast<ha_innobase_inplace_ctx*>(
+ ha_innobase_inplace_ctx* ctx = static_cast<ha_innobase_inplace_ctx*>(
ha_alter_info->handler_ctx);
for (ulint i = 0; i < ctx->num_to_add_vcol; i++) {
-
- err = innobase_add_one_virtual(
- user_table, ctx->add_vcol_name[i],
- &ctx->add_vcol[i], trx);
-
- if (err != DB_SUCCESS) {
- my_error(ER_INTERNAL_ERROR, MYF(0),
- "InnoDB: ADD COLUMN...VIRTUAL");
- return(true);
+ if (innobase_add_one_virtual(
+ user_table, ctx->add_vcol_name[i],
+ &ctx->add_vcol[i], trx)) {
+ return true;
}
}
-
- ulint n_col = unsigned(user_table->n_cols) - DATA_N_SYS_COLS;
- ulint n_v_col = unsigned(user_table->n_v_cols)
- + ctx->num_to_add_vcol - ctx->num_to_drop_vcol;
- ulint new_n = dict_table_encode_n_col(n_col, n_v_col)
- + (unsigned(user_table->flags & DICT_TF_COMPACT) << 31);
-
- return innodb_update_n_cols(user_table, new_n, trx);
+ return false;
}
-/** Insert into SYS_COLUMNS and insert/update the hidden metadata record
-for instant ADD COLUMN.
-@param[in,out] ctx ALTER TABLE context for the current partition
-@param[in] altered_table MySQL table that is being altered
-@param[in] table MySQL table as it is before the ALTER operation
-@param[in,out] trx dictionary transaction
-@retval true failure
-@retval false success */
-static
-bool
-innobase_add_instant_try(
- ha_innobase_inplace_ctx*ctx,
- const TABLE* altered_table,
- const TABLE* table,
- trx_t* trx)
+/** Delete metadata from SYS_COLUMNS and SYS_VIRTUAL.
+@param[in] id table id
+@param[in] pos first SYS_COLUMNS.POS
+@param[in,out] trx data dictionary transaction
+@retval true Failure
+@retval false Success. */
+static bool innobase_instant_drop_cols(table_id_t id, ulint pos, trx_t* trx)
{
- DBUG_ASSERT(!ctx->need_rebuild());
-
- if (!ctx->is_instant()) return false;
-
- DBUG_ASSERT(altered_table->s->fields > table->s->fields);
- DBUG_ASSERT(ctx->old_table->n_cols == ctx->old_n_cols);
-
- dict_table_t* user_table = ctx->old_table;
- user_table->instant_add_column(*ctx->instant_table);
- dict_index_t* index = dict_table_get_first_index(user_table);
- /* The table may have been emptied and may have lost its
- 'instant-add-ness' during this instant ADD COLUMN. */
-
- /* Construct a table row of default values for the stored columns. */
- dtuple_t* row = dtuple_create(ctx->heap, user_table->n_cols);
- dict_table_copy_types(row, user_table);
- Field** af = altered_table->field;
- Field** const end = altered_table->field + altered_table->s->fields;
-
- for (uint i = 0; af < end; af++) {
- if (!(*af)->stored_in_db()) {
- continue;
- }
-
- dict_col_t* col = dict_table_get_nth_col(user_table, i);
- DBUG_ASSERT(!strcmp((*af)->field_name.str,
- dict_table_get_col_name(user_table, i)));
-
- dfield_t* d = dtuple_get_nth_field(row, i);
-
- if (col->is_instant()) {
- dfield_set_data(d, col->def_val.data,
- col->def_val.len);
- } else if ((*af)->real_maybe_null()) {
- /* Store NULL for nullable 'core' columns. */
- dfield_set_null(d);
- } else {
- switch ((*af)->type()) {
- case MYSQL_TYPE_VARCHAR:
- case MYSQL_TYPE_GEOMETRY:
- case MYSQL_TYPE_TINY_BLOB:
- case MYSQL_TYPE_MEDIUM_BLOB:
- case MYSQL_TYPE_BLOB:
- case MYSQL_TYPE_LONG_BLOB:
- variable_length:
- /* Store the empty string for 'core'
- variable-length NOT NULL columns. */
- dfield_set_data(d, field_ref_zero, 0);
- break;
- case MYSQL_TYPE_STRING:
- if (col->mbminlen != col->mbmaxlen
- && dict_table_is_comp(user_table)) {
- goto variable_length;
- }
- /* fall through */
- default:
- /* For fixed-length NOT NULL 'core' columns,
- get a dummy default value from SQL. Note that
- we will preserve the old values of these
- columns when updating the metadata
- record, to avoid unnecessary updates. */
- ulint len = (*af)->pack_length();
- DBUG_ASSERT(d->type.mtype != DATA_INT
- || len <= 8);
- row_mysql_store_col_in_innobase_format(
- d, d->type.mtype == DATA_INT
- ? static_cast<byte*>(
- mem_heap_alloc(ctx->heap, len))
- : NULL, true, (*af)->ptr, len,
- dict_table_is_comp(user_table));
- }
- }
-
- if (i + DATA_N_SYS_COLS < ctx->old_n_cols) {
- i++;
- continue;
- }
-
- pars_info_t* info = pars_info_create();
- pars_info_add_ull_literal(info, "id", user_table->id);
- pars_info_add_int4_literal(info, "pos", i);
- pars_info_add_str_literal(info, "name", (*af)->field_name.str);
- pars_info_add_int4_literal(info, "mtype", d->type.mtype);
- pars_info_add_int4_literal(info, "prtype", d->type.prtype);
- pars_info_add_int4_literal(info, "len", d->type.len);
+ pars_info_t* info = pars_info_create();
+ pars_info_add_ull_literal(info, "id", id);
+ pars_info_add_int4_literal(info, "pos", pos);
- dberr_t err = que_eval_sql(
+ dberr_t err = que_eval_sql(
info,
- "PROCEDURE ADD_COL () IS\n"
+ "PROCEDURE DELETE_COL () IS\n"
"BEGIN\n"
- "INSERT INTO SYS_COLUMNS VALUES"
- "(:id,:pos,:name,:mtype,:prtype,:len,0);\n"
+ "DELETE FROM SYS_COLUMNS WHERE\n"
+ "TABLE_ID = :id AND POS >= :pos;\n"
+ "DELETE FROM SYS_VIRTUAL WHERE TABLE_ID = :id;\n"
"END;\n", FALSE, trx);
- if (err != DB_SUCCESS) {
- my_error(ER_INTERNAL_ERROR, MYF(0),
- "InnoDB: Insert into SYS_COLUMNS failed");
- return(true);
- }
-
- i++;
- }
-
- if (innodb_update_n_cols(user_table, dict_table_encode_n_col(
- unsigned(user_table->n_cols)
- - DATA_N_SYS_COLS,
- user_table->n_v_cols)
- | (user_table->flags & DICT_TF_COMPACT) << 31,
- trx)) {
- return true;
- }
-
- unsigned i = unsigned(user_table->n_cols) - DATA_N_SYS_COLS;
- byte trx_id[DATA_TRX_ID_LEN], roll_ptr[DATA_ROLL_PTR_LEN];
- dfield_set_data(dtuple_get_nth_field(row, i++), field_ref_zero,
- DATA_ROW_ID_LEN);
- dfield_set_data(dtuple_get_nth_field(row, i++), trx_id, sizeof trx_id);
- dfield_set_data(dtuple_get_nth_field(row, i),roll_ptr,sizeof roll_ptr);
- DBUG_ASSERT(i + 1 == user_table->n_cols);
-
- trx_write_trx_id(trx_id, trx->id);
- /* The DB_ROLL_PTR will be assigned later, when allocating undo log.
- Silence a Valgrind warning in dtuple_validate() when
- row_ins_clust_index_entry_low() searches for the insert position. */
- memset(roll_ptr, 0, sizeof roll_ptr);
-
- dtuple_t* entry = row_build_index_entry(row, NULL, index, ctx->heap);
- entry->info_bits = REC_INFO_METADATA;
-
- mtr_t mtr;
- mtr.start();
- index->set_modified(mtr);
- btr_pcur_t pcur;
- btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, &pcur, true,
- 0, &mtr);
- ut_ad(btr_pcur_is_before_first_on_page(&pcur));
- btr_pcur_move_to_next_on_page(&pcur);
-
- buf_block_t* block = btr_pcur_get_block(&pcur);
- ut_ad(page_is_leaf(block->frame));
- ut_ad(!page_has_prev(block->frame));
- ut_ad(!buf_block_get_page_zip(block));
- const rec_t* rec = btr_pcur_get_rec(&pcur);
- que_thr_t* thr = pars_complete_graph_for_exec(
- NULL, trx, ctx->heap, NULL);
-
- dberr_t err;
- if (rec_is_metadata(rec, index)) {
- ut_ad(page_rec_is_user_rec(rec));
- if (!page_has_next(block->frame)
- && page_rec_is_last(rec, block->frame)) {
- goto empty_table;
- }
- /* Extend the record with the instantly added columns. */
- const unsigned n = user_table->n_cols - ctx->old_n_cols;
- /* Reserve room for DB_TRX_ID,DB_ROLL_PTR and any
- non-updated off-page columns in case they are moved off
- page as a result of the update. */
- upd_t* update = upd_create(index->n_fields, ctx->heap);
- update->n_fields = n;
- update->info_bits = REC_INFO_METADATA;
- /* Add the default values for instantly added columns */
- for (unsigned i = 0; i < n; i++) {
- upd_field_t* uf = upd_get_nth_field(update, i);
- unsigned f = index->n_fields - n + i;
- uf->field_no = f;
- uf->new_val = entry->fields[f];
- }
- offset_t* offsets = NULL;
- mem_heap_t* offsets_heap = NULL;
- big_rec_t* big_rec;
- err = btr_cur_pessimistic_update(
- BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG,
- btr_pcur_get_btr_cur(&pcur),
- &offsets, &offsets_heap, ctx->heap,
- &big_rec, update, UPD_NODE_NO_ORD_CHANGE,
- thr, trx->id, &mtr);
- if (big_rec) {
- if (err == DB_SUCCESS) {
- err = btr_store_big_rec_extern_fields(
- &pcur, offsets, big_rec, &mtr,
- BTR_STORE_UPDATE);
- }
-
- dtuple_big_rec_free(big_rec);
- }
- if (offsets_heap) {
- mem_heap_free(offsets_heap);
- }
- btr_pcur_close(&pcur);
- goto func_exit;
- } else if (page_rec_is_supremum(rec)) {
-empty_table:
- /* The table is empty. */
- ut_ad(fil_page_index_page_check(block->frame));
- ut_ad(!page_has_siblings(block->frame));
- ut_ad(block->page.id.page_no() == index->page);
- btr_page_empty(block, NULL, index, 0, &mtr);
- index->remove_instant();
- err = DB_SUCCESS;
- goto func_exit;
- }
-
- /* Convert the table to the instant ADD COLUMN format. */
- ut_ad(user_table->is_instant());
- mtr.commit();
- mtr.start();
- index->set_modified(mtr);
- if (page_t* root = btr_root_get(index, &mtr)) {
- if (fil_page_get_type(root) != FIL_PAGE_INDEX) {
- DBUG_ASSERT(!"wrong page type");
- goto err_exit;
- }
-
- DBUG_ASSERT(!page_is_comp(root) || !page_get_instant(root));
- mlog_write_ulint(root + FIL_PAGE_TYPE,
- FIL_PAGE_TYPE_INSTANT, MLOG_2BYTES,
- &mtr);
- page_set_instant(root, index->n_core_fields, &mtr);
- mtr.commit();
- mtr.start();
- index->set_modified(mtr);
- err = row_ins_clust_index_entry_low(
- BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index,
- index->n_uniq, entry, 0, thr);
- } else {
-err_exit:
- err = DB_CORRUPTION;
- }
-
-func_exit:
- mtr.commit();
-
if (err != DB_SUCCESS) {
- my_error_innodb(err, table->s->table_name.str,
- user_table->flags);
+ my_error(ER_INTERNAL_ERROR, MYF(0),
+ "InnoDB: DELETE from SYS_COLUMNS/SYS_VIRTUAL failed");
return true;
}
@@ -4678,9 +5469,9 @@ innobase_drop_one_virtual_sys_virtual(
static
bool
innobase_drop_virtual_try(
- Alter_inplace_info* ha_alter_info,
- const dict_table_t* user_table,
- trx_t* trx)
+ const Alter_inplace_info* ha_alter_info,
+ const dict_table_t* user_table,
+ trx_t* trx)
{
ha_innobase_inplace_ctx* ctx;
dberr_t err = DB_SUCCESS;
@@ -4713,14 +5504,466 @@ innobase_drop_virtual_try(
}
}
+ return false;
+}
+
+/** Serialise metadata of dropped or reordered columns.
+@param[in,out] heap memory heap for allocation
+@param[out] field data field with the metadata */
+inline
+void dict_table_t::serialise_columns(mem_heap_t* heap, dfield_t* field) const
+{
+ DBUG_ASSERT(instant);
+ const dict_index_t& index = *UT_LIST_GET_FIRST(indexes);
+ unsigned n_fixed = index.first_user_field();
+ unsigned num_non_pk_fields = index.n_fields - n_fixed;
+
+ ulint len = 4 + num_non_pk_fields * 2;
+
+ byte* data = static_cast<byte*>(mem_heap_alloc(heap, len));
+
+ dfield_set_data(field, data, len);
+
+ mach_write_to_4(data, num_non_pk_fields);
+
+ data += 4;
+
+ for (ulint i = n_fixed; i < index.n_fields; i++) {
+ mach_write_to_2(data, instant->field_map[i - n_fixed]);
+ data += 2;
+ }
+}
+
+/** Construct the metadata record for instant ALTER TABLE.
+@param[in] row dummy or default values for existing columns
+@param[in,out] heap memory heap for allocations
+@return metadata record */
+inline
+dtuple_t*
+dict_index_t::instant_metadata(const dtuple_t& row, mem_heap_t* heap) const
+{
+ ut_ad(is_primary());
+ dtuple_t* entry;
+
+ if (!table->instant) {
+ entry = row_build_index_entry(&row, NULL, this, heap);
+ entry->info_bits = REC_INFO_METADATA_ADD;
+ return entry;
+ }
+
+ entry = dtuple_create(heap, n_fields + 1);
+ entry->n_fields_cmp = n_uniq;
+ entry->info_bits = REC_INFO_METADATA_ALTER;
+
+ const dict_field_t* field = fields;
+
+ for (uint i = 0; i <= n_fields; i++, field++) {
+ dfield_t* dfield = dtuple_get_nth_field(entry, i);
+
+ if (i == first_user_field()) {
+ table->serialise_columns(heap, dfield);
+ dfield->type.metadata_blob_init();
+ field--;
+ continue;
+ }
+
+ ut_ad(!field->col->is_virtual());
+
+ if (field->col->is_dropped()) {
+ dict_col_copy_type(field->col, &dfield->type);
+ if (field->col->is_nullable()) {
+ dfield_set_null(dfield);
+ } else {
+ dfield_set_data(dfield, field_ref_zero,
+ field->fixed_len);
+ }
+ continue;
+ }
+
+ const dfield_t* s = dtuple_get_nth_field(&row, field->col->ind);
+ ut_ad(dict_col_type_assert_equal(field->col, &s->type));
+ *dfield = *s;
+
+ if (dfield_is_null(dfield)) {
+ continue;
+ }
+
+ if (dfield_is_ext(dfield)) {
+ ut_ad(i > first_user_field());
+ ut_ad(!field->prefix_len);
+ ut_ad(dfield->len >= FIELD_REF_SIZE);
+ dfield_set_len(dfield, dfield->len - FIELD_REF_SIZE);
+ }
+
+ if (!field->prefix_len) {
+ continue;
+ }
+
+ ut_ad(field->col->ord_part);
+ ut_ad(i < n_uniq);
- ulint n_col = unsigned(user_table->n_cols) - DATA_N_SYS_COLS;
- ulint n_v_col = unsigned(user_table->n_v_cols)
- - ctx->num_to_drop_vcol;
- ulint new_n = dict_table_encode_n_col(n_col, n_v_col)
- | ((user_table->flags & DICT_TF_COMPACT) << 31);
+ ulint len = dtype_get_at_most_n_mbchars(
+ field->col->prtype,
+ field->col->mbminlen, field->col->mbmaxlen,
+ field->prefix_len, dfield->len,
+ static_cast<char*>(dfield_get_data(dfield)));
+ dfield_set_len(dfield, len);
+ }
- return innodb_update_n_cols(user_table, new_n, trx);
+ return entry;
+}
+
+/** Insert or update SYS_COLUMNS and the hidden metadata record
+for instant ALTER TABLE.
+@param[in] ha_alter_info ALTER TABLE context
+@param[in,out] ctx ALTER TABLE context for the current partition
+@param[in] altered_table MySQL table that is being altered
+@param[in] table MySQL table as it is before the ALTER operation
+@param[in,out] trx dictionary transaction
+@retval true failure
+@retval false success */
+static bool innobase_instant_try(
+ const Alter_inplace_info* ha_alter_info,
+ ha_innobase_inplace_ctx* ctx,
+ const TABLE* altered_table,
+ const TABLE* table,
+ trx_t* trx)
+{
+ DBUG_ASSERT(!ctx->need_rebuild());
+ DBUG_ASSERT(ctx->is_instant());
+
+ dict_table_t* user_table = ctx->old_table;
+
+ dict_index_t* index = dict_table_get_first_index(user_table);
+ mtr_t mtr;
+ mtr.start();
+ /* Prevent purge from calling dict_index_t::clear_instant_add(),
+ to protect index->n_core_fields, index->table->instant and others
+ from changing during ctx->instant_column(). */
+ instant_metadata_lock(*index, mtr);
+ const unsigned n_old_fields = index->n_fields;
+ const dict_col_t* old_cols = user_table->cols;
+ DBUG_ASSERT(user_table->n_cols == ctx->old_n_cols);
+
+ const bool metadata_changed = ctx->instant_column();
+
+ DBUG_ASSERT(index->n_fields >= n_old_fields);
+ /* Release the page latch. Between this and the next
+ btr_pcur_open_at_index_side(), data fields such as
+ index->n_core_fields and index->table->instant could change,
+ but we would handle that in empty_table: below. */
+ mtr.commit();
+ /* The table may have been emptied and may have lost its
+ 'instantness' during this ALTER TABLE. */
+
+ /* Construct a table row of default values for the stored columns. */
+ dtuple_t* row = dtuple_create(ctx->heap, user_table->n_cols);
+ dict_table_copy_types(row, user_table);
+ Field** af = altered_table->field;
+ Field** const end = altered_table->field + altered_table->s->fields;
+ ut_d(List_iterator_fast<Create_field> cf_it(
+ ha_alter_info->alter_info->create_list));
+ if (ctx->first_alter_pos
+ && innobase_instant_drop_cols(user_table->id,
+ ctx->first_alter_pos - 1, trx)) {
+ return true;
+ }
+ for (uint i = 0; af < end; af++) {
+ if (!(*af)->stored_in_db()) {
+ ut_d(cf_it++);
+ continue;
+ }
+
+ const dict_col_t* old = dict_table_t::find(old_cols,
+ ctx->col_map,
+ ctx->old_n_cols, i);
+ DBUG_ASSERT(!old || i >= ctx->old_n_cols - DATA_N_SYS_COLS
+ || old->ind == i
+ || (ctx->first_alter_pos
+ && old->ind >= ctx->first_alter_pos - 1));
+
+ dfield_t* d = dtuple_get_nth_field(row, i);
+ const dict_col_t* col = dict_table_get_nth_col(user_table, i);
+ DBUG_ASSERT(!col->is_virtual());
+ DBUG_ASSERT(!col->is_dropped());
+ DBUG_ASSERT(col->mtype != DATA_SYS);
+ DBUG_ASSERT(!strcmp((*af)->field_name.str,
+ dict_table_get_col_name(user_table, i)));
+ DBUG_ASSERT(old || col->is_added());
+
+ ut_d(const Create_field* new_field = cf_it++);
+ /* new_field->field would point to an existing column.
+ If it is NULL, the column was added by this ALTER TABLE. */
+ ut_ad(!new_field->field == !old);
+
+ if (col->is_added()) {
+ dfield_set_data(d, col->def_val.data,
+ col->def_val.len);
+ } else if ((*af)->real_maybe_null()) {
+ /* Store NULL for nullable 'core' columns. */
+ dfield_set_null(d);
+ } else {
+ switch ((*af)->type()) {
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ variable_length:
+ /* Store the empty string for 'core'
+ variable-length NOT NULL columns. */
+ dfield_set_data(d, field_ref_zero, 0);
+ break;
+ case MYSQL_TYPE_STRING:
+ if (col->mbminlen != col->mbmaxlen
+ && user_table->not_redundant()) {
+ goto variable_length;
+ }
+ /* fall through */
+ default:
+ /* For fixed-length NOT NULL 'core' columns,
+ get a dummy default value from SQL. Note that
+ we will preserve the old values of these
+ columns when updating the metadata
+ record, to avoid unnecessary updates. */
+ ulint len = (*af)->pack_length();
+ DBUG_ASSERT(d->type.mtype != DATA_INT
+ || len <= 8);
+ row_mysql_store_col_in_innobase_format(
+ d, d->type.mtype == DATA_INT
+ ? static_cast<byte*>(
+ mem_heap_alloc(ctx->heap, len))
+ : NULL, true, (*af)->ptr, len,
+ dict_table_is_comp(user_table));
+ ut_ad(new_field->field->pack_length() == len);
+ }
+ }
+
+ bool update = old && (!ctx->first_alter_pos
+ || i < ctx->first_alter_pos - 1);
+ DBUG_ASSERT(!old || col->same_format(*old));
+ if (update
+ && old->prtype == d->type.prtype) {
+ /* The record is already present in SYS_COLUMNS. */
+ } else if (innodb_insert_sys_columns(user_table->id, i,
+ (*af)->field_name.str,
+ d->type.mtype,
+ d->type.prtype,
+ d->type.len, 0, trx,
+ update)) {
+ return true;
+ }
+
+ i++;
+ }
+
+ if (innodb_update_cols(user_table, dict_table_encode_n_col(
+ unsigned(user_table->n_cols)
+ - DATA_N_SYS_COLS,
+ user_table->n_v_cols)
+ | (user_table->flags & DICT_TF_COMPACT) << 31,
+ trx)) {
+ return true;
+ }
+
+ if (ctx->first_alter_pos) {
+add_all_virtual:
+ for (uint i = 0; i < user_table->n_v_cols; i++) {
+ if (innobase_add_one_virtual(
+ user_table,
+ dict_table_get_v_col_name(user_table, i),
+ &user_table->v_cols[i], trx)) {
+ return true;
+ }
+ }
+ } else if (ha_alter_info->handler_flags & ALTER_DROP_VIRTUAL_COLUMN) {
+ if (innobase_instant_drop_cols(user_table->id, 65536, trx)) {
+ return true;
+ }
+ goto add_all_virtual;
+ } else if ((ha_alter_info->handler_flags & ALTER_ADD_VIRTUAL_COLUMN)
+ && innobase_add_virtual_try(ha_alter_info, user_table,
+ trx)) {
+ return true;
+ }
+
+ unsigned i = unsigned(user_table->n_cols) - DATA_N_SYS_COLS;
+ DBUG_ASSERT(i >= altered_table->s->stored_fields);
+ DBUG_ASSERT(i <= altered_table->s->stored_fields + 1);
+ if (i > altered_table->s->fields) {
+ const dict_col_t& fts_doc_id = user_table->cols[i - 1];
+ DBUG_ASSERT(!strcmp(fts_doc_id.name(*user_table),
+ FTS_DOC_ID_COL_NAME));
+ DBUG_ASSERT(!fts_doc_id.is_nullable());
+ DBUG_ASSERT(fts_doc_id.len == 8);
+ dfield_set_data(dtuple_get_nth_field(row, i - 1),
+ field_ref_zero, fts_doc_id.len);
+ }
+ byte trx_id[DATA_TRX_ID_LEN], roll_ptr[DATA_ROLL_PTR_LEN];
+ dfield_set_data(dtuple_get_nth_field(row, i++), field_ref_zero,
+ DATA_ROW_ID_LEN);
+ dfield_set_data(dtuple_get_nth_field(row, i++), trx_id, sizeof trx_id);
+ dfield_set_data(dtuple_get_nth_field(row, i),roll_ptr,sizeof roll_ptr);
+ DBUG_ASSERT(i + 1 == user_table->n_cols);
+
+ trx_write_trx_id(trx_id, trx->id);
+ /* The DB_ROLL_PTR will be assigned later, when allocating undo log.
+ Silence a Valgrind warning in dtuple_validate() when
+ row_ins_clust_index_entry_low() searches for the insert position. */
+ memset(roll_ptr, 0, sizeof roll_ptr);
+
+ dtuple_t* entry = index->instant_metadata(*row, ctx->heap);
+ mtr.start();
+ index->set_modified(mtr);
+ btr_pcur_t pcur;
+ btr_pcur_open_at_index_side(true, index, BTR_MODIFY_TREE, &pcur, true,
+ 0, &mtr);
+ ut_ad(btr_pcur_is_before_first_on_page(&pcur));
+ btr_pcur_move_to_next_on_page(&pcur);
+
+ buf_block_t* block = btr_pcur_get_block(&pcur);
+ ut_ad(page_is_leaf(block->frame));
+ ut_ad(!page_has_prev(block->frame));
+ ut_ad(!buf_block_get_page_zip(block));
+ const rec_t* rec = btr_pcur_get_rec(&pcur);
+ que_thr_t* thr = pars_complete_graph_for_exec(
+ NULL, trx, ctx->heap, NULL);
+
+ dberr_t err = DB_SUCCESS;
+ if (rec_is_metadata(rec, *index)) {
+ ut_ad(page_rec_is_user_rec(rec));
+ if (!rec_is_alter_metadata(rec, *index)
+ && !index->table->instant
+ && !page_has_next(block->frame)
+ && page_rec_is_last(rec, block->frame)) {
+ goto empty_table;
+ }
+
+ if (!metadata_changed) {
+ goto func_exit;
+ }
+
+ /* Ensure that the root page is in the correct format. */
+ buf_block_t* root = btr_root_block_get(index, RW_X_LATCH,
+ &mtr);
+ DBUG_ASSERT(root);
+ if (fil_page_get_type(root->frame) != FIL_PAGE_TYPE_INSTANT) {
+ DBUG_ASSERT(!"wrong page type");
+ err = DB_CORRUPTION;
+ goto func_exit;
+ }
+
+ btr_set_instant(root, *index, &mtr);
+
+ /* Extend the record with any added columns. */
+ uint n = uint(index->n_fields) - n_old_fields;
+ /* Reserve room for DB_TRX_ID,DB_ROLL_PTR and any
+ non-updated off-page columns in case they are moved off
+ page as a result of the update. */
+ const unsigned f = user_table->instant != NULL;
+ upd_t* update = upd_create(index->n_fields + f, ctx->heap);
+ update->n_fields = n + f;
+ update->info_bits = f
+ ? REC_INFO_METADATA_ALTER
+ : REC_INFO_METADATA_ADD;
+ if (f) {
+ upd_field_t* uf = upd_get_nth_field(update, 0);
+ uf->field_no = index->first_user_field();
+ uf->new_val = entry->fields[uf->field_no];
+ DBUG_ASSERT(!dfield_is_ext(&uf->new_val));
+ DBUG_ASSERT(!dfield_is_null(&uf->new_val));
+ }
+
+ /* Add the default values for instantly added columns */
+ unsigned j = f;
+
+ for (unsigned k = n_old_fields; k < index->n_fields; k++) {
+ upd_field_t* uf = upd_get_nth_field(update, j++);
+ uf->field_no = k + f;
+ uf->new_val = entry->fields[k + f];
+
+ ut_ad(j <= n + f);
+ }
+
+ ut_ad(j == n + f);
+
+ offset_t* offsets = NULL;
+ mem_heap_t* offsets_heap = NULL;
+ big_rec_t* big_rec;
+ err = btr_cur_pessimistic_update(
+ BTR_NO_LOCKING_FLAG | BTR_KEEP_POS_FLAG,
+ btr_pcur_get_btr_cur(&pcur),
+ &offsets, &offsets_heap, ctx->heap,
+ &big_rec, update, UPD_NODE_NO_ORD_CHANGE,
+ thr, trx->id, &mtr);
+
+ offsets = rec_get_offsets(
+ btr_pcur_get_rec(&pcur), index, offsets,
+ true, ULINT_UNDEFINED, &offsets_heap);
+ if (big_rec) {
+ if (err == DB_SUCCESS) {
+ err = btr_store_big_rec_extern_fields(
+ &pcur, offsets, big_rec, &mtr,
+ BTR_STORE_UPDATE);
+ }
+
+ dtuple_big_rec_free(big_rec);
+ }
+ if (offsets_heap) {
+ mem_heap_free(offsets_heap);
+ }
+ btr_pcur_close(&pcur);
+ goto func_exit;
+ } else if (page_rec_is_supremum(rec) && !index->table->instant) {
+empty_table:
+ /* The table is empty. */
+ ut_ad(fil_page_index_page_check(block->frame));
+ ut_ad(!page_has_siblings(block->frame));
+ ut_ad(block->page.id.page_no() == index->page);
+ /* MDEV-17383: free metadata BLOBs! */
+ btr_page_empty(block, NULL, index, 0, &mtr);
+ if (index->is_instant()) {
+ index->clear_instant_add();
+ }
+ goto func_exit;
+ } else if (!user_table->is_instant()) {
+ ut_ad(!user_table->not_redundant());
+ goto func_exit;
+ }
+
+ /* Convert the table to the instant ALTER TABLE format. */
+ mtr.commit();
+ mtr.start();
+ index->set_modified(mtr);
+ if (buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, &mtr)) {
+ if (fil_page_get_type(root->frame) != FIL_PAGE_INDEX) {
+ DBUG_ASSERT(!"wrong page type");
+ goto err_exit;
+ }
+
+ btr_set_instant(root, *index, &mtr);
+ mtr.commit();
+ mtr.start();
+ index->set_modified(mtr);
+ err = row_ins_clust_index_entry_low(
+ BTR_NO_LOCKING_FLAG, BTR_MODIFY_TREE, index,
+ index->n_uniq, entry, 0, thr);
+ } else {
+err_exit:
+ err = DB_CORRUPTION;
+ }
+
+func_exit:
+ mtr.commit();
+
+ if (err != DB_SUCCESS) {
+ my_error_innodb(err, table->s->table_name.str,
+ user_table->flags);
+ return true;
+ }
+
+ return false;
}
/** Adjust the create index column number from "New table" to
@@ -4740,8 +5983,6 @@ innodb_v_adjust_idx_col(
ulint num_v_dropped,
index_def_t* index_def)
{
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
for (ulint i = 0; i < index_def->n_fields; i++) {
#ifdef UNIV_DEBUG
bool col_found = false;
@@ -4759,15 +6000,14 @@ innodb_v_adjust_idx_col(
const Field* field = NULL;
- cf_it.rewind();
-
/* Found the field in the new table */
- while (const Create_field* new_field = cf_it++) {
- if (new_field->stored_in_db()) {
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
+ if (new_field.stored_in_db()) {
continue;
}
- field = new_field->field;
+ field = new_field.field;
if (num_v == index_field->col_no) {
break;
@@ -4950,11 +6190,9 @@ prepare_inplace_alter_table_dict(
const char* path = thd_innodb_tmpdir(
ctx->prebuilt->trx->mysql_thd);
- index_defs = innobase_create_key_defs(
- ctx->heap, ha_alter_info, altered_table, ctx->num_to_add_index,
+ index_defs = ctx->create_key_defs(
+ ha_alter_info, altered_table,
num_fts_index,
- dict_index_is_auto_gen_clust(dict_table_get_first_index(
- ctx->new_table)),
fts_doc_id_col, add_fts_doc_id, add_fts_doc_id_idx,
old_table);
@@ -5147,10 +6385,10 @@ new_clustered_failed:
}
if (altered_table->versioned()) {
- if (i == altered_table->s->row_start_field) {
+ if (i == altered_table->s->vers.start_fieldno) {
field_type |= DATA_VERS_START;
} else if (i ==
- altered_table->s->row_end_field) {
+ altered_table->s->vers.end_fieldno) {
field_type |= DATA_VERS_END;
} else if (!(field->flags
& VERS_UPDATE_UNVERSIONED_FLAG)) {
@@ -5326,26 +6564,19 @@ new_clustered_failed:
== !!new_clustered);
}
- if (ctx->need_rebuild() && user_table->supports_instant()) {
- if (!instant_alter_column_possible(ha_alter_info, old_table)) {
- goto not_instant_add_column;
- }
-
- for (uint i = uint(ctx->old_table->n_cols) - DATA_N_SYS_COLS;
- i--; ) {
- if (ctx->col_map[i] != i) {
- goto not_instant_add_column;
- }
- }
-
- DBUG_ASSERT(ctx->new_table->n_cols > ctx->old_table->n_cols);
+ DBUG_ASSERT(!ctx->need_rebuild()
+ || !ctx->new_table->persistent_autoinc);
+ if (ctx->need_rebuild() && instant_alter_column_possible(
+ *user_table, ha_alter_info, old_table, altered_table,
+ ha_innobase::is_innodb_strict_mode(ctx->trx->mysql_thd))) {
for (uint a = 0; a < ctx->num_to_add_index; a++) {
ctx->add_index[a]->table = ctx->new_table;
error = dict_index_add_to_cache(
ctx->add_index[a], FIL_NULL, add_v);
ut_a(error == DB_SUCCESS);
}
+
DBUG_ASSERT(ha_alter_info->key_count
/* hidden GEN_CLUST_INDEX in InnoDB */
+ dict_index_is_auto_gen_clust(
@@ -5357,24 +6588,23 @@ new_clustered_failed:
altered_table->key_info)
!= FTS_EXIST_DOC_ID_INDEX)
== ctx->num_to_add_index);
+
ctx->num_to_add_index = 0;
ctx->add_index = NULL;
uint i = 0; // index of stored columns ctx->new_table->cols[]
Field **af = altered_table->field;
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
-
- while (const Create_field* new_field = cf_it++) {
- DBUG_ASSERT(!new_field->field
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
+ DBUG_ASSERT(!new_field.field
|| std::find(old_table->field,
old_table->field
+ old_table->s->fields,
- new_field->field) !=
+ new_field.field) !=
old_table->field + old_table->s->fields);
- DBUG_ASSERT(new_field->field
- || !strcmp(new_field->field_name.str,
+ DBUG_ASSERT(new_field.field
+ || !strcmp(new_field.field_name.str,
(*af)->field_name.str));
if (!(*af)->stored_in_db()) {
@@ -5387,26 +6617,11 @@ new_clustered_failed:
DBUG_ASSERT(!strcmp((*af)->field_name.str,
dict_table_get_col_name(ctx->new_table,
i)));
- DBUG_ASSERT(!col->is_instant());
+ DBUG_ASSERT(!col->is_added());
- if (new_field->field) {
- ut_d(const dict_col_t* old_col
- = dict_table_get_nth_col(user_table, i));
- ut_d(const dict_index_t* index
- = user_table->indexes.start);
- DBUG_SLOW_ASSERT(col->mtype == old_col->mtype);
- ut_ad(col->prtype == old_col->prtype
- || col->prtype
- == (old_col->prtype & ~DATA_VERSIONED));
- DBUG_SLOW_ASSERT(col->mbminlen
- == old_col->mbminlen);
- DBUG_SLOW_ASSERT(col->mbmaxlen
- == old_col->mbmaxlen);
- DBUG_SLOW_ASSERT(col->len >= old_col->len);
- DBUG_SLOW_ASSERT(old_col->is_instant()
- == (dict_col_get_clust_pos(
- old_col, index)
- >= index->n_core_fields));
+ if (new_field.field) {
+ /* This is a pre-existing column,
+ possibly at a different position. */
} else if ((*af)->is_real_null()) {
/* DEFAULT NULL */
col->def_val.len = UNIV_SQL_NULL;
@@ -5474,11 +6689,15 @@ new_clustered_failed:
ctx->new_table, i),
FTS_DOC_ID_COL_NAME)));
+ if (altered_table->found_next_number_field) {
+ ctx->new_table->persistent_autoinc
+ = ctx->old_table->persistent_autoinc;
+ }
+
ctx->prepare_instant();
}
if (ctx->need_rebuild()) {
-not_instant_add_column:
DBUG_ASSERT(ctx->need_rebuild());
DBUG_ASSERT(!ctx->is_instant());
DBUG_ASSERT(num_fts_index <= 1);
@@ -5531,15 +6750,15 @@ not_instant_add_column:
before we can use it we need to open the
table. The new_table must be in the data
dictionary cache, because we are still holding
- the dict_sys->mutex. */
- ut_ad(mutex_own(&dict_sys->mutex));
+ the dict_sys.mutex. */
+ ut_ad(mutex_own(&dict_sys.mutex));
temp_table = dict_table_open_on_name(
ctx->new_table->name.m_name, TRUE, FALSE,
DICT_ERR_IGNORE_NONE);
ut_a(ctx->new_table == temp_table);
/* n_ref_count must be 1, because purge cannot
be executing on this very table as we are
- holding dict_operation_lock X-latch. */
+ holding dict_sys.latch X-latch. */
DBUG_ASSERT(ctx->new_table->get_ref_count() == 1);
DBUG_ASSERT(ctx->new_table->id != 0);
DBUG_ASSERT(ctx->new_table->id == ctx->trx->table_id);
@@ -5625,7 +6844,6 @@ error_handling_drop_uncached_1:
ut_ad(new_clust_index->n_core_null_bytes
== UT_BITS_IN_BYTES(new_clust_index->n_nullable));
- DBUG_ASSERT(!ctx->new_table->persistent_autoinc);
if (const Field* ai = altered_table->found_next_number_field) {
const unsigned col_no = innodb_col_no(ai);
@@ -5774,8 +6992,7 @@ error_handling_drop_uncached:
op_ok:
#endif /* UNIV_DEBUG */
ut_ad(ctx->trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
DICT_TF2_FLAG_SET(ctx->new_table, DICT_TF2_FTS);
if (ctx->need_rebuild()) {
@@ -5853,10 +7070,10 @@ error_handling:
case DB_SUCCESS:
ut_a(!dict_locked);
- ut_d(mutex_enter(&dict_sys->mutex));
+ ut_d(mutex_enter(&dict_sys.mutex));
ut_d(dict_table_check_for_dup_indexes(
user_table, CHECK_PARTIAL_OK));
- ut_d(mutex_exit(&dict_sys->mutex));
+ ut_d(mutex_exit(&dict_sys.mutex));
DBUG_RETURN(false);
case DB_TABLESPACE_EXISTS:
my_error(ER_TABLESPACE_EXISTS, MYF(0), "(unknown)");
@@ -5917,7 +7134,7 @@ error_handled:
trx_commit_for_mysql(ctx->trx);
/* n_ref_count must be 1, because purge cannot
be executing on this very table as we are
- holding dict_operation_lock X-latch. */
+ holding dict_sys.latch X-latch. */
DBUG_ASSERT(user_table->get_ref_count() == 1 || ctx->online);
online_retry_drop_indexes_with_trx(user_table, ctx->trx);
@@ -6042,6 +7259,116 @@ innobase_check_foreign_key_index(
return(false);
}
+/**
+Rename a given index in the InnoDB data dictionary.
+
+@param index index to rename
+@param new_name new name of the index
+@param[in,out] trx dict transaction to use, not going to be committed here
+
+@retval true Failure
+@retval false Success */
+static MY_ATTRIBUTE((warn_unused_result))
+bool
+rename_index_try(
+ const dict_index_t* index,
+ const char* new_name,
+ trx_t* trx)
+{
+ DBUG_ENTER("rename_index_try");
+ ut_d(dict_sys.assert_locked());
+ ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
+
+ pars_info_t* pinfo;
+ dberr_t err;
+
+ pinfo = pars_info_create();
+
+ pars_info_add_ull_literal(pinfo, "table_id", index->table->id);
+ pars_info_add_ull_literal(pinfo, "index_id", index->id);
+ pars_info_add_str_literal(pinfo, "new_name", new_name);
+
+ trx->op_info = "Renaming an index in SYS_INDEXES";
+
+ DBUG_EXECUTE_IF(
+ "ib_rename_index_fail1",
+ DBUG_SET("+d,innodb_report_deadlock");
+ );
+
+ err = que_eval_sql(
+ pinfo,
+ "PROCEDURE RENAME_INDEX_IN_SYS_INDEXES () IS\n"
+ "BEGIN\n"
+ "UPDATE SYS_INDEXES SET\n"
+ "NAME = :new_name\n"
+ "WHERE\n"
+ "ID = :index_id AND\n"
+ "TABLE_ID = :table_id;\n"
+ "END;\n",
+ FALSE, trx); /* pinfo is freed by que_eval_sql() */
+
+ DBUG_EXECUTE_IF(
+ "ib_rename_index_fail1",
+ DBUG_SET("-d,innodb_report_deadlock");
+ );
+
+ trx->op_info = "";
+
+ if (err != DB_SUCCESS) {
+ my_error_innodb(err, index->table->name.m_name, 0);
+ DBUG_RETURN(true);
+ }
+
+ DBUG_RETURN(false);
+}
+
+
+/**
+Rename a given index in the InnoDB data dictionary cache.
+
+@param[in,out] index index to rename
+@param new_name new index name
+*/
+static
+void
+innobase_rename_index_cache(dict_index_t* index, const char* new_name)
+{
+ DBUG_ENTER("innobase_rename_index_cache");
+ ut_d(dict_sys.assert_locked());
+
+ size_t old_name_len = strlen(index->name);
+ size_t new_name_len = strlen(new_name);
+
+ if (old_name_len < new_name_len) {
+ index->name = static_cast<char*>(
+ mem_heap_alloc(index->heap, new_name_len + 1));
+ }
+
+ memcpy(const_cast<char*>(index->name()), new_name, new_name_len + 1);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/** Rename the index name in cache.
+@param[in] ctx alter context
+@param[in] ha_alter_info Data used during inplace alter. */
+static void innobase_rename_indexes_cache(
+ const ha_innobase_inplace_ctx* ctx,
+ const Alter_inplace_info* ha_alter_info)
+{
+ DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_RENAME_INDEX);
+
+ for (const Alter_inplace_info::Rename_key_pair& pair :
+ ha_alter_info->rename_keys) {
+ dict_index_t* index = dict_table_get_index_on_name(
+ ctx->old_table, pair.old_key->name.str);
+ ut_ad(index);
+
+ innobase_rename_index_cache(index, pair.new_key->name.str);
+ }
+}
+
/** Fill the stored column information in s_cols list.
@param[in] altered_table mysql table object
@@ -6093,7 +7420,7 @@ alter_fill_stored_column(
s_col.num_base = num_base;
innodb_base_col_setup_for_stored(table, field, &s_col);
- (*s_cols)->push_back(s_col);
+ (*s_cols)->push_front(s_col);
}
}
@@ -6119,8 +7446,6 @@ ha_innobase::prepare_inplace_alter_table(
{
dict_index_t** drop_index; /*!< Index to be dropped */
ulint n_drop_index; /*!< Number of indexes to drop */
- dict_index_t** rename_index; /*!< Indexes to be dropped */
- ulint n_rename_index; /*!< Number of indexes to rename */
dict_foreign_t**drop_fk; /*!< Foreign key constraints to drop */
ulint n_drop_fk; /*!< Number of foreign keys to drop */
dict_foreign_t**add_fk = NULL; /*!< Foreign key constraints to drop */
@@ -6159,10 +7484,10 @@ ha_innobase::prepare_inplace_alter_table(
}
#endif /* UNIV_DEBUG */
- ut_d(mutex_enter(&dict_sys->mutex));
+ ut_d(mutex_enter(&dict_sys.mutex));
ut_d(dict_table_check_for_dup_indexes(
m_prebuilt->table, CHECK_ABORTED_OK));
- ut_d(mutex_exit(&dict_sys->mutex));
+ ut_d(mutex_exit(&dict_sys.mutex));
if (!(ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE)) {
/* Nothing to do */
@@ -6274,9 +7599,6 @@ err_exit_no_heap:
already contains. */
if (ha_alter_info->handler_flags
& ALTER_COLUMN_NAME) {
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
-
for (Field** fp = table->field; *fp; fp++) {
if (!((*fp)->flags & FIELD_IS_RENAMED)) {
continue;
@@ -6284,10 +7606,10 @@ err_exit_no_heap:
const char* name = 0;
- cf_it.rewind();
- while (Create_field* cf = cf_it++) {
- if (cf->field == *fp) {
- name = cf->field_name.str;
+ for (const Create_field& cf :
+ ha_alter_info->alter_info->create_list) {
+ if (cf.field == *fp) {
+ name = cf.field_name.str;
goto check_if_ok_to_rename;
}
}
@@ -6446,11 +7768,8 @@ check_if_ok_to_rename:
ha_alter_info->alter_info->drop_list.elements
* sizeof(dict_foreign_t*)));
- List_iterator<Alter_drop> drop_it(
- ha_alter_info->alter_info->drop_list);
-
- while (Alter_drop* drop = drop_it++) {
- if (drop->type != Alter_drop::FOREIGN_KEY) {
+ for (Alter_drop& drop : ha_alter_info->alter_info->drop_list) {
+ if (drop.type != Alter_drop::FOREIGN_KEY) {
continue;
}
@@ -6471,13 +7790,13 @@ check_if_ok_to_rename:
fid = fid ? fid + 1 : foreign->id;
if (!my_strcasecmp(system_charset_info,
- fid, drop->name)) {
+ fid, drop.name)) {
goto found_fk;
}
}
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
- drop->type_name(), drop->name);
+ drop.type_name(), drop.name);
goto err_exit;
found_fk:
for (ulint i = n_drop_fk; i--; ) {
@@ -6636,9 +7955,6 @@ check_if_can_drop_indexes:
}
}
- n_rename_index = 0;
- rename_index = NULL;
-
n_add_fk = 0;
if (ha_alter_info->handler_flags
@@ -6692,6 +8008,20 @@ err_exit:
}
}
+ if (ha_alter_info->handler_flags & ALTER_RENAME_INDEX) {
+ for (const Alter_inplace_info::Rename_key_pair& pair :
+ ha_alter_info->rename_keys) {
+ dict_index_t* index = dict_table_get_index_on_name(
+ indexed_table, pair.old_key->name.str);
+
+ if (!index || index->is_corrupted()) {
+ my_error(ER_INDEX_CORRUPT, MYF(0),
+ index->name());
+ goto err_exit;
+ }
+ }
+ }
+
const ha_table_option_struct& alt_opt=
*ha_alter_info->create_info->option_struct;
@@ -6707,7 +8037,6 @@ err_exit:
= new ha_innobase_inplace_ctx(
m_prebuilt,
drop_index, n_drop_index,
- rename_index, n_rename_index,
drop_fk, n_drop_fk,
add_fk, n_add_fk,
ha_alter_info->online,
@@ -6786,21 +8115,20 @@ err_exit:
/* See if an AUTO_INCREMENT column was added. */
uint i = 0;
ulint num_v = 0;
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
- while (const Create_field* new_field = cf_it++) {
+ for (const Create_field& new_field :
+ ha_alter_info->alter_info->create_list) {
const Field* field;
DBUG_ASSERT(i < altered_table->s->fields);
for (uint old_i = 0; table->field[old_i]; old_i++) {
- if (new_field->field == table->field[old_i]) {
+ if (new_field.field == table->field[old_i]) {
goto found_col;
}
}
/* This is an added column. */
- DBUG_ASSERT(!new_field->field);
+ DBUG_ASSERT(!new_field.field);
DBUG_ASSERT(ha_alter_info->handler_flags
& ALTER_ADD_COLUMN);
@@ -6824,7 +8152,7 @@ err_exit:
autoinc_col_max_value = innobase_get_int_col_max_value(field);
}
found_col:
- num_v += !new_field->stored_in_db();
+ num_v += !new_field.stored_in_db();
i++;
}
@@ -6835,7 +8163,6 @@ found_col:
ha_alter_info->handler_ctx = new ha_innobase_inplace_ctx(
m_prebuilt,
drop_index, n_drop_index,
- rename_index, n_rename_index,
drop_fk, n_drop_fk, add_fk, n_add_fk,
ha_alter_info->online,
heap, m_prebuilt->table, col_names,
@@ -6898,16 +8225,14 @@ alter_templ_needs_rebuild(
dict_table_t* table)
{
ulint i = 0;
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
for (Field** fp = altered_table->field; *fp; fp++, i++) {
- cf_it.rewind();
- while (const Create_field* cf = cf_it++) {
+ for (const Create_field& cf :
+ ha_alter_info->alter_info->create_list) {
for (ulint j=0; j < table->n_cols; j++) {
dict_col_t* cols
= dict_table_get_nth_col(table, j);
- if (cf->length > cols->len
+ if (cf.length > cols->len
&& dict_col_in_v_indexes(table, cols)) {
return(true);
}
@@ -6966,9 +8291,8 @@ ha_innobase::inplace_alter_table(
bool rebuild_templ = false;
DBUG_ENTER("inplace_alter_table");
DBUG_ASSERT(!srv_read_only_mode);
-
ut_ad(!sync_check_iterate(sync_check()));
- ut_ad(!rw_lock_own_flagged(&dict_operation_lock,
+ ut_ad(!rw_lock_own_flagged(&dict_sys.latch,
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
DEBUG_SYNC(m_user_thd, "innodb_inplace_alter_table_enter");
@@ -7021,7 +8345,7 @@ ok_exit:
rebuild_templ
= ctx->need_rebuild()
|| ((ha_alter_info->handler_flags
- & ALTER_COLUMN_EQUAL_PACK_LENGTH)
+ & ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE)
&& alter_templ_needs_rebuild(
altered_table, ha_alter_info, ctx->new_table));
@@ -7116,10 +8440,10 @@ oom:
KEY* dup_key;
all_done:
case DB_SUCCESS:
- ut_d(mutex_enter(&dict_sys->mutex));
+ ut_d(mutex_enter(&dict_sys.mutex));
ut_d(dict_table_check_for_dup_indexes(
m_prebuilt->table, CHECK_PARTIAL_OK));
- ut_d(mutex_exit(&dict_sys->mutex));
+ ut_d(mutex_exit(&dict_sys.mutex));
/* prebuilt->table->n_ref_count can be anything here,
given that we hold at most a shared lock on the table. */
goto ok_exit;
@@ -7181,10 +8505,7 @@ innobase_online_rebuild_log_free(
dict_table_t* table)
{
dict_index_t* clust_index = dict_table_get_first_index(table);
-
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
-
+ ut_d(dict_sys.assert_locked());
rw_lock_x_lock(&clust_index->lock);
if (clust_index->online_log) {
@@ -7457,8 +8778,7 @@ innobase_drop_foreign_try(
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
/* Drop the constraint from the data dictionary. */
static const char sql[] =
@@ -7494,7 +8814,6 @@ innobase_drop_foreign_try(
@param[in] ctx ALTER TABLE context
@param[in,out] trx Data dictionary transaction
@param[in] table_name Table name in MySQL
-@param[in] nth_col 0-based index of the column
@param[in] from old column name
@param[in] to new column name
@retval true Failure
@@ -7505,52 +8824,22 @@ innobase_rename_column_try(
const ha_innobase_inplace_ctx& ctx,
trx_t* trx,
const char* table_name,
- ulint nth_col,
const char* from,
const char* to)
{
- pars_info_t* info;
dberr_t error;
DBUG_ENTER("innobase_rename_column_try");
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
if (ctx.need_rebuild()) {
goto rename_foreign;
}
- info = pars_info_create();
-
- pars_info_add_ull_literal(info, "tableid", ctx.old_table->id);
- pars_info_add_int4_literal(info, "nth", nth_col);
- pars_info_add_str_literal(info, "new", to);
-
- trx->op_info = "renaming column in SYS_COLUMNS";
-
- error = que_eval_sql(
- info,
- "PROCEDURE RENAME_SYS_COLUMNS_PROC () IS\n"
- "BEGIN\n"
- "UPDATE SYS_COLUMNS SET NAME=:new\n"
- "WHERE TABLE_ID=:tableid\n"
- "AND POS=:nth;\n"
- "END;\n",
- FALSE, trx);
-
- DBUG_EXECUTE_IF("ib_rename_column_error",
- error = DB_OUT_OF_FILE_SPACE;);
-
- if (error != DB_SUCCESS) {
-err_exit:
- my_error_innodb(error, table_name, 0);
- trx->error_state = DB_SUCCESS;
- trx->op_info = "";
- DBUG_RETURN(true);
- }
+ error = DB_SUCCESS;
trx->op_info = "renaming column in SYS_FIELDS";
@@ -7568,19 +8857,16 @@ err_exit:
}
for (ulint i = 0; i < dict_index_get_n_fields(index); i++) {
- const dict_field_t* field
- = dict_index_get_nth_field(index, i);
- if (my_strcasecmp(system_charset_info, field->name,
- from)) {
+ const dict_field_t& f = index->fields[i];
+ DBUG_ASSERT(!f.name == f.col->is_dropped());
+
+ if (!f.name || my_strcasecmp(system_charset_info,
+ f.name, from)) {
continue;
}
- info = pars_info_create();
-
- ulint pos = i;
- if (has_prefixes) {
- pos = (pos << 16) + field->prefix_len;
- }
+ pars_info_t* info = pars_info_create();
+ ulint pos = has_prefixes ? i << 16 | f.prefix_len : i;
pars_info_add_ull_literal(info, "indexid", index->id);
pars_info_add_int4_literal(info, "nth", pos);
@@ -7595,6 +8881,8 @@ err_exit:
"AND POS=:nth;\n"
"END;\n",
FALSE, trx);
+ DBUG_EXECUTE_IF("ib_rename_column_error",
+ error = DB_OUT_OF_FILE_SPACE;);
if (error != DB_SUCCESS) {
goto err_exit;
@@ -7602,6 +8890,14 @@ err_exit:
}
}
+ if (error != DB_SUCCESS) {
+err_exit:
+ my_error_innodb(error, table_name, 0);
+ trx->error_state = DB_SUCCESS;
+ trx->op_info = "";
+ DBUG_RETURN(true);
+ }
+
rename_foreign:
trx->op_info = "renaming column in SYS_FOREIGN_COLS";
@@ -7630,7 +8926,7 @@ rename_foreign:
continue;
}
- info = pars_info_create();
+ pars_info_t* info = pars_info_create();
pars_info_add_str_literal(info, "id", foreign->id);
pars_info_add_int4_literal(info, "nth", i);
@@ -7672,7 +8968,7 @@ rename_foreign:
continue;
}
- info = pars_info_create();
+ pars_info_t* info = pars_info_create();
pars_info_add_str_literal(info, "id", foreign->id);
pars_info_add_int4_literal(info, "nth", i);
@@ -7727,11 +9023,10 @@ innobase_rename_columns_try(
trx_t* trx,
const char* table_name)
{
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
uint i = 0;
ulint num_v = 0;
+ DBUG_ASSERT(ctx->need_rebuild());
DBUG_ASSERT(ha_alter_info->handler_flags
& ALTER_COLUMN_NAME);
@@ -7741,20 +9036,13 @@ innobase_rename_columns_try(
goto processed_field;
}
- cf_it.rewind();
-
- while (Create_field* cf = cf_it++) {
- if (cf->field == *fp) {
- ulint col_n = is_virtual
- ? dict_create_v_col_pos(
- num_v, i)
- : i - num_v;
-
+ for (const Create_field& cf :
+ ha_alter_info->alter_info->create_list) {
+ if (cf.field == *fp) {
if (innobase_rename_column_try(
*ctx, trx, table_name,
- col_n,
- cf->field->field_name.str,
- cf->field_name.str)) {
+ cf.field->field_name.str,
+ cf.field_name.str)) {
return(true);
}
goto processed_field;
@@ -7773,63 +9061,99 @@ processed_field:
return(false);
}
+/** Convert field type and length to InnoDB format */
+static void get_type(const Field& f, ulint& prtype, ulint& mtype, ulint& len)
+{
+ mtype = get_innobase_type_from_mysql_type(&prtype, &f);
+ len = f.pack_length();
+ prtype |= f.type();
+ if (f.type() == MYSQL_TYPE_VARCHAR) {
+ auto l = static_cast<const Field_varstring&>(f).length_bytes;
+ len -= l;
+ if (l == 2) prtype |= DATA_LONG_TRUE_VARCHAR;
+ }
+ if (!f.real_maybe_null()) prtype |= DATA_NOT_NULL;
+ if (f.binary()) prtype |= DATA_BINARY_TYPE;
+ if (f.table->versioned()) {
+ if (&f == f.table->field[f.table->s->vers.start_fieldno]) {
+ prtype |= DATA_VERS_START;
+ } else if (&f == f.table->field[f.table->s->vers.end_fieldno]) {
+ prtype |= DATA_VERS_END;
+ } else if (!(f.flags & VERS_UPDATE_UNVERSIONED_FLAG)) {
+ prtype |= DATA_VERSIONED;
+ }
+ }
+ if (!f.stored_in_db()) prtype |= DATA_VIRTUAL;
+
+ if (dtype_is_string_type(mtype)) {
+ prtype |= ulint(f.charset()->number) << 16;
+ }
+}
+
/** Enlarge a column in the data dictionary tables.
-@param user_table InnoDB table that was being altered
+@param ctx In-place ALTER TABLE context
@param trx data dictionary transaction
@param table_name Table name in MySQL
-@param nth_col 0-based index of the column
-@param new_len new column length, in bytes
+@param pos 0-based index to user_table->cols[] or user_table->v_cols[]
+@param f new column
@param is_v if it's a virtual column
@retval true Failure
@retval false Success */
static MY_ATTRIBUTE((nonnull, warn_unused_result))
bool
-innobase_enlarge_column_try(
-/*========================*/
- const dict_table_t* user_table,
+innobase_rename_or_enlarge_column_try(
+ ha_innobase_inplace_ctx*ctx,
trx_t* trx,
const char* table_name,
- ulint nth_col,
- ulint new_len,
+ ulint pos,
+ const Field& f,
bool is_v)
{
- pars_info_t* info;
- dberr_t error;
-#ifdef UNIV_DEBUG
dict_col_t* col;
-#endif /* UNIV_DEBUG */
- dict_v_col_t* v_col;
- ulint pos;
+ dict_table_t* user_table = ctx->old_table;
- DBUG_ENTER("innobase_enlarge_column_try");
+ DBUG_ENTER("innobase_rename_or_enlarge_column_try");
+ DBUG_ASSERT(!ctx->need_rebuild());
DBUG_ASSERT(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
+
+ ulint n_base;
if (is_v) {
- v_col = dict_table_get_nth_v_col(user_table, nth_col);
+ dict_v_col_t* v_col= dict_table_get_nth_v_col(user_table, pos);
pos = dict_create_v_col_pos(v_col->v_pos, v_col->m_col.ind);
-#ifdef UNIV_DEBUG
col = &v_col->m_col;
-#endif /* UNIV_DEBUG */
+ n_base = v_col->num_base;
} else {
-#ifdef UNIV_DEBUG
- col = dict_table_get_nth_col(user_table, nth_col);
-#endif /* UNIV_DEBUG */
- pos = nth_col;
+ col = dict_table_get_nth_col(user_table, pos);
+ n_base = 0;
}
+ ulint prtype, mtype, len;
+ get_type(f, prtype, mtype, len);
+ DBUG_ASSERT(!dtype_is_string_type(col->mtype)
+ || col->mbminlen == f.charset()->mbminlen);
+ DBUG_ASSERT(col->len <= len);
+
#ifdef UNIV_DEBUG
- ut_ad(col->len < new_len);
- switch (col->mtype) {
+ ut_ad(col->mbminlen <= col->mbmaxlen);
+ switch (mtype) {
case DATA_MYSQL:
- /* NOTE: we could allow this when !(prtype & DATA_BINARY_TYPE)
- and ROW_FORMAT is not REDUNDANT and mbminlen<mbmaxlen.
- That is, we treat a UTF-8 CHAR(n) column somewhat like
- a VARCHAR. */
- ut_error;
+ if (!(prtype & DATA_BINARY_TYPE) || user_table->not_redundant()
+ || col->mbminlen != col->mbmaxlen) {
+ /* NOTE: we could allow this when !(prtype &
+ DATA_BINARY_TYPE) and ROW_FORMAT is not REDUNDANT and
+ mbminlen<mbmaxlen. That is, we treat a UTF-8 CHAR(n)
+ column somewhat like a VARCHAR. */
+ break;
+ }
+ /* fall through */
+ case DATA_FIXBINARY:
+ case DATA_CHAR:
+ ut_ad(col->len == len);
+ break;
case DATA_BINARY:
case DATA_VARCHAR:
case DATA_VARMYSQL:
@@ -7837,60 +9161,61 @@ innobase_enlarge_column_try(
case DATA_BLOB:
break;
default:
- ut_error;
+ ut_ad(!((col->prtype ^ prtype) & ~DATA_VERSIONED));
+ ut_ad(col->mtype == mtype);
+ ut_ad(col->len == len);
}
#endif /* UNIV_DEBUG */
- info = pars_info_create();
- pars_info_add_ull_literal(info, "tableid", user_table->id);
- pars_info_add_int4_literal(info, "nth", pos);
- pars_info_add_int4_literal(info, "new", new_len);
+ const char* col_name = col->name(*user_table);
+ const bool same_name = !strcmp(col_name, f.field_name.str);
- trx->op_info = "resizing column in SYS_COLUMNS";
-
- error = que_eval_sql(
- info,
- "PROCEDURE RESIZE_SYS_COLUMNS_PROC () IS\n"
- "BEGIN\n"
- "UPDATE SYS_COLUMNS SET LEN=:new\n"
- "WHERE TABLE_ID=:tableid AND POS=:nth;\n"
- "END;\n",
- FALSE, trx);
-
- DBUG_EXECUTE_IF("ib_resize_column_error",
- error = DB_OUT_OF_FILE_SPACE;);
-
- trx->op_info = "";
- trx->error_state = DB_SUCCESS;
-
- if (error != DB_SUCCESS) {
- my_error_innodb(error, table_name, 0);
+ if (!same_name
+ && innobase_rename_column_try(*ctx, trx, table_name,
+ col_name, f.field_name.str)) {
DBUG_RETURN(true);
}
- DBUG_RETURN(false);
+ if (same_name
+ && col->prtype == prtype && col->mtype == mtype
+ && col->len == len) {
+ DBUG_RETURN(false);
+ }
+
+ DBUG_RETURN(innodb_insert_sys_columns(user_table->id, pos,
+ f.field_name.str,
+ mtype, prtype, len,
+ n_base, trx, true));
}
-/** Enlarge columns in the data dictionary tables.
+/** Rename or enlarge columns in the data dictionary cache
+as part of commit_try_norebuild().
@param ha_alter_info Data used during in-place alter.
-@param table the TABLE
-@param user_table InnoDB table that was being altered
+@param ctx In-place ALTER TABLE context
+@param altered_table metadata after ALTER TABLE
+@param table metadata before ALTER TABLE
@param trx data dictionary transaction
@param table_name Table name in MySQL
@retval true Failure
@retval false Success */
static MY_ATTRIBUTE((nonnull, warn_unused_result))
bool
-innobase_enlarge_columns_try(
-/*=========================*/
+innobase_rename_or_enlarge_columns_try(
Alter_inplace_info* ha_alter_info,
+ ha_innobase_inplace_ctx*ctx,
+ const TABLE* altered_table,
const TABLE* table,
- const dict_table_t* user_table,
trx_t* trx,
const char* table_name)
{
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
+ DBUG_ENTER("innobase_rename_or_enlarge_columns_try");
+
+ if (!(ha_alter_info->handler_flags
+ & (ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
+ | ALTER_COLUMN_NAME))) {
+ DBUG_RETURN(false);
+ }
+
ulint i = 0;
ulint num_v = 0;
@@ -7898,77 +9223,83 @@ innobase_enlarge_columns_try(
const bool is_v = !(*fp)->stored_in_db();
ulint idx = is_v ? num_v++ : i - num_v;
- cf_it.rewind();
- while (Create_field* cf = cf_it++) {
- if (cf->field == *fp) {
- if ((*fp)->is_equal(cf)
- == IS_EQUAL_PACK_LENGTH
- && innobase_enlarge_column_try(
- user_table, trx, table_name,
- idx, static_cast<ulint>(cf->length), is_v)) {
- return(true);
+ Field** af = altered_table->field;
+ for (const Create_field& cf :
+ ha_alter_info->alter_info->create_list) {
+ if (cf.field == *fp) {
+ if (innobase_rename_or_enlarge_column_try(
+ ctx, trx, table_name,
+ idx, **af, is_v)) {
+ DBUG_RETURN(true);
}
-
break;
}
+ af++;
}
}
- return(false);
+ DBUG_RETURN(false);
}
/** Rename or enlarge columns in the data dictionary cache
as part of commit_cache_norebuild().
@param ha_alter_info Data used during in-place alter.
-@param table the TABLE
+@param altered_table metadata after ALTER TABLE
+@param table metadata before ALTER TABLE
@param user_table InnoDB table that was being altered */
static MY_ATTRIBUTE((nonnull))
void
innobase_rename_or_enlarge_columns_cache(
/*=====================================*/
Alter_inplace_info* ha_alter_info,
+ const TABLE* altered_table,
const TABLE* table,
dict_table_t* user_table)
{
if (!(ha_alter_info->handler_flags
- & (ALTER_COLUMN_EQUAL_PACK_LENGTH
+ & (ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE
| ALTER_COLUMN_NAME))) {
return;
}
- List_iterator_fast<Create_field> cf_it(
- ha_alter_info->alter_info->create_list);
uint i = 0;
ulint num_v = 0;
for (Field** fp = table->field; *fp; fp++, i++) {
const bool is_virtual = !(*fp)->stored_in_db();
- cf_it.rewind();
- while (Create_field* cf = cf_it++) {
- if (cf->field != *fp) {
+ Field** af = altered_table->field;
+ for (Create_field& cf :
+ ha_alter_info->alter_info->create_list) {
+ if (cf.field != *fp) {
+ af++;
continue;
}
ulint col_n = is_virtual ? num_v : i - num_v;
-
- if ((*fp)->is_equal(cf) == IS_EQUAL_PACK_LENGTH) {
- if (is_virtual) {
- dict_table_get_nth_v_col(
- user_table, col_n)->m_col.len
- = cf->length;
- } else {
- dict_table_get_nth_col(
- user_table, col_n)->len
- = cf->length;
- }
- }
+ dict_col_t *col = is_virtual
+ ? &dict_table_get_nth_v_col(user_table, col_n)
+ ->m_col
+ : dict_table_get_nth_col(user_table, col_n);
+ const bool is_string= dtype_is_string_type(col->mtype);
+ DBUG_ASSERT(col->mbminlen
+ == (is_string
+ ? (*af)->charset()->mbminlen : 0));
+ ulint prtype, mtype, len;
+ get_type(**af, prtype, mtype, len);
+ DBUG_ASSERT(is_string == dtype_is_string_type(mtype));
+
+ col->prtype = prtype;
+ col->mtype = mtype;
+ col->len = len;
+ col->mbmaxlen = is_string
+ ? (*af)->charset()->mbmaxlen : 0;
if ((*fp)->flags & FIELD_IS_RENAMED) {
dict_mem_table_col_rename(
user_table, col_n,
- cf->field->field_name.str,
- cf->field_name.str, is_virtual);
+ cf.field->field_name.str,
+ (*af)->field_name.str, is_virtual);
}
break;
@@ -8208,7 +9539,7 @@ innobase_update_foreign_cache(
DBUG_ENTER("innobase_update_foreign_cache");
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
user_table = ctx->old_table;
@@ -8361,27 +9692,24 @@ vers_change_fields_try(
DBUG_ASSERT(ha_alter_info);
DBUG_ASSERT(ctx);
- List_iterator_fast<Create_field> it(
- ha_alter_info->alter_info->create_list);
-
- while (const Create_field* create_field = it++) {
- if (!create_field->field) {
+ for (const Create_field& create_field : ha_alter_info->alter_info->create_list) {
+ if (!create_field.field) {
continue;
}
- if (create_field->versioning
+ if (create_field.versioning
== Column_definition::VERSIONING_NOT_SET) {
continue;
}
const dict_table_t* new_table = ctx->new_table;
- const uint pos = innodb_col_no(create_field->field);
+ const uint pos = innodb_col_no(create_field.field);
const dict_col_t* col = dict_table_get_nth_col(new_table, pos);
DBUG_ASSERT(!col->vers_sys_start());
DBUG_ASSERT(!col->vers_sys_end());
ulint new_prtype
- = create_field->versioning
+ = create_field.versioning
== Column_definition::WITHOUT_VERSIONING
? col->prtype & ~DATA_VERSIONED
: col->prtype | DATA_VERSIONED;
@@ -8414,23 +9742,21 @@ vers_change_fields_cache(
DBUG_ASSERT(ctx);
DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED);
- List_iterator_fast<Create_field> it(
- ha_alter_info->alter_info->create_list);
-
- while (const Create_field* create_field = it++) {
- if (!create_field->field || create_field->field->vcol_info) {
+ for (const Create_field& create_field :
+ ha_alter_info->alter_info->create_list) {
+ if (!create_field.field || create_field.field->vcol_info) {
continue;
}
dict_col_t* col = dict_table_get_nth_col(
- ctx->new_table, innodb_col_no(create_field->field));
+ ctx->new_table, innodb_col_no(create_field.field));
- if (create_field->versioning
+ if (create_field.versioning
== Column_definition::WITHOUT_VERSIONING) {
DBUG_ASSERT(!col->vers_sys_start());
DBUG_ASSERT(!col->vers_sys_end());
col->prtype &= ~DATA_VERSIONED;
- } else if (create_field->versioning
+ } else if (create_field.versioning
== Column_definition::WITH_VERSIONING) {
DBUG_ASSERT(!col->vers_sys_start());
@@ -8554,6 +9880,38 @@ commit_try_rebuild(
}
}
+/** Rename indexes in dictionary.
+@param[in] ctx alter info context
+@param[in] ha_alter_info Operation used during inplace alter
+@param[out] trx transaction to change the index name
+ in dictionary
+@return true if it failed to rename
+@return false if it is success. */
+static
+bool
+rename_indexes_try(
+ const ha_innobase_inplace_ctx* ctx,
+ const Alter_inplace_info* ha_alter_info,
+ trx_t* trx)
+{
+ DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_RENAME_INDEX);
+
+ for (const Alter_inplace_info::Rename_key_pair& pair :
+ ha_alter_info->rename_keys) {
+ dict_index_t* index = dict_table_get_index_on_name(
+ ctx->old_table, pair.old_key->name.str);
+ // This was checked previously in
+ // ha_innobase::prepare_inplace_alter_table()
+ ut_ad(index);
+
+ if (rename_index_try(index, pair.new_key->name.str, trx)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
/** Apply the changes made during commit_try_rebuild(),
to the data dictionary cache and the file system.
@param ctx In-place ALTER TABLE context */
@@ -8589,8 +9947,7 @@ commit_cache_rebuild(
/** Set of column numbers */
typedef std::set<ulint, std::less<ulint>, ut_allocator<ulint> > col_set;
-/** Store the column number of the columns in a list belonging
-to indexes which are not being dropped.
+/** Collect (not instantly dropped) columns from dropped indexes
@param[in] ctx In-place ALTER TABLE context
@param[in, out] drop_col_list list which will be set, containing columns
which is part of index being dropped
@@ -8599,7 +9956,7 @@ to indexes which are not being dropped.
being dropped */
static
void
-get_col_list_to_be_dropped(
+collect_columns_from_dropped_indexes(
const ha_innobase_inplace_ctx* ctx,
col_set& drop_col_list,
col_set& drop_v_col_list)
@@ -8620,6 +9977,12 @@ get_col_list_to_be_dropped(
} else {
ulint col_no = dict_col_get_no(idx_col);
+ if (ctx->col_map
+ && ctx->col_map[col_no]
+ == ULINT_UNDEFINED) {
+ // this column was instantly dropped
+ continue;
+ }
drop_col_list.insert(col_no);
}
}
@@ -8805,34 +10168,49 @@ commit_try_norebuild(
}
}
- if ((ha_alter_info->handler_flags
- & ALTER_COLUMN_NAME)
- && innobase_rename_columns_try(ha_alter_info, ctx, old_table,
- trx, table_name)) {
+ if (innobase_rename_or_enlarge_columns_try(ha_alter_info, ctx,
+ altered_table, old_table,
+ trx, table_name)) {
DBUG_RETURN(true);
}
- if ((ha_alter_info->handler_flags
- & ALTER_COLUMN_EQUAL_PACK_LENGTH)
- && innobase_enlarge_columns_try(ha_alter_info, old_table,
- ctx->old_table, trx, table_name)) {
+ if ((ha_alter_info->handler_flags & ALTER_RENAME_INDEX)
+ && rename_indexes_try(ctx, ha_alter_info, trx)) {
DBUG_RETURN(true);
}
- if ((ha_alter_info->handler_flags
- & ALTER_DROP_VIRTUAL_COLUMN)
- && innobase_drop_virtual_try(ha_alter_info, ctx->old_table, trx)) {
- DBUG_RETURN(true);
+ if (ctx->is_instant()) {
+ DBUG_RETURN(innobase_instant_try(ha_alter_info, ctx,
+ altered_table, old_table,
+ trx));
}
- if ((ha_alter_info->handler_flags
- & ALTER_ADD_VIRTUAL_COLUMN)
- && innobase_add_virtual_try(ha_alter_info, ctx->old_table, trx)) {
- DBUG_RETURN(true);
- }
+ if (ha_alter_info->handler_flags
+ & (ALTER_DROP_VIRTUAL_COLUMN | ALTER_ADD_VIRTUAL_COLUMN)) {
+ if ((ha_alter_info->handler_flags & ALTER_DROP_VIRTUAL_COLUMN)
+ && innobase_drop_virtual_try(ha_alter_info, ctx->old_table,
+ trx)) {
+ DBUG_RETURN(true);
+ }
- if (innobase_add_instant_try(ctx, altered_table, old_table, trx)) {
- DBUG_RETURN(true);
+ if ((ha_alter_info->handler_flags & ALTER_ADD_VIRTUAL_COLUMN)
+ && innobase_add_virtual_try(ha_alter_info, ctx->old_table,
+ trx)) {
+ DBUG_RETURN(true);
+ }
+
+ ulint n_col = unsigned(ctx->old_table->n_cols)
+ - DATA_N_SYS_COLS;
+ ulint n_v_col = unsigned(ctx->old_table->n_v_cols)
+ + ctx->num_to_add_vcol - ctx->num_to_drop_vcol;
+
+ if (innodb_update_cols(
+ ctx->old_table,
+ dict_table_encode_n_col(n_col, n_v_col)
+ | unsigned(ctx->old_table->flags & DICT_TF_COMPACT)
+ << 31, trx)) {
+ DBUG_RETURN(true);
+ }
}
DBUG_RETURN(false);
@@ -8842,6 +10220,7 @@ commit_try_norebuild(
after a successful commit_try_norebuild() call.
@param ha_alter_info algorithm=inplace context
@param ctx In-place ALTER TABLE context for the current partition
+@param altered_table the TABLE after the ALTER
@param table the TABLE before the ALTER
@param trx Data dictionary transaction
(will be started and committed, for DROP INDEX)
@@ -8852,6 +10231,7 @@ commit_cache_norebuild(
/*===================*/
Alter_inplace_info* ha_alter_info,
ha_innobase_inplace_ctx*ctx,
+ const TABLE* altered_table,
const TABLE* table,
trx_t* trx)
{
@@ -8874,11 +10254,17 @@ commit_cache_norebuild(
bool update = !(space->flags
& FSP_FLAGS_MASK_PAGE_COMPRESSION);
mutex_enter(&fil_system.mutex);
- space->flags = (~FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL
- & (space->flags
- | FSP_FLAGS_MASK_PAGE_COMPRESSION))
- | ctx->page_compression_level
+ space->flags &= ~FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL;
+ space->flags |= ctx->page_compression_level
<< FSP_FLAGS_MEM_COMPRESSION_LEVEL;
+ if (!space->full_crc32()) {
+ space->flags
+ |= FSP_FLAGS_MASK_PAGE_COMPRESSION;
+ } else if (!space->is_compressed()) {
+ space->flags
+ |= innodb_compression_algorithm
+ << FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO;
+ }
mutex_exit(&fil_system.mutex);
if (update) {
@@ -8896,7 +10282,7 @@ commit_cache_norebuild(
mtr.start();
if (buf_block_t* b = buf_page_get(
page_id_t(space->id, 0),
- page_size_t(space->flags),
+ space->zip_size(),
RW_X_LATCH, &mtr)) {
mtr.set_named_space(space);
mlog_write_ulint(
@@ -8913,25 +10299,21 @@ commit_cache_norebuild(
col_set drop_list;
col_set v_drop_list;
- col_set::const_iterator col_it;
/* Check if the column, part of an index to be dropped is part of any
other index which is not being dropped. If it so, then set the ord_part
of the column to 0. */
- get_col_list_to_be_dropped(ctx, drop_list, v_drop_list);
+ collect_columns_from_dropped_indexes(ctx, drop_list, v_drop_list);
- for (col_it = drop_list.begin(); col_it != drop_list.end(); ++col_it) {
- if (!check_col_exists_in_indexes(ctx->new_table,
- *col_it, false)) {
- ctx->new_table->cols[*col_it].ord_part = 0;
+ for (ulint col : drop_list) {
+ if (!check_col_exists_in_indexes(ctx->new_table, col, false)) {
+ ctx->new_table->cols[col].ord_part = 0;
}
}
- for (col_it = v_drop_list.begin();
- col_it != v_drop_list.end(); ++col_it) {
- if (!check_col_exists_in_indexes(ctx->new_table,
- *col_it, true)) {
- ctx->new_table->v_cols[*col_it].m_col.ord_part = 0;
+ for (ulint col : v_drop_list) {
+ if (!check_col_exists_in_indexes(ctx->new_table, col, true)) {
+ ctx->new_table->v_cols[col].m_col.ord_part = 0;
}
}
@@ -8999,13 +10381,57 @@ commit_cache_norebuild(
if (!ctx->is_instant()) {
innobase_rename_or_enlarge_columns_cache(
- ha_alter_info, table, ctx->new_table);
+ ha_alter_info, altered_table, table, ctx->new_table);
+ } else {
+ ut_ad(ctx->col_map);
+
+ if (fts_t* fts = ctx->new_table->fts) {
+ ut_ad(fts->doc_col != ULINT_UNDEFINED);
+ ut_ad(ctx->new_table->n_cols > DATA_N_SYS_COLS);
+ const ulint c = ctx->col_map[fts->doc_col];
+ ut_ad(c < ulint(ctx->new_table->n_cols)
+ - DATA_N_SYS_COLS);
+ ut_d(const dict_col_t& col = ctx->new_table->cols[c]);
+ ut_ad(!col.is_nullable());
+ ut_ad(!col.is_virtual());
+ ut_ad(!col.is_added());
+ ut_ad(col.prtype & DATA_UNSIGNED);
+ ut_ad(col.mtype == DATA_INT);
+ ut_ad(col.len == 8);
+ ut_ad(col.ord_part);
+ fts->doc_col = c;
+ }
+
+ if (ha_alter_info->handler_flags & ALTER_DROP_STORED_COLUMN) {
+ const dict_index_t* index = ctx->new_table->indexes.start;
+
+ for (const dict_field_t* f = index->fields,
+ * const end = f + index->n_fields;
+ f != end; f++) {
+ dict_col_t& c = *f->col;
+ if (c.is_dropped()) {
+ c.set_dropped(!c.is_nullable(),
+ DATA_LARGE_MTYPE(c.mtype)
+ || (!f->fixed_len
+ && c.len > 255),
+ f->fixed_len);
+ }
+ }
+ }
+
+ if (!ctx->instant_table->persistent_autoinc) {
+ ctx->new_table->persistent_autoinc = 0;
+ }
}
if (ha_alter_info->handler_flags & ALTER_COLUMN_UNVERSIONED) {
vers_change_fields_cache(ha_alter_info, ctx, table);
}
+ if (ha_alter_info->handler_flags & ALTER_RENAME_INDEX) {
+ innobase_rename_indexes_cache(ctx, ha_alter_info);
+ }
+
ctx->new_table->fts_doc_id_index
= ctx->new_table->fts
? dict_table_get_index_on_name(
@@ -9044,7 +10470,7 @@ alter_stats_norebuild(
in a separate transaction from trx, because lock waits are not
allowed in a data dictionary transaction. (Lock waits are possible
on the statistics table, because it is directly accessible by users,
- not covered by the dict_operation_lock.)
+ not covered by the dict_sys.latch.)
Because the data dictionary changes were already committed, orphaned
rows may be left in the statistics table if the system crashes.
@@ -9075,6 +10501,27 @@ alter_stats_norebuild(
}
}
+ for (const Alter_inplace_info::Rename_key_pair& pair :
+ ha_alter_info->rename_keys) {
+ dberr_t err = dict_stats_rename_index(ctx->new_table,
+ pair.old_key->name.str,
+ pair.new_key->name.str);
+
+ if (err != DB_SUCCESS) {
+ push_warning_printf(
+ thd,
+ Sql_condition::WARN_LEVEL_WARN,
+ ER_ERROR_ON_RENAME,
+ "Error renaming an index of table '%s'"
+ " from '%s' to '%s' in InnoDB persistent"
+ " statistics storage: %s",
+ ctx->new_table->name.m_name,
+ pair.old_key->name.str,
+ pair.new_key->name.str,
+ ut_strerr(err));
+ }
+ }
+
for (i = 0; i < ctx->num_to_add_index; i++) {
dict_index_t* index = ctx->add_index[i];
DBUG_ASSERT(index->table == ctx->new_table);
@@ -9110,23 +10557,8 @@ alter_stats_rebuild(
DBUG_VOID_RETURN;
}
-#ifndef DBUG_OFF
- bool file_unreadable_orig = false;
-#endif /* DBUG_OFF */
-
- DBUG_EXECUTE_IF(
- "ib_rename_index_fail2",
- file_unreadable_orig = table->file_unreadable;
- table->file_unreadable = true;
- );
-
dberr_t ret = dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT);
- DBUG_EXECUTE_IF(
- "ib_rename_index_fail2",
- table->file_unreadable = file_unreadable_orig;
- );
-
if (ret != DB_SUCCESS) {
push_warning_printf(
thd,
@@ -9700,7 +11132,8 @@ foreign_fail:
bool fk_fail = innobase_update_foreign_cache(
ctx, m_user_thd) != DB_SUCCESS;
- if (!commit_cache_norebuild(ha_alter_info, ctx, table,
+ if (!commit_cache_norebuild(ha_alter_info, ctx,
+ altered_table, table,
trx)) {
fk_fail = true;
}
@@ -9770,7 +11203,13 @@ foreign_fail:
}
}
- if (ctx0->num_to_drop_vcol || ctx0->num_to_add_vcol) {
+ /* MDEV-17468: Avoid this at least when ctx->is_instant().
+ Currently dict_load_column_low() is the only place where
+ num_base for virtual columns is assigned to nonzero. */
+ if (ctx0->num_to_drop_vcol || ctx0->num_to_add_vcol
+ || (ctx0->is_instant()
+ && m_prebuilt->table->n_v_cols
+ && ha_alter_info->handler_flags & ALTER_STORED_COLUMN_ORDER)) {
DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1);
trx_commit_for_mysql(m_prebuilt->trx);
@@ -9787,7 +11226,13 @@ foreign_fail:
tb_name[strlen(m_prebuilt->table->name.m_name)] = 0;
dict_table_close(m_prebuilt->table, true, false);
- dict_table_remove_from_cache(m_prebuilt->table);
+ if (ctx0->is_instant()) {
+ for (unsigned i = ctx0->old_n_v_cols; i--; ) {
+ ctx0->old_v_cols[i].~dict_v_col_t();
+ }
+ const_cast<unsigned&>(ctx0->old_n_v_cols) = 0;
+ }
+ dict_sys.remove(m_prebuilt->table);
m_prebuilt->table = dict_table_open_on_name(
tb_name, TRUE, TRUE, DICT_ERR_IGNORE_NONE);
@@ -9871,11 +11316,6 @@ foreign_fail:
DBUG_ASSERT(0 == strcmp(ctx->old_table->name.m_name,
ctx->tmp_name));
- DBUG_EXECUTE_IF(
- "ib_rename_index_fail3",
- DBUG_SET("+d,innodb_report_deadlock");
- );
-
if (dict_stats_drop_table(
ctx->new_table->name.m_name,
errstr, sizeof(errstr))
@@ -9891,11 +11331,6 @@ foreign_fail:
errstr);
}
- DBUG_EXECUTE_IF(
- "ib_rename_index_fail3",
- DBUG_SET("-d,innodb_report_deadlock");
- );
-
DBUG_EXECUTE_IF("ib_ddl_crash_before_commit",
DBUG_SUICIDE(););
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index ae3267ed623..50f056fd2c8 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -1650,12 +1650,12 @@ i_s_cmp_per_index_fill_low(
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name.str);
/* Create a snapshot of the stats so we do not bump into lock
- order violations with dict_sys->mutex below. */
+ order violations with dict_sys.mutex below. */
mutex_enter(&page_zip_stat_per_index_mutex);
page_zip_stat_per_index_t snap (page_zip_stat_per_index);
mutex_exit(&page_zip_stat_per_index_mutex);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
page_zip_stat_per_index_t::iterator iter;
ulint i;
@@ -1713,13 +1713,13 @@ i_s_cmp_per_index_fill_low(
contents of INFORMATION_SCHEMA.innodb_cmp_per_index being
inconsistent, but it is an acceptable compromise. */
if (i == 1000) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
i = 0;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (reset) {
page_zip_reset_stat_per_index();
@@ -2871,17 +2871,17 @@ i_s_fts_deleted_generic_fill(
/* Prevent DROP of the internal tables for fulltext indexes.
FIXME: acquire DDL-blocking MDL on the user table name! */
- rw_lock_s_lock(&dict_operation_lock);
+ rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_id(
innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (!user_table) {
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
} else if (!dict_table_has_fts_index(user_table)) {
dict_table_close(user_table, FALSE, FALSE);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@@ -2898,7 +2898,7 @@ i_s_fts_deleted_generic_fill(
dict_table_close(user_table, FALSE, FALSE);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
trx_free(trx);
@@ -3281,14 +3281,14 @@ i_s_fts_index_cache_fill(
/* Prevent DROP of the internal tables for fulltext indexes.
FIXME: acquire DDL-blocking MDL on the user table name! */
- rw_lock_s_lock(&dict_operation_lock);
+ rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_id(
innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (!user_table) {
no_fts:
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@@ -3316,7 +3316,7 @@ no_fts:
}
dict_table_close(user_table, FALSE, FALSE);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(ret);
}
@@ -3473,9 +3473,9 @@ i_s_fts_index_table_fill_selected(
}
}
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
que_graph_free(graph);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
trx_free(trx);
@@ -3728,13 +3728,13 @@ i_s_fts_index_table_fill(
/* Prevent DROP of the internal tables for fulltext indexes.
FIXME: acquire DDL-blocking MDL on the user table name! */
- rw_lock_s_lock(&dict_operation_lock);
+ rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_id(
innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (!user_table) {
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@@ -3754,7 +3754,7 @@ i_s_fts_index_table_fill(
dict_table_close(user_table, FALSE, FALSE);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
ut_free(conv_str.f_str);
@@ -3891,14 +3891,14 @@ i_s_fts_config_fill(
/* Prevent DROP of the internal tables for fulltext indexes.
FIXME: acquire DDL-blocking MDL on the user table name! */
- rw_lock_s_lock(&dict_operation_lock);
+ rw_lock_s_lock(&dict_sys.latch);
user_table = dict_table_open_on_id(
innodb_ft_aux_table_id, FALSE, DICT_TABLE_OP_NORMAL);
if (!user_table) {
no_fts:
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_RETURN(0);
}
@@ -3962,7 +3962,7 @@ no_fts:
dict_table_close(user_table, FALSE, FALSE);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
trx_free(trx);
@@ -4854,7 +4854,7 @@ i_s_innodb_buffer_page_fill(
if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
bool ret = false;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
const dict_index_t* index =
dict_index_get_if_in_cache_low(
@@ -4879,7 +4879,7 @@ i_s_innodb_buffer_page_fill(
system_charset_info);
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
OK(ret);
@@ -5577,7 +5577,7 @@ i_s_innodb_buf_page_lru_fill(
if (page_info->page_type == I_S_PAGE_TYPE_INDEX) {
bool ret = false;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
const dict_index_t* index =
dict_index_get_if_in_cache_low(
@@ -5602,7 +5602,7 @@ i_s_innodb_buf_page_lru_fill(
system_charset_info);
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
OK(ret);
@@ -5971,7 +5971,7 @@ i_s_dict_fill_sys_tables(
ulint compact = DICT_TF_GET_COMPACT(table->flags);
ulint atomic_blobs = DICT_TF_HAS_ATOMIC_BLOBS(
table->flags);
- const page_size_t& page_size = dict_tf_get_page_size(table->flags);
+ const ulint zip_size = dict_tf_get_zip_size(table->flags);
const char* row_format;
if (!compact) {
@@ -6000,10 +6000,7 @@ i_s_dict_fill_sys_tables(
OK(field_store_string(fields[SYS_TABLES_ROW_FORMAT], row_format));
- OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(
- page_size.is_compressed()
- ? page_size.physical()
- : 0, true));
+ OK(fields[SYS_TABLES_ZIP_PAGE_SIZE]->store(zip_size, true));
OK(field_store_string(fields[SYS_TABLES_SPACE_TYPE],
table->space_id ? "Single" : "System"));
@@ -6038,7 +6035,7 @@ i_s_sys_tables_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
@@ -6052,7 +6049,7 @@ i_s_sys_tables_fill_table(
err_msg = dict_process_sys_tables_rec_and_mtr_commit(
heap, rec, &table_rec, false, &mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_tables(thd, table_rec,
@@ -6070,13 +6067,13 @@ i_s_sys_tables_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -6266,7 +6263,7 @@ i_s_dict_fill_sys_tablestats(
OK(field_store_string(fields[SYS_TABLESTATS_NAME],
table->name.m_name));
- dict_table_stats_lock(table, RW_S_LATCH);
+ rw_lock_s_lock(&table->stats_latch);
if (table->stat_initialized) {
OK(field_store_string(fields[SYS_TABLESTATS_INIT],
@@ -6296,7 +6293,7 @@ i_s_dict_fill_sys_tablestats(
OK(fields[SYS_TABLESTATS_MODIFIED]->store(0, true));
}
- dict_table_stats_unlock(table, RW_S_LATCH);
+ rw_lock_s_unlock(&table->stats_latch);
OK(fields[SYS_TABLESTATS_AUTONINC]->store(table->autoinc, true));
@@ -6334,8 +6331,8 @@ i_s_sys_tables_fill_table_stats(
}
heap = mem_heap_create(1000);
- rw_lock_s_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ rw_lock_s_lock(&dict_sys.latch);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_TABLES);
@@ -6350,7 +6347,7 @@ i_s_sys_tables_fill_table_stats(
heap, rec, &table_rec, true, &mtr);
ulint ref_count = table_rec ? table_rec->get_ref_count() : 0;
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
DBUG_EXECUTE_IF("test_sys_tablestats", {
if (strcmp("test/t1", table_rec->name.m_name) == 0 ) {
@@ -6368,20 +6365,20 @@ i_s_sys_tables_fill_table_stats(
err_msg);
}
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
mem_heap_empty(heap);
/* Get the next record */
- rw_lock_s_lock(&dict_operation_lock);
- mutex_enter(&dict_sys->mutex);
+ rw_lock_s_lock(&dict_sys.latch);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
- rw_lock_s_unlock(&dict_operation_lock);
+ mutex_exit(&dict_sys.mutex);
+ rw_lock_s_unlock(&dict_sys.latch);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -6621,7 +6618,7 @@ i_s_sys_indexes_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
/* Start scan the SYS_INDEXES table */
@@ -6643,7 +6640,7 @@ i_s_sys_indexes_fill_table(
space_id = space_id == 4 ? mach_read_from_4(field)
: ULINT_UNDEFINED;
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
if (int err = i_s_dict_fill_sys_indexes(
@@ -6661,13 +6658,13 @@ i_s_sys_indexes_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -6874,7 +6871,7 @@ i_s_sys_columns_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_COLUMNS);
@@ -6892,7 +6889,7 @@ i_s_sys_columns_fill_table(
&nth_v_col);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_columns(thd, table_id, col_name,
@@ -6907,13 +6904,13 @@ i_s_sys_columns_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -7083,7 +7080,7 @@ i_s_sys_virtual_fill_table(
DBUG_RETURN(0);
}
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_VIRTUAL);
@@ -7099,7 +7096,7 @@ i_s_sys_virtual_fill_table(
&base_pos);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_virtual(thd, table_id, pos, base_pos,
@@ -7111,13 +7108,13 @@ i_s_sys_virtual_fill_table(
}
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
DBUG_RETURN(0);
}
@@ -7283,7 +7280,7 @@ i_s_sys_fields_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
/* will save last index id so that we know whether we move to
@@ -7304,7 +7301,7 @@ i_s_sys_fields_fill_table(
&pos, &index_id, last_id);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_fields(thd, index_id, &field_rec,
@@ -7319,13 +7316,13 @@ i_s_sys_fields_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -7515,7 +7512,7 @@ i_s_sys_foreign_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN);
@@ -7529,7 +7526,7 @@ i_s_sys_foreign_fill_table(
err_msg = dict_process_sys_foreign_rec(heap, rec, &foreign_rec);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_foreign(thd, &foreign_rec,
@@ -7544,12 +7541,12 @@ i_s_sys_foreign_fill_table(
/* Get the next record */
mtr_start(&mtr);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -7729,7 +7726,7 @@ i_s_sys_foreign_cols_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_FOREIGN_COLS);
@@ -7746,7 +7743,7 @@ i_s_sys_foreign_cols_fill_table(
heap, rec, &name, &for_col_name, &ref_col_name, &pos);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_foreign_cols(
@@ -7761,13 +7758,13 @@ i_s_sys_foreign_cols_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -7960,7 +7957,9 @@ i_s_dict_fill_sys_tablespaces(
DBUG_ENTER("i_s_dict_fill_sys_tablespaces");
- if (is_system_tablespace(space)) {
+ if (fil_space_t::full_crc32(flags)) {
+ row_format = NULL;
+ } else if (is_system_tablespace(space)) {
row_format = "Compact, Redundant or Dynamic";
} else if (FSP_FLAGS_GET_ZIP_SSIZE(flags)) {
row_format = "Compressed";
@@ -7984,7 +7983,7 @@ i_s_dict_fill_sys_tablespaces(
is_system_tablespace(space)
? "System" : "Single"));
- ulint cflags = fsp_flags_is_valid(flags, space)
+ ulint cflags = fil_space_t::is_valid_flags(flags, space)
? flags : fsp_flags_convert_from_101(flags);
if (cflags == ULINT_UNDEFINED) {
fields[SYS_TABLESPACES_PAGE_SIZE]->set_null();
@@ -7996,13 +7995,11 @@ i_s_dict_fill_sys_tablespaces(
DBUG_RETURN(0);
}
- const page_size_t page_size(cflags);
-
OK(fields[SYS_TABLESPACES_PAGE_SIZE]->store(
- page_size.logical(), true));
+ fil_space_t::logical_size(cflags), true));
OK(fields[SYS_TABLESPACES_ZIP_PAGE_SIZE]->store(
- page_size.physical(), true));
+ fil_space_t::physical_size(cflags), true));
os_file_stat_t stat;
os_file_size_t file;
@@ -8087,7 +8084,7 @@ i_s_sys_tablespaces_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
for (rec = dict_startscan_system(&pcur, &mtr, SYS_TABLESPACES);
@@ -8104,7 +8101,7 @@ i_s_sys_tablespaces_fill_table(
heap, rec, &space, &name, &flags);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_tablespaces(
@@ -8119,12 +8116,12 @@ i_s_sys_tablespaces_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -8278,7 +8275,7 @@ i_s_sys_datafiles_fill_table(
}
heap = mem_heap_create(1000);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_startscan_system(&pcur, &mtr, SYS_DATAFILES);
@@ -8293,7 +8290,7 @@ i_s_sys_datafiles_fill_table(
heap, rec, &space, &path);
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
if (!err_msg) {
i_s_dict_fill_sys_datafiles(
@@ -8307,13 +8304,13 @@ i_s_sys_datafiles_fill_table(
mem_heap_empty(heap);
/* Get the next record */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
mtr_start(&mtr);
rec = dict_getnext_system(&pcur, &mtr);
}
mtr_commit(&mtr);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
mem_heap_free(heap);
DBUG_RETURN(0);
@@ -8687,7 +8684,7 @@ static ST_FIELD_INFO innodb_tablespaces_scrubbing_fields_info[] =
#define TABLESPACES_SCRUBBING_COMPRESSED 2
{STRUCT_FLD(field_name, "COMPRESSED"),
- STRUCT_FLD(field_length, MY_INT32_NUM_DECIMAL_DIGITS),
+ STRUCT_FLD(field_length, 1),
STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
@@ -8739,6 +8736,15 @@ static ST_FIELD_INFO innodb_tablespaces_scrubbing_fields_info[] =
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+#define TABLESPACES_SCRUBBING_ON_SSD 8
+ {STRUCT_FLD(field_name, "ON_SSD"),
+ STRUCT_FLD(field_length, 1),
+ STRUCT_FLD(field_type, MYSQL_TYPE_LONG),
+ STRUCT_FLD(value, 0),
+ STRUCT_FLD(field_flags, MY_I_S_UNSIGNED),
+ STRUCT_FLD(old_name, ""),
+ STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
+
END_OF_ST_FIELD_INFO
};
@@ -8810,6 +8816,8 @@ i_s_dict_fill_tablespaces_scrubbing(
}
}
+ OK(fields[TABLESPACES_SCRUBBING_ON_SSD]->store(!space->is_rotational(),
+ true));
OK(schema_table_store_record(thd, table_to_fill));
DBUG_RETURN(0);
diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc
index 26ba7f6a388..a0fe5306e65 100644
--- a/storage/innobase/ibuf/ibuf0ibuf.cc
+++ b/storage/innobase/ibuf/ibuf0ibuf.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2020 MariaDB Corporation.
+Copyright (c) 2016, 2020, 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
@@ -338,7 +338,7 @@ ibuf_header_page_get(
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_HEADER_PAGE_NO),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
if (block) {
buf_block_dbg_add_level(block, SYNC_IBUF_HEADER);
@@ -368,7 +368,7 @@ ibuf_tree_root_get(
/* only segment list access is exclusive each other */
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
- univ_page_size, RW_SX_LATCH, mtr);
+ 0, RW_SX_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
@@ -483,7 +483,7 @@ ibuf_init_at_db_start(void)
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, FSP_IBUF_TREE_ROOT_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -548,13 +548,8 @@ ibuf_max_size_update(
}
-/*********************************************************************//**
-Initializes an ibuf bitmap page. */
-void
-ibuf_bitmap_page_init(
-/*==================*/
- buf_block_t* block, /*!< in: bitmap page */
- mtr_t* mtr) /*!< in: mtr */
+/** Apply MLOG_IBUF_BITMAP_INIT when crash-upgrading */
+ATTRIBUTE_COLD void ibuf_bitmap_init_apply(buf_block_t* block)
{
page_t* page;
ulint byte_offset;
@@ -565,65 +560,41 @@ ibuf_bitmap_page_init(
/* Write all zeros to the bitmap */
compile_time_assert(!(IBUF_BITS_PER_PAGE % 2));
- byte_offset = UT_BITS_IN_BYTES(block->page.size.physical()
+ byte_offset = UT_BITS_IN_BYTES(block->physical_size()
* IBUF_BITS_PER_PAGE);
memset(page + IBUF_BITMAP, 0, byte_offset);
-
- /* The remaining area (up to the page trailer) is uninitialized. */
- mlog_write_initial_log_record(page, MLOG_IBUF_BITMAP_INIT, mtr);
-}
-
-/*********************************************************************//**
-Parses a redo log record of an ibuf bitmap page init.
-@return end of log record or NULL */
-byte*
-ibuf_parse_bitmap_init(
-/*===================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr MY_ATTRIBUTE((unused)), /*!< in: buffer end */
- buf_block_t* block, /*!< in: block or NULL */
- mtr_t* mtr) /*!< in: mtr or NULL */
-{
- ut_ad(ptr != NULL);
- ut_ad(end_ptr != NULL);
-
- if (block) {
- ibuf_bitmap_page_init(block, mtr);
- }
-
- return(ptr);
}
# ifdef UNIV_DEBUG
/** Gets the desired bits for a given page from a bitmap page.
@param[in] page bitmap page
@param[in] page_id page id whose bits to get
-@param[in] page_size page id whose bits to get
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in,out] mtr mini-transaction holding an x-latch on the
bitmap page
@return value of bits */
-# define ibuf_bitmap_page_get_bits(page, page_id, page_size, bit, mtr) \
- ibuf_bitmap_page_get_bits_low(page, page_id, page_size, \
+# define ibuf_bitmap_page_get_bits(page, page_id, zip_size, bit, mtr) \
+ ibuf_bitmap_page_get_bits_low(page, page_id, zip_size, \
MTR_MEMO_PAGE_X_FIX, mtr, bit)
# else /* UNIV_DEBUG */
/** Gets the desired bits for a given page from a bitmap page.
@param[in] page bitmap page
@param[in] page_id page id whose bits to get
-@param[in] page_size page id whose bits to get
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in,out] mtr mini-transaction holding an x-latch on the
bitmap page
@return value of bits */
-# define ibuf_bitmap_page_get_bits(page, page_id, page_size, bit, mtr) \
- ibuf_bitmap_page_get_bits_low(page, page_id, page_size, bit)
+# define ibuf_bitmap_page_get_bits(page, page_id, zip_size, bit, mtr) \
+ ibuf_bitmap_page_get_bits_low(page, page_id, zip_size, bit)
# endif /* UNIV_DEBUG */
/** Gets the desired bits for a given page from a bitmap page.
@param[in] page bitmap page
@param[in] page_id page id whose bits to get
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] latch_type MTR_MEMO_PAGE_X_FIX, MTR_MEMO_BUF_FIX, ...
@param[in,out] mtr mini-transaction holding latch_type on the
bitmap page
@@ -634,7 +605,7 @@ ulint
ibuf_bitmap_page_get_bits_low(
const page_t* page,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
#ifdef UNIV_DEBUG
ulint latch_type,
mtr_t* mtr,
@@ -645,12 +616,14 @@ ibuf_bitmap_page_get_bits_low(
ulint bit_offset;
ulint map_byte;
ulint value;
+ const ulint size = zip_size ? zip_size : srv_page_size;
+ ut_ad(ut_is_2pow(zip_size));
ut_ad(bit < IBUF_BITS_PER_PAGE);
compile_time_assert(!(IBUF_BITS_PER_PAGE % 2));
ut_ad(mtr_memo_contains_page(mtr, page, latch_type));
- bit_offset = (page_id.page_no() % page_size.physical())
+ bit_offset = (page_id.page_no() & (size - 1))
* IBUF_BITS_PER_PAGE + bit;
byte_offset = bit_offset / 8;
@@ -674,7 +647,7 @@ ibuf_bitmap_page_get_bits_low(
/** Sets the desired bit for a given page in a bitmap page.
@param[in,out] page bitmap page
@param[in] page_id page id whose bits to set
-@param[in] page_size page size
+@param[in] physical_size page size
@param[in] bit IBUF_BITMAP_FREE, IBUF_BITMAP_BUFFERED, ...
@param[in] val value to set
@param[in,out] mtr mtr containing an x-latch to the bitmap page */
@@ -683,7 +656,7 @@ void
ibuf_bitmap_page_set_bits(
page_t* page,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint physical_size,
ulint bit,
ulint val,
mtr_t* mtr)
@@ -697,7 +670,7 @@ ibuf_bitmap_page_set_bits(
ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr->is_named_space(page_id.space()));
- bit_offset = (page_id.page_no() % page_size.physical())
+ bit_offset = (page_id.page_no() % physical_size)
* IBUF_BITS_PER_PAGE + bit;
byte_offset = bit_offset / 8;
@@ -724,26 +697,20 @@ ibuf_bitmap_page_set_bits(
/** Calculates the bitmap page number for a given page number.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] size page size
@return the bitmap page id where the file page is mapped */
-UNIV_INLINE
-const page_id_t
-ibuf_bitmap_page_no_calc(
- const page_id_t page_id,
- const page_size_t& page_size)
+inline page_id_t ibuf_bitmap_page_no_calc(const page_id_t page_id, ulint size)
{
- ulint bitmap_page_no;
-
- bitmap_page_no = FSP_IBUF_BITMAP_OFFSET
- + (page_id.page_no() & ~(page_size.physical() - 1));
+ if (!size) size = srv_page_size;
- return(page_id_t(page_id.space(), bitmap_page_no));
+ return page_id_t(page_id.space(), FSP_IBUF_BITMAP_OFFSET
+ + (page_id.page_no() & ~(size - 1)));
}
/** Gets the ibuf bitmap page where the bits describing a given file page are
stored.
@param[in] page_id page id of the file page
-@param[in] page_size page size of the file page
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] file file name
@param[in] line line where called
@param[in,out] mtr mini-transaction
@@ -754,7 +721,7 @@ static
page_t*
ibuf_bitmap_get_map_page_func(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
const char* file,
unsigned line,
mtr_t* mtr)
@@ -762,8 +729,8 @@ ibuf_bitmap_get_map_page_func(
buf_block_t* block = NULL;
dberr_t err = DB_SUCCESS;
- block = buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, page_size),
- page_size, RW_X_LATCH, NULL, BUF_GET,
+ block = buf_page_get_gen(ibuf_bitmap_page_no_calc(page_id, zip_size),
+ zip_size, RW_X_LATCH, NULL, BUF_GET,
file, line, mtr, &err);
if (err != DB_SUCCESS) {
@@ -779,13 +746,13 @@ ibuf_bitmap_get_map_page_func(
/** Gets the ibuf bitmap page where the bits describing a given file page are
stored.
@param[in] page_id page id of the file page
-@param[in] page_size page size of the file page
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction
@return bitmap page where the file page is mapped, that is, the bitmap
page containing the descriptor bits for the file page; the bitmap page
is x-latched */
-#define ibuf_bitmap_get_map_page(page_id, page_size, mtr) \
- ibuf_bitmap_get_map_page_func(page_id, page_size, \
+#define ibuf_bitmap_get_map_page(page_id, zip_size, mtr) \
+ ibuf_bitmap_get_map_page_func(page_id, zip_size, \
__FILE__, __LINE__, mtr)
/************************************************************************//**
@@ -819,14 +786,14 @@ ibuf_set_free_bits_low(
}
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, mtr);
+ block->zip_size(), mtr);
#ifdef UNIV_IBUF_DEBUG
ut_a(val <= ibuf_index_page_calc_free(block));
#endif /* UNIV_IBUF_DEBUG */
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, val, mtr);
}
@@ -863,17 +830,14 @@ ibuf_set_free_bits_func(
block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, &mtr);
+ block->zip_size(), &mtr);
switch (space->purpose) {
case FIL_TYPE_LOG:
ut_ad(0);
break;
case FIL_TYPE_TABLESPACE:
- /* Avoid logging while fixing up truncate of table. */
- if (!srv_is_tablespace_truncated(block->page.id.space())) {
- break;
- }
+ break;
/* fall through */
case FIL_TYPE_TEMPORARY:
case FIL_TYPE_IMPORT:
@@ -908,7 +872,7 @@ ibuf_set_free_bits_func(
#endif /* UNIV_IBUF_DEBUG */
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, val, &mtr);
mtr_commit(&mtr);
@@ -958,7 +922,7 @@ ibuf_update_free_bits_low(
ut_a(!buf_block_get_page_zip(block));
ut_ad(mtr->is_named_space(block->page.id.space()));
- before = ibuf_index_page_calc_free_bits(block->page.size.logical(),
+ before = ibuf_index_page_calc_free_bits(srv_page_size,
max_ins_size);
after = ibuf_index_page_calc_free(block);
@@ -993,10 +957,10 @@ ibuf_update_free_bits_zip(
buf_frame_t* frame = buf_block_get_frame(block);
ut_a(frame);
ut_a(page_is_leaf(frame));
- ut_a(block->page.size.is_compressed());
+ ut_a(block->zip_size());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, mtr);
+ block->zip_size(), mtr);
after = ibuf_index_page_calc_free_zip(block);
@@ -1010,7 +974,7 @@ ibuf_update_free_bits_zip(
}
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, after, mtr);
}
@@ -1052,23 +1016,19 @@ ibuf_update_free_bits_for_two_pages_low(
/** Returns TRUE if the page is one of the fixed address ibuf pages.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return TRUE if a fixed address ibuf i/o page */
-UNIV_INLINE
-ibool
-ibuf_fixed_addr_page(
- const page_id_t page_id,
- const page_size_t& page_size)
+inline bool ibuf_fixed_addr_page(const page_id_t page_id, ulint zip_size)
{
return((page_id.space() == IBUF_SPACE_ID
&& page_id.page_no() == IBUF_TREE_ROOT_PAGE_NO)
- || ibuf_bitmap_page(page_id, page_size));
+ || ibuf_bitmap_page(page_id, zip_size));
}
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] x_latch FALSE if relaxed check (avoid latching the
bitmap page)
@param[in] file file name
@@ -1077,12 +1037,12 @@ bitmap page)
bitmap page if the page is not one of the fixed address ibuf pages, or NULL,
in which case a new transaction is created.
@return TRUE if level 2 or level 3 page */
-ibool
+bool
ibuf_page_low(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
#ifdef UNIV_DEBUG
- ibool x_latch,
+ bool x_latch,
#endif /* UNIV_DEBUG */
const char* file,
unsigned line,
@@ -1095,12 +1055,10 @@ ibuf_page_low(
ut_ad(!recv_no_ibuf_operations);
ut_ad(x_latch || mtr == NULL);
- if (ibuf_fixed_addr_page(page_id, page_size)) {
-
- return(TRUE);
+ if (ibuf_fixed_addr_page(page_id, zip_size)) {
+ return(true);
} else if (page_id.space() != IBUF_SPACE_ID) {
-
- return(FALSE);
+ return(false);
}
compile_time_assert(IBUF_SPACE_ID == 0);
@@ -1123,14 +1081,14 @@ ibuf_page_low(
dberr_t err = DB_SUCCESS;
buf_block_t* block = buf_page_get_gen(
- ibuf_bitmap_page_no_calc(page_id, page_size),
- page_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
- file, line, &local_mtr, &err);
+ ibuf_bitmap_page_no_calc(page_id, zip_size),
+ zip_size, RW_NO_LATCH, NULL, BUF_GET_NO_LATCH,
+ file, line, &local_mtr, &err);
bitmap_page = buf_block_get_frame(block);
ret = ibuf_bitmap_page_get_bits_low(
- bitmap_page, page_id, page_size,
+ bitmap_page, page_id, zip_size,
MTR_MEMO_BUF_FIX, &local_mtr, IBUF_BITMAP_IBUF);
mtr_commit(&local_mtr);
@@ -1143,10 +1101,10 @@ ibuf_page_low(
mtr_start(mtr);
}
- bitmap_page = ibuf_bitmap_get_map_page_func(page_id, page_size,
+ bitmap_page = ibuf_bitmap_get_map_page_func(page_id, zip_size,
file, line, mtr);
- ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, page_size,
+ ret = ibuf_bitmap_page_get_bits(bitmap_page, page_id, zip_size,
IBUF_BITMAP_IBUF, mtr);
if (mtr == &local_mtr) {
@@ -1389,32 +1347,26 @@ ibuf_rec_get_counter(
}
}
-/****************************************************************//**
-Add accumulated operation counts to a permanent array. Both arrays must be
-of size IBUF_OP_COUNT. */
-static
-void
-ibuf_add_ops(
-/*=========*/
- ulint* arr, /*!< in/out: array to modify */
- const ulint* ops) /*!< in: operation counts */
+/**
+ Add accumulated operation counts to a permanent array.
+ Both arrays must be of size IBUF_OP_COUNT.
+*/
+static void ibuf_add_ops(Atomic_counter<ulint> *out, const ulint *in)
{
- ulint i;
-
- for (i = 0; i < IBUF_OP_COUNT; i++) {
- my_atomic_addlint(&arr[i], ops[i]);
- }
+ for (auto i = 0; i < IBUF_OP_COUNT; i++)
+ out[i]+= in[i];
}
+
/****************************************************************//**
Print operation counts. The array must be of size IBUF_OP_COUNT. */
static
void
ibuf_print_ops(
/*===========*/
- const ulint* ops, /*!< in: operation counts */
- FILE* file) /*!< in: file where to print */
+ const Atomic_counter<ulint>* ops, /*!< in: operation counts */
+ FILE* file) /*!< in: file where to print */
{
static const char* op_names[] = {
"insert",
@@ -1427,7 +1379,7 @@ ibuf_print_ops(
for (i = 0; i < IBUF_OP_COUNT; i++) {
fprintf(file, "%s " ULINTPF "%s", op_names[i],
- ops[i], (i < (IBUF_OP_COUNT - 1)) ? ", " : "");
+ ulint{ops[i]}, (i < (IBUF_OP_COUNT - 1)) ? ", " : "");
}
putc('\n', file);
@@ -2025,11 +1977,11 @@ ibuf_add_free_page(void)
(level 2 page) */
const page_id_t page_id(IBUF_SPACE_ID, block->page.id.page_no());
- bitmap_page = ibuf_bitmap_get_map_page(page_id, univ_page_size, &mtr);
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex);
- ibuf_bitmap_page_set_bits(bitmap_page, page_id, univ_page_size,
+ ibuf_bitmap_page_set_bits(bitmap_page, page_id, srv_page_size,
IBUF_BITMAP_IBUF, TRUE, &mtr);
ibuf_mtr_commit(&mtr);
@@ -2100,7 +2052,7 @@ ibuf_remove_free_page(void)
compile_time_assert(IBUF_SPACE_ID == 0);
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
- fil_system.sys_space, page_no, false, &mtr);
+ fil_system.sys_space, page_no, false, true, &mtr);
const page_id_t page_id(IBUF_SPACE_ID, page_no);
@@ -2118,7 +2070,7 @@ ibuf_remove_free_page(void)
{
buf_block_t* block;
- block = buf_page_get(page_id, univ_page_size, RW_X_LATCH, &mtr);
+ block = buf_page_get(page_id, 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -2138,13 +2090,13 @@ ibuf_remove_free_page(void)
/* Set the bit indicating that this page is no more an ibuf tree page
(level 2 page) */
- bitmap_page = ibuf_bitmap_get_map_page(page_id, univ_page_size, &mtr);
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, 0, &mtr);
mutex_exit(&ibuf_mutex);
ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, univ_page_size, IBUF_BITMAP_IBUF, FALSE,
- &mtr);
+ bitmap_page, page_id, srv_page_size,
+ IBUF_BITMAP_IBUF, FALSE, &mtr);
ut_d(buf_page_set_file_page_was_freed(page_id));
@@ -2994,7 +2946,7 @@ ibuf_get_volume_buffered(
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, prev_page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -3066,7 +3018,7 @@ count_later:
block = buf_page_get(
page_id_t(IBUF_SPACE_ID, next_page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE);
@@ -3279,6 +3231,24 @@ ibuf_get_entry_counter_func(
}
}
+
+/** Translates the ibuf free bits to the free space on a page in bytes.
+@param[in] physical_size page_size
+@param[in] bits value for ibuf bitmap bits
+@return maximum insert size after reorganize for the page */
+inline ulint
+ibuf_index_page_calc_free_from_bits(ulint physical_size, ulint bits)
+{
+ ut_ad(bits < 4);
+ ut_ad(physical_size > IBUF_PAGE_SIZE_PER_FREE_SPACE);
+
+ if (bits == 3) {
+ bits = 4;
+ }
+
+ return bits * physical_size / IBUF_PAGE_SIZE_PER_FREE_SPACE;
+}
+
/** Buffer an operation in the insert/delete buffer, instead of doing it
directly to the disk page, if this is possible.
@param[in] mode BTR_MODIFY_PREV or BTR_MODIFY_TREE
@@ -3290,7 +3260,7 @@ buffering
@param[in,out] index index where to insert; must not be unique
or clustered
@param[in] page_id page id where to insert
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] thr query thread
@return DB_SUCCESS, DB_STRONG_FAIL or other error */
static MY_ATTRIBUTE((warn_unused_result))
@@ -3303,7 +3273,7 @@ ibuf_insert_low(
ulint entry_size,
dict_index_t* index,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
que_thr_t* thr)
{
big_rec_t* dummy_big_rec;
@@ -3413,6 +3383,8 @@ ibuf_insert_low(
? &min_n_recs
: NULL, &mtr);
+ const ulint physical_size = zip_size ? zip_size : srv_page_size;
+
if (op == IBUF_OP_DELETE
&& (min_n_recs < 2 || buf_pool_watch_occurred(page_id))) {
/* The page could become empty after the record is
@@ -3454,8 +3426,7 @@ fail_exit:
ibuf_mtr_start(&bitmap_mtr);
index->set_modified(bitmap_mtr);
- bitmap_page = ibuf_bitmap_get_map_page(page_id, page_size,
- &bitmap_mtr);
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size, &bitmap_mtr);
/* We check if the index page is suitable for buffered entries */
@@ -3469,11 +3440,12 @@ fail_exit:
if (op == IBUF_OP_INSERT) {
ulint bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, page_size, IBUF_BITMAP_FREE,
+ bitmap_page, page_id, physical_size, IBUF_BITMAP_FREE,
&bitmap_mtr);
if (buffered + entry_size + page_dir_calc_reserved_space(1)
- > ibuf_index_page_calc_free_from_bits(page_size, bits)) {
+ > ibuf_index_page_calc_free_from_bits(physical_size,
+ bits)) {
/* Release the bitmap page latch early. */
ibuf_mtr_commit(&bitmap_mtr);
@@ -3516,11 +3488,11 @@ fail_exit:
buffered entries for this index page, if the bit is not set yet */
old_bit_value = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, page_size,
+ bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, &bitmap_mtr);
if (!old_bit_value) {
- ibuf_bitmap_page_set_bits(bitmap_page, page_id, page_size,
+ ibuf_bitmap_page_set_bits(bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, TRUE,
&bitmap_mtr);
}
@@ -3614,23 +3586,23 @@ func_exit:
return(err);
}
-/** Buffer an operation in the insert/delete buffer, instead of doing it
-directly to the disk page, if this is possible. Does not do it if the index
+/** Buffer an operation in the change buffer, instead of applying it
+directly to the file page, if this is possible. Does not do it if the index
is clustered or unique.
@param[in] op operation type
@param[in] entry index entry to insert
@param[in,out] index index where to insert
@param[in] page_id page id where to insert
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] thr query thread
-@return TRUE if success */
-ibool
+@return true if success */
+bool
ibuf_insert(
ibuf_op_t op,
const dtuple_t* entry,
dict_index_t* index,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
que_thr_t* thr)
{
dberr_t err;
@@ -3658,7 +3630,7 @@ ibuf_insert(
case IBUF_USE_NONE:
case IBUF_USE_DELETE:
case IBUF_USE_DELETE_MARK:
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
case IBUF_USE_INSERT:
case IBUF_USE_INSERT_DELETE_MARK:
case IBUF_USE_ALL:
@@ -3669,7 +3641,7 @@ ibuf_insert(
switch (use) {
case IBUF_USE_NONE:
case IBUF_USE_INSERT:
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
case IBUF_USE_DELETE_MARK:
case IBUF_USE_DELETE:
case IBUF_USE_INSERT_DELETE_MARK:
@@ -3683,7 +3655,7 @@ ibuf_insert(
case IBUF_USE_NONE:
case IBUF_USE_INSERT:
case IBUF_USE_INSERT_DELETE_MARK:
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
case IBUF_USE_DELETE_MARK:
case IBUF_USE_DELETE:
case IBUF_USE_ALL:
@@ -3723,7 +3695,7 @@ check_watch:
is being buffered, have this request executed
directly on the page in the buffer pool after the
buffered entries for this page have been merged. */
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
}
}
@@ -3734,30 +3706,22 @@ skip_watch:
>= page_get_free_space_of_empty(dict_table_is_comp(index->table))
/ 2) {
- DBUG_RETURN(FALSE);
+ DBUG_RETURN(false);
}
err = ibuf_insert_low(BTR_MODIFY_PREV, op, no_counter,
entry, entry_size,
- index, page_id, page_size, thr);
+ index, page_id, zip_size, thr);
if (err == DB_FAIL) {
err = ibuf_insert_low(BTR_MODIFY_TREE | BTR_LATCH_FOR_INSERT,
op, no_counter, entry, entry_size,
- index, page_id, page_size, thr);
+ index, page_id, zip_size, thr);
}
- if (err == DB_SUCCESS) {
-#ifdef UNIV_IBUF_DEBUG
- /* fprintf(stderr, "Ibuf insert for page no %lu of index %s\n",
- page_no, index->name); */
-#endif
- DBUG_RETURN(TRUE);
+ ut_a(err == DB_SUCCESS || err == DB_STRONG_FAIL
+ || err == DB_TOO_BIG_RECORD);
- } else {
- ut_a(err == DB_STRONG_FAIL || err == DB_TOO_BIG_RECORD);
-
- DBUG_RETURN(FALSE);
- }
+ DBUG_RETURN(err == DB_SUCCESS);
}
/********************************************************************//**
@@ -3821,13 +3785,13 @@ ibuf_insert_to_index_page_low(
"InnoDB: that table.\n", stderr);
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, mtr);
+ block->zip_size(), mtr);
old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->zip_size(),
IBUF_BITMAP_FREE, mtr);
ib::error() << "page " << block->page.id << ", size "
- << block->page.size.physical() << ", bitmap bits " << old_bits;
+ << block->physical_size() << ", bitmap bits " << old_bits;
ib::error() << BUG_REPORT_MSG;
@@ -4389,15 +4353,16 @@ subsequently was dropped.
@param[in,out] block if page has been read from disk,
pointer to the page x-latched, else NULL
@param[in] page_id page id of the index page
-@param[in] update_ibuf_bitmap normally this is set to TRUE, but
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] update_ibuf_bitmap normally this is set, but
if we have deleted or are deleting the tablespace, then we naturally do not
want to update a non-existent bitmap page */
void
ibuf_merge_or_delete_for_page(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t* page_size,
- ibool update_ibuf_bitmap)
+ ulint zip_size,
+ bool update_ibuf_bitmap)
{
btr_pcur_t pcur;
#ifdef UNIV_IBUF_DEBUG
@@ -4421,38 +4386,23 @@ ibuf_merge_or_delete_for_page(
return;
}
- /* We cannot refer to page_size in the following, because it is passed
- as NULL (it is unknown) when buf_read_ibuf_merge_pages() is merging
- (discarding) changes for a dropped tablespace. When block != NULL or
- update_ibuf_bitmap is specified, then page_size must be known.
- That is why we will repeat the check below, with page_size in
- place of univ_page_size. Passing univ_page_size assumes that the
- uncompressed page size always is a power-of-2 multiple of the
- compressed page size. */
-
- if (ibuf_fixed_addr_page(page_id, univ_page_size)
- || fsp_descr_page(page_id, univ_page_size)) {
+ const ulint physical_size = zip_size ? zip_size : srv_page_size;
+
+ if (ibuf_fixed_addr_page(page_id, physical_size)
+ || fsp_descr_page(page_id, physical_size)) {
return;
}
fil_space_t* space;
if (update_ibuf_bitmap) {
-
- ut_ad(page_size != NULL);
-
- if (ibuf_fixed_addr_page(page_id, *page_size)
- || fsp_descr_page(page_id, *page_size)) {
- return;
- }
-
space = fil_space_acquire_silent(page_id.space());
if (UNIV_UNLIKELY(!space)) {
/* Do not try to read the bitmap page from the
non-existent tablespace, delete the ibuf records */
block = NULL;
- update_ibuf_bitmap = FALSE;
+ update_ibuf_bitmap = false;
} else {
page_t* bitmap_page = NULL;
ulint bitmap_bits = 0;
@@ -4460,12 +4410,12 @@ ibuf_merge_or_delete_for_page(
ibuf_mtr_start(&mtr);
bitmap_page = ibuf_bitmap_get_map_page(
- page_id, *page_size, &mtr);
+ page_id, zip_size, &mtr);
if (bitmap_page &&
fil_page_get_type(bitmap_page) != FIL_PAGE_TYPE_ALLOCATED) {
bitmap_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr);
}
@@ -4486,8 +4436,8 @@ ibuf_merge_or_delete_for_page(
}
}
} else if (block != NULL
- && (ibuf_fixed_addr_page(page_id, *page_size)
- || fsp_descr_page(page_id, *page_size))) {
+ && (ibuf_fixed_addr_page(page_id, physical_size)
+ || fsp_descr_page(page_id, physical_size))) {
return;
} else {
@@ -4720,23 +4670,23 @@ reset_bit:
if (update_ibuf_bitmap) {
page_t* bitmap_page;
- bitmap_page = ibuf_bitmap_get_map_page(page_id, *page_size,
+ bitmap_page = ibuf_bitmap_get_map_page(page_id, zip_size,
&mtr);
ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, physical_size,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
if (block != NULL) {
ulint old_bits = ibuf_bitmap_page_get_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, zip_size,
IBUF_BITMAP_FREE, &mtr);
ulint new_bits = ibuf_index_page_calc_free(block);
if (old_bits != new_bits) {
ibuf_bitmap_page_set_bits(
- bitmap_page, page_id, *page_size,
+ bitmap_page, page_id, physical_size,
IBUF_BITMAP_FREE, new_bits, &mtr);
}
}
@@ -4751,20 +4701,15 @@ reset_bit:
btr_pcur_close(&pcur);
mem_heap_free(heap);
- my_atomic_addlint(&ibuf->n_merges, 1);
+ ibuf->n_merges++;
ibuf_add_ops(ibuf->n_merged_ops, mops);
ibuf_add_ops(ibuf->n_discarded_ops, dops);
}
-/*********************************************************************//**
-Deletes all entries in the insert buffer for a given space id. This is used
-in DISCARD TABLESPACE, IMPORT TABLESPACE, and 5.7 TRUNCATE TABLE recovery.
-NOTE: this does not update the page free bitmaps in the space. The space will
-become CORRUPT when you call this function! */
-void
-ibuf_delete_for_discarded_space(
-/*============================*/
- ulint space) /*!< in: space id */
+/** Delete all change buffer entries for a tablespace,
+in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery.
+@param[in] space missing or to-be-discarded tablespace */
+void ibuf_delete_for_discarded_space(ulint space)
{
mem_heap_t* heap;
btr_pcur_t pcur;
@@ -4879,7 +4824,7 @@ ibuf_print(
ibuf->size,
ibuf->free_list_len,
ibuf->seg_size,
- ibuf->n_merges);
+ ulint{ibuf->n_merges});
fputs("merged operations:\n ", file);
ibuf_print_ops(ibuf->n_merged_ops, file);
@@ -4899,7 +4844,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
ulint page_no;
ut_ad(trx->mysql_thd);
ut_ad(space->purpose == FIL_TYPE_IMPORT);
- const page_size_t page_size(space->flags);
+
+ const ulint zip_size = space->zip_size();
+ const ulint physical_size = space->physical_size();
/* fil_space_t::size and fil_space_t::free_limit would still be 0
at this point. So, we will have to read page 0. */
ut_ad(!space->free_limit);
@@ -4908,7 +4855,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
mtr_t mtr;
ulint size;
mtr.start();
- if (buf_block_t* sp = buf_page_get(page_id_t(space->id, 0), page_size,
+ if (buf_block_t* sp = buf_page_get(page_id_t(space->id, 0),
+ zip_size,
RW_S_LATCH, &mtr)) {
size = std::min(
mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
@@ -4932,7 +4880,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
below page_no is measured in number of pages since the beginning of
the space, as usual. */
- for (page_no = 0; page_no < size; page_no += page_size.physical()) {
+ for (page_no = 0; page_no < size; page_no += physical_size) {
page_t* bitmap_page;
ulint i;
@@ -4948,23 +4896,24 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
ibuf_enter(&mtr);
bitmap_page = ibuf_bitmap_get_map_page(
- page_id_t(space->id, page_no), page_size, &mtr);
+ page_id_t(space->id, page_no), zip_size, &mtr);
if (buf_is_zeroes(span<const byte>(bitmap_page,
- page_size.physical()))) {
+ physical_size))) {
/* This means we got all-zero page instead of
ibuf bitmap page. The subsequent page should be
all-zero pages. */
#ifdef UNIV_DEBUG
for (ulint curr_page = page_no + 1;
- curr_page < page_size.physical(); curr_page++) {
+ curr_page < physical_size; curr_page++) {
buf_block_t* block = buf_page_get(
page_id_t(space->id, curr_page),
- page_size, RW_S_LATCH, &mtr);
+ zip_size, RW_S_LATCH, &mtr);
page_t* page = buf_block_get_frame(block);
ut_ad(buf_is_zeroes(span<const byte>(
- page, page_size.physical())));
+ page,
+ physical_size)));
}
#endif /* UNIV_DEBUG */
ibuf_exit(&mtr);
@@ -4977,17 +4926,13 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
return DB_CORRUPTION;
}
- for (i = FSP_IBUF_BITMAP_OFFSET + 1;
- i < page_size.physical();
- i++) {
-
+ for (i = FSP_IBUF_BITMAP_OFFSET + 1; i < physical_size; i++) {
const ulint offset = page_no + i;
-
const page_id_t cur_page_id(space->id, offset);
if (ibuf_bitmap_page_get_bits(
- bitmap_page, cur_page_id, page_size,
- IBUF_BITMAP_IBUF, &mtr)) {
+ bitmap_page, cur_page_id, zip_size,
+ IBUF_BITMAP_IBUF, &mtr)) {
mutex_exit(&ibuf_mutex);
ibuf_exit(&mtr);
@@ -5004,7 +4949,7 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
}
if (ibuf_bitmap_page_get_bits(
- bitmap_page, cur_page_id, page_size,
+ bitmap_page, cur_page_id, zip_size,
IBUF_BITMAP_BUFFERED, &mtr)) {
ib_errf(trx->mysql_thd,
@@ -5019,7 +4964,8 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
slightly corrupted tables can be
imported and dumped. Clear the bit. */
ibuf_bitmap_page_set_bits(
- bitmap_page, cur_page_id, page_size,
+ bitmap_page, cur_page_id,
+ physical_size,
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
}
}
@@ -5049,18 +4995,18 @@ ibuf_set_bitmap_for_bulk_load(
free_val = ibuf_index_page_calc_free(block);
mtr_start(&mtr);
- mtr.set_named_space_id(block->page.id.space());
+ fil_space_t* space = mtr.set_named_space_id(block->page.id.space());
bitmap_page = ibuf_bitmap_get_map_page(block->page.id,
- block->page.size, &mtr);
+ space->zip_size(), &mtr);
free_val = reset ? 0 : ibuf_index_page_calc_free(block);
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_FREE, free_val, &mtr);
ibuf_bitmap_page_set_bits(
- bitmap_page, block->page.id, block->page.size,
+ bitmap_page, block->page.id, block->physical_size(),
IBUF_BITMAP_BUFFERED, FALSE, &mtr);
mtr_commit(&mtr);
diff --git a/storage/innobase/include/btr0btr.h b/storage/innobase/include/btr0btr.h
index 698343bf371..e90db17b548 100644
--- a/storage/innobase/include/btr0btr.h
+++ b/storage/innobase/include/btr0btr.h
@@ -173,24 +173,19 @@ record is in spatial index */
| BTR_LATCH_FOR_DELETE \
| BTR_MODIFY_EXTERNAL)))
-/**************************************************************//**
-Report that an index page is corrupted. */
-void
-btr_corruption_report(
-/*==================*/
- const buf_block_t* block, /*!< in: corrupted block */
- const dict_index_t* index) /*!< in: index tree */
- ATTRIBUTE_COLD __attribute__((nonnull));
+/** Report that an index page is corrupted.
+@param[in] buffer block
+@param[in] index tree */
+ATTRIBUTE_COLD ATTRIBUTE_NORETURN __attribute__((nonnull))
+void btr_corruption_report(const buf_block_t* block,const dict_index_t* index);
/** Assert that a B-tree page is not corrupted.
@param block buffer block containing a B-tree page
@param index the B-tree index */
-#define btr_assert_not_corrupted(block, index) \
- if ((ibool) !!page_is_comp(buf_block_get_frame(block)) \
- != dict_table_is_comp((index)->table)) { \
- btr_corruption_report(block, index); \
- ut_error; \
- }
+#define btr_assert_not_corrupted(block, index) \
+ if (!!page_is_comp(buf_block_get_frame(block)) \
+ != index->table->not_redundant()) \
+ btr_corruption_report(block, index)
/**************************************************************//**
Gets the root node of a tree and sx-latches it for segment access.
@@ -225,6 +220,7 @@ btr_height_get(
/** Gets a buffer page and declares its latching order level.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] mode latch mode
@param[in] file file name
@param[in] line line where called
@@ -236,7 +232,7 @@ UNIV_INLINE
buf_block_t*
btr_block_get_func(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint mode,
const char* file,
unsigned line,
@@ -245,13 +241,13 @@ btr_block_get_func(
/** Gets a buffer page and declares its latching order level.
@param page_id tablespace/page identifier
-@param page_size page size
+@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param mode latch mode
@param index index tree, may be NULL if not the insert buffer tree
@param mtr mini-transaction handle
@return the block descriptor */
-# define btr_block_get(page_id, page_size, mode, index, mtr) \
- btr_block_get_func(page_id, page_size, mode, \
+# define btr_block_get(page_id, zip_size, mode, index, mtr) \
+ btr_block_get_func(page_id, zip_size, mode, \
__FILE__, __LINE__, (dict_index_t*)index, mtr)
/**************************************************************//**
Gets the index id field of a page.
@@ -327,40 +323,33 @@ btr_node_ptr_get_child_page_no(
@param[in] type type of the index
@param[in,out] space tablespace where created
@param[in] index_id index id
-@param[in] index index, or NULL when applying TRUNCATE
-log record during recovery
-@param[in] btr_redo_create_info used for applying TRUNCATE log
-@param[in] mtr mini-transaction handle
-record during recovery
-@return page number of the created root, FIL_NULL if did not succeed */
+@param[in] index index
+@param[in,out] mtr mini-transaction
+@return page number of the created root
+@retval FIL_NULL if did not succeed */
ulint
btr_create(
ulint type,
fil_space_t* space,
index_id_t index_id,
dict_index_t* index,
- const btr_create_t* btr_redo_create_info,
mtr_t* mtr);
/** Free a persistent index tree if it exists.
@param[in] page_id root page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] index_id PAGE_INDEX_ID contents
@param[in,out] mtr mini-transaction */
void
btr_free_if_exists(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
index_id_t index_id,
mtr_t* mtr);
-/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
-@param[in] page_id root page id
-@param[in] page_size page size */
-void
-btr_free(
- const page_id_t page_id,
- const page_size_t& page_size);
+/** Free an index tree in a temporary tablespace.
+@param[in] page_id root page id */
+void btr_free(const page_id_t page_id);
/** Read the last used AUTO_INCREMENT value from PAGE_ROOT_AUTO_INC.
@param[in,out] index clustered index
@@ -390,6 +379,12 @@ void
btr_write_autoinc(dict_index_t* index, ib_uint64_t autoinc, bool reset = false)
MY_ATTRIBUTE((nonnull));
+/** Write instant ALTER TABLE metadata to a root page.
+@param[in,out] root clustered index root page
+@param[in] index clustered index with instant ALTER TABLE
+@param[in,out] mtr mini-transaction */
+void btr_set_instant(buf_block_t* root, const dict_index_t& index, mtr_t* mtr);
+
/*************************************************************//**
Makes tree one level higher by splitting the root, and inserts
the tuple. It is assumed that mtr contains an x-latch on the tree.
@@ -750,21 +745,23 @@ dberr_t
btr_validate_index(
/*===============*/
dict_index_t* index, /*!< in: index */
- const trx_t* trx, /*!< in: transaction or 0 */
- bool lockout)/*!< in: true if X-latch index is intended */
+ const trx_t* trx) /*!< in: transaction or 0 */
MY_ATTRIBUTE((warn_unused_result));
-/*************************************************************//**
-Removes a page from the level list of pages. */
-UNIV_INTERN
+/** Remove a page from the level list of pages.
+@param[in] space space where removed
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] page page to remove
+@param[in] index index tree
+@param[in,out] mtr mini-transaction */
void
btr_level_list_remove_func(
-/*=======================*/
- ulint space, /*!< in: space where removed */
- const page_size_t& page_size,/*!< in: page size */
- page_t* page, /*!< in/out: page to remove */
- dict_index_t* index, /*!< in: index tree */
- mtr_t* mtr); /*!< in/out: mini-transaction */
+ ulint space,
+ ulint zip_size,
+ page_t* page,
+ dict_index_t* index,
+ mtr_t* mtr);
+
/*************************************************************//**
Removes a page from the level list of pages.
@param space in: space where removed
@@ -799,5 +796,6 @@ btr_lift_page_up(
/****************************************************************
Global variable controlling if scrubbing should be performed */
extern my_bool srv_immediate_scrub_data_uncompressed;
+extern Atomic_counter<uint32_t> btr_validate_index_running;
#endif
diff --git a/storage/innobase/include/btr0btr.ic b/storage/innobase/include/btr0btr.ic
index 5bb7318fefb..42bad4861b4 100644
--- a/storage/innobase/include/btr0btr.ic
+++ b/storage/innobase/include/btr0btr.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2017, MariaDB Corporation.
+Copyright (c) 2015, 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 6/2/1994 Heikki Tuuri
/** Gets a buffer page and declares its latching order level.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] mode latch mode
@param[in] file file name
@param[in] line line where called
@@ -42,7 +43,7 @@ UNIV_INLINE
buf_block_t*
btr_block_get_func(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint mode,
const char* file,
unsigned line,
@@ -53,7 +54,7 @@ btr_block_get_func(
dberr_t err=DB_SUCCESS;
block = buf_page_get_gen(
- page_id, page_size, mode, NULL, BUF_GET, file, line, mtr, &err);
+ page_id, zip_size, mode, NULL, BUF_GET, file, line, mtr, &err);
if (err == DB_DECRYPTION_FAILED) {
if (index && index->table) {
diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h
index 9384cb578ed..3c127986bfe 100644
--- a/storage/innobase/include/btr0bulk.h
+++ b/storage/innobase/include/btr0bulk.h
@@ -289,8 +289,7 @@ public:
ut_ad(!dict_index_is_spatial(index));
#ifdef UNIV_DEBUG
if (m_flush_observer)
- my_atomic_addlint(&m_index->table->space->redo_skipped_count,
- 1);
+ m_index->table->space->redo_skipped_count++;
#endif /* UNIV_DEBUG */
}
@@ -299,8 +298,7 @@ public:
{
#ifdef UNIV_DEBUG
if (m_flush_observer)
- my_atomic_addlint(&m_index->table->space->redo_skipped_count,
- ulint(-1));
+ m_index->table->space->redo_skipped_count--;
#endif /* UNIV_DEBUG */
}
diff --git a/storage/innobase/include/btr0cur.h b/storage/innobase/include/btr0cur.h
index 13a420fd912..5d10d26e025 100644
--- a/storage/innobase/include/btr0cur.h
+++ b/storage/innobase/include/btr0cur.h
@@ -729,11 +729,12 @@ btr_free_externally_stored_field(
ignored if rec == NULL */
bool rollback, /*!< in: performing rollback? */
mtr_t* local_mtr); /*!< in: mtr containing the latch */
+
/** Copies the prefix of an externally stored field of a record.
The clustered index record must be protected by a lock or a page latch.
@param[out] buf the field, or a prefix of it
@param[in] len length of buf, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
@@ -744,7 +745,7 @@ ulint
btr_copy_externally_stored_field_prefix(
byte* buf,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte* data,
ulint local_len);
@@ -754,7 +755,7 @@ The clustered index record must be protected by a lock or a page latch.
@param[in] data 'internally' stored part of the field
containing also the reference to the external part; must be protected by
a lock or a page latch
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] local_len length of data
@param[in,out] heap mem heap
@return the whole field copied to heap */
@@ -762,7 +763,7 @@ byte*
btr_copy_externally_stored_field(
ulint* len,
const byte* data,
- const page_size_t& page_size,
+ ulint zip_size,
ulint local_len,
mem_heap_t* heap);
@@ -770,7 +771,7 @@ btr_copy_externally_stored_field(
@param[in] rec record in a clustered index; must be
protected by a lock or a page latch
@param[in] offset array returned by rec_get_offsets()
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] no field number
@param[out] len length of the field
@param[in,out] heap mem heap
@@ -779,7 +780,7 @@ byte*
btr_rec_copy_externally_stored_field(
const rec_t* rec,
const offset_t* offsets,
- const page_size_t& page_size,
+ ulint zip_size,
ulint no,
ulint* len,
mem_heap_t* heap);
@@ -810,6 +811,7 @@ btr_rec_set_deleted_flag(
/** Latches the leaf page or pages requested.
@param[in] block leaf page where the search converged
@param[in] page_id page id of the leaf
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] latch_mode BTR_SEARCH_LEAF, ...
@param[in] cursor cursor
@param[in] mtr mini-transaction
@@ -818,7 +820,7 @@ btr_latch_leaves_t
btr_cur_latch_leaves(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint latch_mode,
btr_cur_t* cursor,
mtr_t* mtr);
@@ -1021,7 +1023,7 @@ inherited external field. */
#define BTR_EXTERN_INHERITED_FLAG 64U
/** Number of searches down the B-tree in btr_cur_search_to_nth_level(). */
-extern ulint btr_cur_n_non_sea;
+extern Atomic_counter<ulint> btr_cur_n_non_sea;
/** Old value of btr_cur_n_non_sea. Copied by
srv_refresh_innodb_monitor_stats(). Referenced by
srv_printf_innodb_monitor(). */
diff --git a/storage/innobase/include/btr0defragment.h b/storage/innobase/include/btr0defragment.h
index 57f8c2f3811..22f29eae3a6 100644
--- a/storage/innobase/include/btr0defragment.h
+++ b/storage/innobase/include/btr0defragment.h
@@ -26,9 +26,9 @@ this program; if not, write to the Free Software Foundation, Inc.,
#define BTR_DEFRAGMENT_MAX_N_PAGES 32
/** stats in btr_defragment */
-extern ulint btr_defragment_compression_failures;
-extern ulint btr_defragment_failures;
-extern ulint btr_defragment_count;
+extern Atomic_counter<ulint> btr_defragment_compression_failures;
+extern Atomic_counter<ulint> btr_defragment_failures;
+extern Atomic_counter<ulint> btr_defragment_count;
/** Item in the work queue for btr_degrament_thread. */
struct btr_defragment_item_t
diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
index 527782d548e..8bbfe18c5d9 100644
--- a/storage/innobase/include/btr0sea.h
+++ b/storage/innobase/include/btr0sea.h
@@ -43,7 +43,7 @@ void btr_search_sys_resize(ulint hash_size);
void btr_search_sys_free();
/** Disable the adaptive hash search system and empty the index.
-@param need_mutex need to acquire dict_sys->mutex */
+@param need_mutex need to acquire dict_sys.mutex */
void btr_search_disable(bool need_mutex);
/** Enable the adaptive hash search system. */
void btr_search_enable();
diff --git a/storage/innobase/include/btr0types.h b/storage/innobase/include/btr0types.h
index 22e1ef11a68..83c374e2561 100644
--- a/storage/innobase/include/btr0types.h
+++ b/storage/innobase/include/btr0types.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2018, 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
@@ -27,7 +28,6 @@ Created 2/17/1996 Heikki Tuuri
#define btr0types_h
#include "page0types.h"
-#include "page0size.h"
#include "rem0types.h"
/** Persistent cursor */
@@ -49,41 +49,11 @@ extern ulong btr_ahi_parts;
/** The size of a reference to data stored on a different page.
The reference is stored at the end of the prefix of the field
in the index record. */
+#define FIELD_REF_SIZE 20U
#define BTR_EXTERN_FIELD_REF_SIZE FIELD_REF_SIZE
/** If the data don't exceed the size, the data are stored locally. */
#define BTR_EXTERN_LOCAL_STORED_MAX_SIZE \
(BTR_EXTERN_FIELD_REF_SIZE * 2)
-/** The information is used for creating a new index tree when
-applying TRUNCATE log record during recovery */
-struct btr_create_t {
-
- explicit btr_create_t(const byte* const ptr)
- :
- format_flags(),
- n_fields(),
- field_len(),
- fields(ptr),
- trx_id_pos(ULINT_UNDEFINED)
- {
- /* Do nothing */
- }
-
- /** Page format */
- ulint format_flags;
-
- /** Numbr of index fields */
- ulint n_fields;
-
- /** The length of the encoded meta-data */
- ulint field_len;
-
- /** Field meta-data, encoded. */
- const byte* const fields;
-
- /** Position of trx-id column. */
- ulint trx_id_pos;
-};
-
#endif
diff --git a/storage/innobase/include/buf0buddy.h b/storage/innobase/include/buf0buddy.h
index 5b1aefb4d69..5119a1c58c4 100644
--- a/storage/innobase/include/buf0buddy.h
+++ b/storage/innobase/include/buf0buddy.h
@@ -26,11 +26,6 @@ Created December 2006 by Marko Makela
#ifndef buf0buddy_h
#define buf0buddy_h
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE
-#endif
-
#include "buf0types.h"
/**********************************************************************//**
diff --git a/storage/innobase/include/buf0buddy.ic b/storage/innobase/include/buf0buddy.ic
index dad9cb668dd..39ab46d80dd 100644
--- a/storage/innobase/include/buf0buddy.ic
+++ b/storage/innobase/include/buf0buddy.ic
@@ -23,11 +23,6 @@ Binary buddy allocator for compressed pages
Created December 2006 by Marko Makela
*******************************************************/
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE
-#endif
-
#include "buf0buf.h"
#include "buf0buddy.h"
@@ -132,8 +127,3 @@ buf_buddy_free(
buf_buddy_free_low(buf_pool, buf, buf_buddy_get_slot(size));
}
-
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE UNIV_INLINE_ORIGINAL
-#endif
diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h
index 6bf2dc2f1c4..93cf3742c88 100644
--- a/storage/innobase/include/buf0buf.h
+++ b/storage/innobase/include/buf0buf.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2020 MariaDB Corporation.
+Copyright (c) 2013, 2020, 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
@@ -42,7 +42,6 @@ Created 11/5/1995 Heikki Tuuri
#include "os0proc.h"
#include "log0log.h"
#include "srv0srv.h"
-#include "my_atomic.h"
#include <ostream>
// Forward declaration
@@ -428,16 +427,14 @@ be implemented at a higher level. In other words, all possible
accesses to a given page through this function must be protected by
the same set of mutexes or latches.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size
@return pointer to the block */
-buf_page_t*
-buf_page_get_zip(
- const page_id_t page_id,
- const page_size_t& page_size);
+buf_page_t* buf_page_get_zip(const page_id_t page_id, ulint zip_size);
/** This is the general function used to get access to a database page.
It does page initialization and applies the buffered redo logs.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
@@ -450,7 +447,7 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
buf_block_t*
buf_page_get_gen(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint rw_latch,
buf_block_t* guess,
ulint mode,
@@ -459,8 +456,9 @@ buf_page_get_gen(
mtr_t* mtr,
dberr_t* err);
-/** This is the low level function used to get access to a database page.
+/** Low level function used to get access to a database page.
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_NO_LATCH
@param[in] guess guessed block or NULL
@param[in] mode BUF_GET, BUF_GET_IF_IN_POOL,
@@ -473,7 +471,7 @@ BUF_PEEK_IF_IN_POOL, BUF_GET_NO_LATCH, or BUF_GET_IF_IN_POOL_OR_WATCH
buf_block_t*
buf_page_get_low(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint rw_latch,
buf_block_t* guess,
ulint mode,
@@ -482,18 +480,18 @@ buf_page_get_low(
mtr_t* mtr,
dberr_t* err);
-/** Initializes a page to the buffer buf_pool. The page is usually not read
+/** Initialize a page in the buffer pool. The page is usually not read
from a file even if it cannot be found in the buffer buf_pool. This is one
of the functions which perform to a block a state transition NOT_USED =>
FILE_PAGE (the other is buf_page_get_gen).
@param[in] page_id page id
-@param[in] page_size page size
-@param[in] mtr mini-transaction
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] mtr mini-transaction
@return pointer to the block, page bufferfixed */
buf_block_t*
buf_page_create(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
mtr_t* mtr);
/********************************************************************//**
@@ -629,33 +627,6 @@ buf_block_buf_fix_inc_func(
buf_block_t* block) /*!< in/out: block to bufferfix */
MY_ATTRIBUTE((nonnull));
-/** Increments the bufferfix count.
-@param[in,out] bpage block to bufferfix
-@return the count */
-UNIV_INLINE
-ulint
-buf_block_fix(buf_page_t* bpage);
-
-/** Increments the bufferfix count.
-@param[in,out] block block to bufferfix
-@return the count */
-UNIV_INLINE
-ulint
-buf_block_fix(buf_block_t* block);
-
-/** Decrements the bufferfix count.
-@param[in,out] bpage block to bufferunfix
-@return the remaining buffer-fix count */
-UNIV_INLINE
-ulint
-buf_block_unfix(buf_page_t* bpage);
-/** Decrements the bufferfix count.
-@param[in,out] block block to bufferunfix
-@return the remaining buffer-fix count */
-UNIV_INLINE
-ulint
-buf_block_unfix(buf_block_t* block);
-
# ifdef UNIV_DEBUG
/** Increments the bufferfix count.
@param[in,out] b block to bufferfix
@@ -715,19 +686,13 @@ buf_page_is_checksum_valid_none(
/** Check if a page is corrupt.
@param[in] check_lsn whether the LSN should be checked
@param[in] read_buf database page
-@param[in] page_size page size
-@param[in] space tablespace
+@param[in] fsp_flags tablespace flags
@return whether the page is corrupted */
bool
buf_page_is_corrupted(
bool check_lsn,
const byte* read_buf,
- const page_size_t& page_size,
-#ifndef UNIV_INNOCHECKSUM
- const fil_space_t* space = NULL)
-#else
- const void* space = NULL)
-#endif
+ ulint fsp_flags)
MY_ATTRIBUTE((warn_unused_result));
inline void *aligned_malloc(size_t size, size_t align)
@@ -751,6 +716,63 @@ inline void aligned_free(void *ptr)
#endif
}
+/** Read the key version from the page. In full crc32 format,
+key version is stored at {0-3th} bytes. In other format, it is
+stored in 26th position.
+@param[in] read_buf database page
+@param[in] fsp_flags tablespace flags
+@return key version of the page. */
+inline uint32_t buf_page_get_key_version(const byte* read_buf, ulint fsp_flags)
+{
+ return fil_space_t::full_crc32(fsp_flags)
+ ? mach_read_from_4(read_buf + FIL_PAGE_FCRC32_KEY_VERSION)
+ : mach_read_from_4(read_buf
+ + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+}
+
+/** Read the compression info from the page. In full crc32 format,
+compression info is at MSB of page type. In other format, it is
+stored in page type.
+@param[in] read_buf database page
+@param[in] fsp_flags tablespace flags
+@return true if page is compressed. */
+inline bool buf_page_is_compressed(const byte* read_buf, ulint fsp_flags)
+{
+ ulint page_type = mach_read_from_2(read_buf + FIL_PAGE_TYPE);
+ return fil_space_t::full_crc32(fsp_flags)
+ ? !!(page_type & 1U << FIL_PAGE_COMPRESS_FCRC32_MARKER)
+ : page_type == FIL_PAGE_PAGE_COMPRESSED;
+}
+
+/** Get the compressed or uncompressed size of a full_crc32 page.
+@param[in] buf page_compressed or uncompressed page
+@param[out] comp whether the page could be compressed
+@param[out] cr whether the page could be corrupted
+@return the payload size in the file page */
+inline uint buf_page_full_crc32_size(const byte* buf, bool* comp, bool* cr)
+{
+ uint t = mach_read_from_2(buf + FIL_PAGE_TYPE);
+ uint page_size = uint(srv_page_size);
+
+ if (!(t & 1U << FIL_PAGE_COMPRESS_FCRC32_MARKER)) {
+ return page_size;
+ }
+
+ t &= ~(1U << FIL_PAGE_COMPRESS_FCRC32_MARKER);
+ t <<= 8;
+
+ if (t < page_size) {
+ page_size = t;
+ if (comp) {
+ *comp = true;
+ }
+ } else if (cr) {
+ *cr = true;
+ }
+
+ return page_size;
+}
+
#ifndef UNIV_INNOCHECKSUM
/**********************************************************************//**
Gets the space id, page offset, and byte offset within page of a
@@ -812,10 +834,8 @@ buf_print(void);
/** Dump a page to stderr.
@param[in] read_buf database page
-@param[in] page_size page size */
-UNIV_INTERN
-void
-buf_page_print(const byte* read_buf, const page_size_t& page_size)
+@param[in] zip_size compressed page size, or 0 */
+void buf_page_print(const byte* read_buf, ulint zip_size = 0)
ATTRIBUTE_COLD __attribute__((nonnull));
/********************************************************************//**
Decompress a block.
@@ -1174,6 +1194,7 @@ and the lock released later.
@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...
@param[in] page_id page id
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] unzip whether the uncompressed page is
requested (for ROW_FORMAT=COMPRESSED)
@return pointer to the block
@@ -1183,7 +1204,7 @@ buf_page_init_for_read(
dberr_t* err,
ulint mode,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
bool unzip);
/** Complete a read or write request of a file page to or from the buffer pool.
@@ -1394,6 +1415,15 @@ ulint
buf_pool_size_align(
ulint size);
+/** Verify that post encryption checksum match with the calculated checksum.
+This function should be called only if tablespace contains crypt data metadata.
+@param[in] page page frame
+@param[in] fsp_flags tablespace flags
+@return true if page is encrypted and OK, false otherwise */
+bool buf_page_verify_crypt_checksum(
+ const byte* page,
+ ulint fsp_flags);
+
/** Calculate the checksum of a page from compressed table and update the
page.
@param[in,out] page page to update
@@ -1414,7 +1444,7 @@ a page is written to disk.
(may be src_frame or an encrypted/compressed copy of it) */
UNIV_INTERN
byte*
-buf_page_encrypt_before_write(
+buf_page_encrypt(
fil_space_t* space,
buf_page_t* bpage,
byte* src_frame);
@@ -1424,10 +1454,9 @@ buf_page_encrypt_before_write(
NOTE! The definition appears here only for other modules of this
directory (buf) to see it. Do not use from outside! */
-struct buf_tmp_buffer_t {
-private:
- int32 reserved; /*!< true if this slot is reserved
- */
+class buf_tmp_buffer_t {
+ /** whether this slot is reserved */
+ std::atomic<bool> reserved;
public:
byte* crypt_buf; /*!< for encryption the data needs to be
copied to a separate buffer before it's
@@ -1443,16 +1472,14 @@ public:
/** Release the slot */
void release()
{
- my_atomic_store32_explicit(&reserved, false,
- MY_MEMORY_ORDER_RELAXED);
+ reserved.store(false, std::memory_order_relaxed);
}
/** Acquire the slot
@return whether the slot was acquired */
bool acquire()
{
- return !my_atomic_fas32_explicit(&reserved, true,
- MY_MEMORY_ORDER_RELAXED);
+ return !reserved.exchange(true, std::memory_order_relaxed);
}
};
@@ -1478,11 +1505,8 @@ public:
buf_pool->page_hash or
buf_pool->zip_hash */
- /** Page size. Protected by buf_pool mutex. */
- page_size_t size;
-
/** Count of how manyfold this block is currently bufferfixed. */
- int32 buf_fix_count;
+ Atomic_counter<uint32_t> buf_fix_count;
/** type of pending I/O operation; also protected by
buf_pool->mutex for writes only */
@@ -1632,6 +1656,27 @@ public:
protected by buf_pool->zip_mutex
or buf_block_t::mutex. */
# endif /* UNIV_DEBUG */
+
+ void fix() { buf_fix_count++; }
+ uint32_t unfix()
+ {
+ uint32_t count= buf_fix_count--;
+ ut_ad(count != 0);
+ return count - 1;
+ }
+
+ /** @return the physical size, in bytes */
+ ulint physical_size() const
+ {
+ return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : srv_page_size;
+ }
+
+ /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes
+ @retval 0 if not compressed */
+ ulint zip_size() const
+ {
+ return zip.ssize ? (UNIV_ZIP_SIZE_MIN >> 1) << zip.ssize : 0;
+ }
};
/** The buffer control block structure */
@@ -1738,20 +1783,20 @@ struct buf_block_t{
/* @{ */
# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
- ulint n_pointers; /*!< used in debugging: the number of
+ Atomic_counter<ulint>
+ n_pointers; /*!< used in debugging: the number of
pointers in the adaptive hash index
pointing to this frame;
protected by atomic memory access
or btr_search_own_all(). */
# define assert_block_ahi_empty(block) \
- ut_a(my_atomic_addlint(&(block)->n_pointers, 0) == 0)
+ ut_a((block)->n_pointers == 0)
# define assert_block_ahi_empty_on_init(block) do { \
UNIV_MEM_VALID(&(block)->n_pointers, sizeof (block)->n_pointers); \
assert_block_ahi_empty(block); \
} while (0)
# define assert_block_ahi_valid(block) \
- ut_a((block)->index \
- || my_atomic_loadlint(&(block)->n_pointers) == 0)
+ ut_a((block)->index || (block)->n_pointers == 0)
# else /* UNIV_AHI_DEBUG || UNIV_DEBUG */
# define assert_block_ahi_empty(block) /* nothing */
# define assert_block_ahi_empty_on_init(block) /* nothing */
@@ -1783,7 +1828,7 @@ struct buf_block_t{
# ifdef UNIV_DEBUG
/** @name Debug fields */
/* @{ */
- rw_lock_t debug_latch; /*!< in the debug version, each thread
+ rw_lock_t* debug_latch; /*!< in the debug version, each thread
which bufferfixes the block acquires
an s-latch here; so we can use the
debug utilities in sync0rw */
@@ -1795,6 +1840,16 @@ struct buf_block_t{
and accessed; we introduce this new
mutex in InnoDB-5.1 to relieve
contention on the buffer pool mutex */
+
+ void fix() { page.fix(); }
+ uint32_t unfix() { return page.unfix(); }
+
+ /** @return the physical size, in bytes */
+ ulint physical_size() const { return page.physical_size(); }
+
+ /** @return the ROW_FORMAT=COMPRESSED physical size, in bytes
+ @retval 0 if not compressed */
+ ulint zip_size() const { return page.zip_size(); }
};
/** Check if a buf_block_t object is in a valid state
@@ -1886,13 +1941,13 @@ public:
HazardPointer(buf_pool, mutex) {}
/** Destructor */
- virtual ~FlushHp() {}
+ ~FlushHp() override {}
/** Adjust the value of hp. This happens when some
other thread working on the same list attempts to
remove the hp from the list.
@param bpage buffer block to be compared */
- void adjust(const buf_page_t* bpage);
+ void adjust(const buf_page_t* bpage) override;
};
/** Class implementing buf_pool->LRU hazard pointer */
@@ -1907,13 +1962,13 @@ public:
HazardPointer(buf_pool, mutex) {}
/** Destructor */
- virtual ~LRUHp() {}
+ ~LRUHp() override {}
/** Adjust the value of hp. This happens when some
other thread working on the same list attempts to
remove the hp from the list.
@param bpage buffer block to be compared */
- void adjust(const buf_page_t* bpage);
+ void adjust(const buf_page_t* bpage) override;
};
/** Special purpose iterators to be used when scanning the LRU list.
@@ -1931,7 +1986,7 @@ public:
LRUHp(buf_pool, mutex) {}
/** Destructor */
- virtual ~LRUItr() {}
+ ~LRUItr() override {}
/** Selects from where to start a scan. If we have scanned
too deep into the LRU list it resets the value to the tail
@@ -1999,17 +2054,6 @@ struct buf_buddy_stat_t {
ib_uint64_t relocated_usec;
};
-/** @brief The temporary memory array structure.
-
-NOTE! The definition appears here only for other modules of this
-directory (buf) to see it. Do not use from outside! */
-
-typedef struct {
- ulint n_slots; /*!< Total number of slots */
- buf_tmp_buffer_t *slots; /*!< Pointer to the slots in the
- array */
-} buf_tmp_array_t;
-
/** @brief The buffer pool structure.
NOTE! The definition appears here only for other modules of this
@@ -2069,7 +2113,8 @@ struct buf_pool_t{
indexed by block->frame */
ulint n_pend_reads; /*!< number of pending read
operations */
- ulint n_pend_unzip; /*!< number of pending decompressions */
+ Atomic_counter<ulint>
+ n_pend_unzip; /*!< number of pending decompressions */
time_t last_printout_time;
/*!< when buf_print_io was last time
@@ -2210,20 +2255,47 @@ struct buf_pool_t{
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
UT_LIST_BASE_NODE_T(buf_buddy_free_t) zip_free[BUF_BUDDY_SIZES_MAX];
/*!< buddy free lists */
+#if BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN
+# error "BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN"
+#endif
+ /* @} */
buf_page_t* watch;
/*!< Sentinel records for buffer
pool watches. Protected by
buf_pool->mutex. */
- buf_tmp_array_t* tmp_arr;
- /*!< Array for temporal memory
- used in compression and encryption */
-
-#if BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN
-# error "BUF_BUDDY_LOW > UNIV_ZIP_SIZE_MIN"
-#endif
- /* @} */
+ /** Temporary memory for page_compressed and encrypted I/O */
+ struct io_buf_t {
+ /** number of elements in slots[] */
+ const ulint n_slots;
+ /** array of slots */
+ buf_tmp_buffer_t* const slots;
+
+ io_buf_t() = delete;
+
+ /** Constructor */
+ explicit io_buf_t(ulint n_slots) :
+ n_slots(n_slots),
+ slots(static_cast<buf_tmp_buffer_t*>(
+ ut_malloc_nokey(n_slots
+ * sizeof *slots)))
+ {
+ memset((void*) slots, 0, n_slots * sizeof *slots);
+ }
+
+ ~io_buf_t();
+
+ /** Reserve a buffer */
+ buf_tmp_buffer_t* reserve()
+ {
+ for (buf_tmp_buffer_t* s = slots, *e = slots + n_slots;
+ s != e; s++) {
+ if (s->acquire()) return s;
+ }
+ return NULL;
+ }
+ } io_buf;
};
/** Print the given buf_pool_t object.
diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic
index 79ec1e5d80b..31137ebf124 100644
--- a/storage/innobase/include/buf0buf.ic
+++ b/storage/innobase/include/buf0buf.ic
@@ -955,49 +955,6 @@ buf_block_get_modify_clock(
return(block->modify_clock);
}
-/** Increments the bufferfix count.
-@param[in,out] bpage block to bufferfix
-@return the count */
-UNIV_INLINE
-ulint
-buf_block_fix(buf_page_t* bpage)
-{
- return uint32(my_atomic_add32_explicit(
- &bpage->buf_fix_count, 1,
- MY_MEMORY_ORDER_RELAXED)) + 1;
-}
-
-/** Increments the bufferfix count.
-@param[in,out] block block to bufferfix
-@return the count */
-UNIV_INLINE
-ulint
-buf_block_fix(buf_block_t* block)
-{
- return buf_block_fix(&block->page);
-}
-
-/** Get the bufferfix count.
-@param[in] bpage block to bufferfix
-@return the count */
-UNIV_INLINE
-ulint
-buf_block_get_fix(buf_page_t* bpage)
-{
- return my_atomic_load32_explicit(&bpage->buf_fix_count,
- MY_MEMORY_ORDER_RELAXED);
-}
-
-/** Get the bufferfix count.
-@param[in] bpage block to bufferfix
-@return the count */
-UNIV_INLINE
-ulint
-buf_block_get_fix(buf_block_t* block)
-{
- return buf_block_get_fix(&block->page);
-}
-
/*******************************************************************//**
Increments the bufferfix count. */
UNIV_INLINE
@@ -1016,36 +973,12 @@ buf_block_buf_fix_inc_func(
threaded. */
if (!fsp_is_system_temporary(block->page.id.space())) {
ibool ret;
- ret = rw_lock_s_lock_nowait(&block->debug_latch, file, line);
+ ret = rw_lock_s_lock_nowait(block->debug_latch, file, line);
ut_a(ret);
}
#endif /* UNIV_DEBUG */
- buf_block_fix(block);
-}
-
-/** Decrements the bufferfix count.
-@param[in,out] bpage block to bufferunfix
-@return the remaining buffer-fix count */
-UNIV_INLINE
-ulint
-buf_block_unfix(buf_page_t* bpage)
-{
- uint32 count = uint32(my_atomic_add32_explicit(
- &bpage->buf_fix_count,
- -1, MY_MEMORY_ORDER_RELAXED));
- ut_ad(count != 0);
- return count - 1;
-}
-
-/** Decrements the bufferfix count.
-@param[in,out] block block to bufferunfix
-@return the remaining buffer-fix count */
-UNIV_INLINE
-ulint
-buf_block_unfix(buf_block_t* block)
-{
- return buf_block_unfix(&block->page);
+ block->fix();
}
/*******************************************************************//**
@@ -1056,14 +989,14 @@ buf_block_buf_fix_dec(
/*==================*/
buf_block_t* block) /*!< in/out: block to bufferunfix */
{
- buf_block_unfix(block);
+ block->unfix();
#ifdef UNIV_DEBUG
/* No debug latch is acquired if block belongs to system temporary.
Debug latch is not of much help if access to block is single
threaded. */
if (!fsp_is_system_temporary(block->page.id.space())) {
- rw_lock_s_unlock(&block->debug_latch);
+ rw_lock_s_unlock(block->debug_latch);
}
#endif /* UNIV_DEBUG */
}
@@ -1306,14 +1239,14 @@ buf_page_release_zip(
is single threaded. */
buf_block_t* block = reinterpret_cast<buf_block_t*>(bpage);
if (!fsp_is_system_temporary(block->page.id.space())) {
- rw_lock_s_unlock(&block->debug_latch);
+ rw_lock_s_unlock(block->debug_latch);
}
}
#endif /* UNIV_DEBUG */
/* Fall through */
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
- buf_block_unfix(reinterpret_cast<buf_block_t*>(bpage));
+ reinterpret_cast<buf_block_t*>(bpage)->unfix();
return;
case BUF_BLOCK_POOL_WATCH:
@@ -1342,7 +1275,7 @@ buf_page_release_latch(
temporary. Debug latch is not of much help if access to block
is single threaded. */
if (!fsp_is_system_temporary(block->page.id.space())) {
- rw_lock_s_unlock(&block->debug_latch);
+ rw_lock_s_unlock(block->debug_latch);
}
#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/include/buf0checksum.h b/storage/innobase/include/buf0checksum.h
index ce39e290ac7..8dc25f91d59 100644
--- a/storage/innobase/include/buf0checksum.h
+++ b/storage/innobase/include/buf0checksum.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 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
@@ -29,18 +29,6 @@ Created Aug 11, 2011 Vasil Dimov
#include "buf0types.h"
-#ifdef INNODB_BUG_ENDIAN_CRC32
-/** Calculate the CRC32 checksum of a page. The value is stored to the page
-when it is written to a file and also checked for a match when reading from
-the file. Note that we must be careful to calculate the same value on all
-architectures.
-@param[in] page buffer page (srv_page_size bytes)
-@param[in] bug_endian whether to use big endian byteorder
-when converting byte strings to integers, for bug-compatibility with
-big-endian architecture running MySQL 5.6, MariaDB 10.0 or MariaDB 10.1
-@return CRC-32C */
-uint32_t buf_calc_page_crc32(const byte* page, bool bug_endian = false);
-#else
/** Calculate the CRC32 checksum of a page. The value is stored to the page
when it is written to a file and also checked for a match when reading from
the file. Note that we must be careful to calculate the same value on all
@@ -48,7 +36,6 @@ architectures.
@param[in] page buffer page (srv_page_size bytes)
@return CRC-32C */
uint32_t buf_calc_page_crc32(const byte* page);
-#endif
/** Calculate a checksum which is stored to the page when it is written
to a file. Note that we must be careful to calculate the same value on
diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h
index a0122d1c3f8..e022dd55215 100644
--- a/storage/innobase/include/buf0flu.h
+++ b/storage/innobase/include/buf0flu.h
@@ -73,17 +73,24 @@ buf_flush_relocate_on_flush_list(
@param[in,out] bpage flushed page
@param[in] dblwr whether the doublewrite buffer was used */
void buf_flush_write_complete(buf_page_t* bpage, bool dblwr);
+
+/** Assign the full crc32 checksum for non-compressed page.
+@param[in,out] page page to be updated */
+void buf_flush_assign_full_crc32_checksum(byte* page);
+
/** Initialize a page for writing to the tablespace.
-@param[in] block buffer block; NULL if bypassing the buffer pool
-@param[in,out] page page frame
-@param[in,out] page_zip_ compressed page, or NULL if uncompressed
-@param[in] newest_lsn newest modification LSN to the page */
+@param[in] block buffer block; NULL if bypassing the buffer pool
+@param[in,out] page page frame
+@param[in,out] page_zip_ compressed page, or NULL if uncompressed
+@param[in] newest_lsn newest modification LSN to the page
+@param[in] use_full_checksum whether tablespace uses full checksum */
void
buf_flush_init_for_writing(
const buf_block_t* block,
byte* page,
void* page_zip_,
- lsn_t newest_lsn);
+ lsn_t newest_lsn,
+ bool use_full_checksum);
# if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/********************************************************************//**
@@ -181,18 +188,6 @@ buf_flush_note_modification(
lsn_t end_lsn, /*!< in: end lsn of the last mtr in the
set of mtr's */
FlushObserver* observer); /*!< in: flush observer */
-
-/********************************************************************//**
-This function should be called when recovery has modified a buffer page. */
-UNIV_INLINE
-void
-buf_flush_recv_note_modification(
-/*=============================*/
- buf_block_t* block, /*!< in: block which is modified */
- lsn_t start_lsn, /*!< in: start lsn of the first mtr in a
- set of mtr's */
- lsn_t end_lsn); /*!< in: end lsn of the last mtr in the
- set of mtr's */
/********************************************************************//**
Returns TRUE if the file page block is immediately suitable for replacement,
i.e., transition FILE_PAGE => NOT_USED allowed.
diff --git a/storage/innobase/include/buf0flu.ic b/storage/innobase/include/buf0flu.ic
index 8d06a53c547..02f3d8ced57 100644
--- a/storage/innobase/include/buf0flu.ic
+++ b/storage/innobase/include/buf0flu.ic
@@ -38,17 +38,6 @@ buf_flush_insert_into_flush_list(
lsn_t lsn); /*!< in: oldest modification */
/********************************************************************//**
-Inserts a modified block into the flush list in the right sorted position.
-This function is used by recovery, because there the modifications do not
-necessarily come in the order of lsn's. */
-void
-buf_flush_insert_sorted_into_flush_list(
-/*====================================*/
- buf_pool_t* buf_pool, /*!< buffer pool instance */
- buf_block_t* block, /*!< in/out: block which is modified */
- lsn_t lsn); /*!< in: oldest modification */
-
-/********************************************************************//**
This function should be called at a mini-transaction commit, if a page was
modified in it. Puts the block to the list of modified blocks, if it is not
already in it. */
@@ -63,24 +52,11 @@ buf_flush_note_modification(
modified this block */
FlushObserver* observer) /*!< in: flush observer */
{
-#ifdef UNIV_DEBUG
- {
- /* Allow write to proceed to shared temporary tablespace
- in read-only mode. */
- ut_ad(!srv_read_only_mode
- || fsp_is_system_temporary(block->page.id.space()));
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
- ut_ad(block->page.buf_fix_count > 0);
-
- buf_pool_t* buf_pool = buf_pool_from_block(block);
-
- ut_ad(!buf_pool_mutex_own(buf_pool));
- ut_ad(!buf_flush_list_mutex_own(buf_pool));
- }
-#endif /* UNIV_DEBUG */
-
mutex_enter(&block->mutex);
-
+ ut_ad(!srv_read_only_mode
+ || fsp_is_system_temporary(block->page.id.space()));
+ ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
+ ut_ad(block->page.buf_fix_count > 0);
ut_ad(block->page.newest_modification <= end_lsn);
block->page.newest_modification = end_lsn;
@@ -98,52 +74,7 @@ buf_flush_note_modification(
ut_ad(block->page.oldest_modification <= start_lsn);
}
- buf_page_mutex_exit(block);
+ mutex_exit(&block->mutex);
srv_stats.buf_pool_write_requests.inc();
}
-
-/********************************************************************//**
-This function should be called when recovery has modified a buffer page. */
-UNIV_INLINE
-void
-buf_flush_recv_note_modification(
-/*=============================*/
- buf_block_t* block, /*!< in: block which is modified */
- lsn_t start_lsn, /*!< in: start lsn of the first mtr in a
- set of mtr's */
- lsn_t end_lsn) /*!< in: end lsn of the last mtr in the
- set of mtr's */
-{
-#ifdef UNIV_DEBUG
- {
- ut_ad(!srv_read_only_mode);
- ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
- ut_ad(block->page.buf_fix_count > 0);
-
- buf_pool_t* buf_pool = buf_pool_from_block(block);
-
- ut_ad(!buf_pool_mutex_own(buf_pool));
- ut_ad(!buf_flush_list_mutex_own(buf_pool));
-
- ut_ad(start_lsn != 0);
- ut_ad(block->page.newest_modification <= end_lsn);
- }
-#endif /* UNIV_DEBUG */
-
- buf_page_mutex_enter(block);
-
- block->page.newest_modification = end_lsn;
-
- if (!block->page.oldest_modification) {
- buf_pool_t* buf_pool = buf_pool_from_block(block);
-
- buf_flush_insert_sorted_into_flush_list(
- buf_pool, block, start_lsn);
- } else {
- ut_ad(block->page.oldest_modification <= start_lsn);
- }
-
- buf_page_mutex_exit(block);
-
-}
diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h
index e590d818334..ff0ba474bb3 100644
--- a/storage/innobase/include/buf0rea.h
+++ b/storage/innobase/include/buf0rea.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2017, MariaDB Corporation.
+Copyright (c) 2015, 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
@@ -34,30 +34,23 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@retval DB_SUCCESS if the page was read and is not corrupted,
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted,
@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but
after decryption normal page checksum does not match.
@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */
-dberr_t
-buf_read_page(
- const page_id_t page_id,
- const page_size_t& page_size);
+dberr_t buf_read_page(const page_id_t page_id, ulint zip_size);
-/********************************************************************//**
-High-level function which reads a page asynchronously from a file to the
+/** High-level function which reads a page asynchronously from a file to the
buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] sync true if synchronous aio is desired */
void
-buf_read_page_background(
- const page_id_t page_id,
- const page_size_t& page_size,
- bool sync);
+buf_read_page_background(const page_id_t page_id, ulint zip_size, bool sync);
/** Applies a random read-ahead in buf_pool if there are at least a threshold
value of accessed pages from the random read-ahead area. Does not read any
@@ -70,16 +63,13 @@ performed by ibuf routines, a situation which could result in a deadlock if
the OS does not support asynchronous i/o.
@param[in] page_id page id of a page which the current thread
wants to access
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether we are inside ibuf routine
@return number of page read requests issued; NOTE that if we read ibuf
pages, it may happen that the page at the given page number does not
get read even if we return a positive value! */
ulint
-buf_read_ahead_random(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf);
+buf_read_ahead_random(const page_id_t page_id, ulint zip_size, bool ibuf);
/** Applies linear read-ahead if in the buf_pool the page is a border page of
a linear read-ahead area and all the pages in the area have been accessed.
@@ -104,14 +94,11 @@ NOTE 3: the calling thread must want access to the page given: this rule is
set to prevent unintended read-aheads performed by ibuf routines, a situation
which could result in a deadlock if the OS does not support asynchronous io.
@param[in] page_id page id; see NOTE 3 above
-@param[in] page_size page size
-@param[in] inside_ibuf TRUE if we are inside ibuf routine
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] ibuf whether if we are inside ibuf routine
@return number of page read requests issued */
ulint
-buf_read_ahead_linear(
- const page_id_t page_id,
- const page_size_t& page_size,
- ibool inside_ibuf);
+buf_read_ahead_linear(const page_id_t page_id, ulint zip_size, bool ibuf);
/********************************************************************//**
Issues read requests for pages which the ibuf module wants to read in, in
diff --git a/storage/innobase/include/buf0types.h b/storage/innobase/include/buf0types.h
index bd5e26df47b..5532a524782 100644
--- a/storage/innobase/include/buf0types.h
+++ b/storage/innobase/include/buf0types.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+Copyright (c) 2019, 2020, 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
@@ -82,8 +83,16 @@ enum srv_checksum_algorithm_t {
innodb when reading */
SRV_CHECKSUM_ALGORITHM_NONE, /*!< Write none, allow crc32,
innodb or none when reading */
- SRV_CHECKSUM_ALGORITHM_STRICT_NONE /*!< Write none, allow none
+ SRV_CHECKSUM_ALGORITHM_STRICT_NONE, /*!< Write none, allow none
when reading */
+
+ /** For new files, always compute CRC-32C for the whole page.
+ For old files, allow crc32, innodb or none when reading. */
+ SRV_CHECKSUM_ALGORITHM_FULL_CRC32,
+
+ /** For new files, always compute CRC-32C for the whole page.
+ For old files, allow crc32 when reading. */
+ SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32
};
inline
@@ -202,6 +211,12 @@ private:
const page_id_t page_id);
};
+/** A field reference full of zero, for use in assertions and checks,
+and dummy default values of instantly dropped columns.
+Initially, BLOB field references are set to zero, in
+dtuple_convert_big_rec(). */
+extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX];
+
#ifndef UNIV_INNOCHECKSUM
#include "ut0mutex.h"
diff --git a/storage/innobase/include/data0data.h b/storage/innobase/include/data0data.h
index 11a7f2e516f..04ddf5b0a42 100644
--- a/storage/innobase/include/data0data.h
+++ b/storage/innobase/include/data0data.h
@@ -543,6 +543,33 @@ struct dtuple_t {
inserted or updated.
@param[in] index index possibly with instantly added columns */
void trim(const dict_index_t& index);
+
+ /**
+ @param info_bits the info_bits of a data tuple
+ @return whether this is a hidden metadata record
+ for instant ADD COLUMN or ALTER TABLE */
+ static bool is_alter_metadata(ulint info_bits)
+ {
+ return UNIV_UNLIKELY(info_bits == REC_INFO_METADATA_ALTER);
+ }
+
+ /**
+ @param info_bits the info_bits of a data tuple
+ @return whether this is a hidden metadata record
+ for instant ADD COLUMN or ALTER TABLE */
+ static bool is_metadata(ulint info_bits)
+ {
+ return UNIV_UNLIKELY((info_bits & ~REC_INFO_DELETED_FLAG)
+ == REC_INFO_METADATA_ADD);
+ }
+
+ /** @return whether this is a hidden metadata record
+ for instant ALTER TABLE (not only ADD COLUMN) */
+ bool is_alter_metadata() const { return is_alter_metadata(info_bits); }
+
+ /** @return whether this is a hidden metadata record
+ for instant ADD COLUMN or ALTER TABLE */
+ bool is_metadata() const { return is_metadata(info_bits); }
};
inline ulint dtuple_get_n_fields(const dtuple_t* tuple)
diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h
index 740a1b83aca..0e496085113 100644
--- a/storage/innobase/include/data0type.h
+++ b/storage/innobase/include/data0type.h
@@ -262,35 +262,31 @@ dtype_get_at_most_n_mbchars(
ulint data_len, /*!< in: length of str (in bytes) */
const char* str); /*!< in: the string whose prefix
length is being determined */
-/*********************************************************************//**
-Checks if a data main type is a string type. Also a BLOB is considered a
-string type.
-@return TRUE if string type */
-ibool
-dtype_is_string_type(
-/*=================*/
- ulint mtype); /*!< in: InnoDB main data type code: DATA_CHAR, ... */
-/*********************************************************************//**
-Checks if a type is a binary string type. Note that for tables created with
-< 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column. For
-those DATA_BLOB columns this function currently returns FALSE.
-@return TRUE if binary string type */
-ibool
-dtype_is_binary_string_type(
-/*========================*/
- ulint mtype, /*!< in: main data type */
- ulint prtype);/*!< in: precise type */
-/*********************************************************************//**
-Checks if a type is a non-binary string type. That is, dtype_is_string_type is
-TRUE and dtype_is_binary_string_type is FALSE. Note that for tables created
-with < 4.0.14, we do not know if a DATA_BLOB column is a BLOB or a TEXT column.
-For those DATA_BLOB columns this function currently returns TRUE.
-@return TRUE if non-binary string type */
-ibool
-dtype_is_non_binary_string_type(
-/*============================*/
- ulint mtype, /*!< in: main data type */
- ulint prtype);/*!< in: precise type */
+/** @return whether main type is a string type */
+inline bool dtype_is_string_type(ulint mtype)
+{
+ return mtype <= DATA_BLOB
+ || mtype == DATA_MYSQL || mtype == DATA_VARMYSQL;
+}
+
+/** @return whether a type is a binary string type */
+inline bool dtype_is_binary_string_type(ulint mtype, ulint prtype)
+{
+ /* Note that for tables created before MySQL 4.0.14,
+ we do not know if a DATA_BLOB column is a BLOB or a TEXT column.
+ For those DATA_BLOB columns we return false. */
+
+ return mtype == DATA_FIXBINARY || mtype == DATA_BINARY
+ || (mtype == DATA_BLOB && (prtype & DATA_BINARY_TYPE));
+}
+
+/** @return whether a type is a non-binary string type */
+inline bool dtype_is_non_binary_string_type(ulint mtype, ulint prtype)
+{
+ return dtype_is_string_type(mtype)
+ && !dtype_is_binary_string_type(mtype, prtype);
+}
+
/*********************************************************************//**
Sets a data type structure. */
UNIV_INLINE
@@ -338,14 +334,15 @@ dtype_get_mblen(
multi-byte character */
ulint* mbmaxlen); /*!< out: maximum length of a
multi-byte character */
-/*********************************************************************//**
-Gets the MySQL charset-collation code for MySQL string types.
-@return MySQL charset-collation code */
-UNIV_INLINE
-ulint
-dtype_get_charset_coll(
-/*===================*/
- ulint prtype);/*!< in: precise data type */
+/**
+Get the charset-collation code for string types.
+@param prtype InnoDB precise type
+@return charset-collation code */
+inline uint16_t dtype_get_charset_coll(ulint prtype)
+{
+ return static_cast<uint16_t>(prtype >> 16) & CHAR_COLL_MASK;
+}
+
/** Form a precise type from the < 4.1.2 format precise type plus the
charset-collation code.
@param[in] old_prtype MySQL type code and the flags
@@ -554,11 +551,55 @@ struct dtype_t{
{
return (prtype & DATA_VERSIONED) == DATA_VERS_END;
}
+
+ /** Set the type of the BLOB in the hidden metadata record. */
+ void metadata_blob_init()
+ {
+ prtype = DATA_NOT_NULL;
+ mtype = DATA_BLOB;
+ len = 0;
+ mbminlen = 0;
+ mbmaxlen = 0;
+ }
};
/** The DB_TRX_ID,DB_ROLL_PTR values for "no history is available" */
extern const byte reset_trx_id[DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN];
+/** Info bit denoting the predefined minimum record: this bit is set
+if and only if the record is the first user record on a non-leaf
+B-tree page that is the leftmost page on its level
+(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */
+#define REC_INFO_MIN_REC_FLAG 0x10UL
+/** The delete-mark flag in info bits */
+#define REC_INFO_DELETED_FLAG 0x20UL
+
+/** Record status values for ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED */
+enum rec_comp_status_t {
+ /** User record (PAGE_LEVEL=0, heap>=PAGE_HEAP_NO_USER_LOW) */
+ REC_STATUS_ORDINARY = 0,
+ /** Node pointer record (PAGE_LEVEL>=0, heap>=PAGE_HEAP_NO_USER_LOW) */
+ REC_STATUS_NODE_PTR = 1,
+ /** The page infimum pseudo-record (heap=PAGE_HEAP_NO_INFIMUM) */
+ REC_STATUS_INFIMUM = 2,
+ /** The page supremum pseudo-record (heap=PAGE_HEAP_NO_SUPREMUM) */
+ REC_STATUS_SUPREMUM = 3,
+ /** Clustered index record that has been inserted or updated
+ after instant ADD COLUMN (more than dict_index_t::n_core_fields) */
+ REC_STATUS_INSTANT = 4
+};
+
+/** The dtuple_t::info_bits of the hidden metadata of instant ADD COLUMN.
+@see rec_is_metadata()
+@see rec_is_alter_metadata() */
+static const byte REC_INFO_METADATA_ADD
+ = REC_INFO_MIN_REC_FLAG | REC_STATUS_INSTANT;
+
+/** The dtuple_t::info_bits of the hidden metadata of instant ALTER TABLE.
+@see rec_is_metadata() */
+static const byte REC_INFO_METADATA_ALTER
+ = REC_INFO_METADATA_ADD | REC_INFO_DELETED_FLAG;
+
#include "data0type.ic"
#endif
diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic
index f2c499716ce..037a71a9345 100644
--- a/storage/innobase/include/data0type.ic
+++ b/storage/innobase/include/data0type.ic
@@ -28,18 +28,6 @@ Created 1/16/1996 Heikki Tuuri
#include "ha_prototypes.h"
/*********************************************************************//**
-Gets the MySQL charset-collation code for MySQL string types.
-@return MySQL charset-collation code */
-UNIV_INLINE
-ulint
-dtype_get_charset_coll(
-/*===================*/
- ulint prtype) /*!< in: precise data type */
-{
- return((prtype >> 16) & CHAR_COLL_MASK);
-}
-
-/*********************************************************************//**
Determines if a MySQL string type is a subset of UTF-8. This function
may return false negatives, in case further character-set collation
codes are introduced in MySQL later.
diff --git a/storage/innobase/include/db0err.h b/storage/innobase/include/db0err.h
index f70a65890c9..6cfc63f4a9e 100644
--- a/storage/innobase/include/db0err.h
+++ b/storage/innobase/include/db0err.h
@@ -136,8 +136,6 @@ enum dberr_t {
DB_FTS_TOO_MANY_WORDS_IN_PHRASE,
/*< Too many words in a phrase */
- DB_TABLESPACE_TRUNCATED, /*!< tablespace was truncated */
-
DB_DECRYPTION_FAILED, /* Tablespace encrypted and
decrypt operation failed because
of missing key management plugin,
diff --git a/storage/innobase/include/dict0boot.h b/storage/innobase/include/dict0boot.h
index 4853d5ad73f..778471b77ae 100644
--- a/storage/innobase/include/dict0boot.h
+++ b/storage/innobase/include/dict0boot.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2018, 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
@@ -50,12 +51,8 @@ dict_hdr_get_new_id(
(not assigned if NULL) */
index_id_t* index_id, /*!< out: index id
(not assigned if NULL) */
- ulint* space_id, /*!< out: space id
+ ulint* space_id); /*!< out: space id
(not assigned if NULL) */
- const dict_table_t* table, /*!< in: table */
- bool disable_redo); /*!< in: if true and table
- object is NULL
- then disable-redo */
/**********************************************************************//**
Writes the current value of the row id counter to the dictionary header file
page. */
@@ -124,13 +121,6 @@ dict_is_sys_table(
/* The following is a secondary index on SYS_TABLES */
#define DICT_TABLE_IDS_ID 5
-#define DICT_HDR_FIRST_ID 10 /* the ids for tables etc. start
- from this number, except for basic
- system tables and their above defined
- indexes; ibuf tables and indexes are
- assigned as the id the number
- DICT_IBUF_ID_MIN plus the space id */
-
/* The offset of the dictionary header on the page */
#define DICT_HDR FSEG_PAGE_DATA
diff --git a/storage/innobase/include/dict0boot.ic b/storage/innobase/include/dict0boot.ic
index dacfcd58b53..7b0a2fd0b86 100644
--- a/storage/innobase/include/dict0boot.ic
+++ b/storage/innobase/include/dict0boot.ic
@@ -33,18 +33,18 @@ dict_sys_get_new_row_id(void)
{
row_id_t id;
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
- id = dict_sys->row_id;
+ id = dict_sys.row_id;
if (0 == (id % DICT_HDR_ROW_ID_WRITE_MARGIN)) {
dict_hdr_flush_row_id();
}
- dict_sys->row_id++;
+ dict_sys.row_id++;
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
return(id);
}
diff --git a/storage/innobase/include/dict0crea.h b/storage/innobase/include/dict0crea.h
index 8ab987cd39a..92f55ce4a14 100644
--- a/storage/innobase/include/dict0crea.h
+++ b/storage/innobase/include/dict0crea.h
@@ -67,14 +67,6 @@ dict_create_table_step(
/*===================*/
que_thr_t* thr); /*!< in: query thread */
-/** Assign a new table ID and put it into the table cache and the transaction.
-@param[in,out] table Table that needs an ID
-@param[in,out] trx Transaction */
-void
-dict_table_assign_new_id(
- dict_table_t* table,
- trx_t* trx);
-
/***********************************************************//**
Creates an index. This is a high-level function used in SQL execution
graphs.
@@ -104,29 +96,12 @@ dict_create_index_tree(
dict_index_t* index, /*!< in/out: index */
const trx_t* trx); /*!< in: InnoDB transaction handle */
-/*******************************************************************//**
-Recreate the index tree associated with a row in SYS_INDEXES table.
-@return new root page number, or FIL_NULL on failure */
-ulint
-dict_recreate_index_tree(
-/*======================*/
- const dict_table_t* table, /*!< in: the table the index
- belongs to */
- btr_pcur_t* pcur, /*!< in/out: persistent cursor pointing
- to record in the clustered index of
- SYS_INDEXES table. The cursor may be
- repositioned in this call. */
- mtr_t* mtr); /*!< in: mtr having the latch
- on the record page. The mtr may be
- committed and restarted in this call. */
-
/** Drop the index tree associated with a row in SYS_INDEXES table.
@param[in,out] rec SYS_INDEXES record
@param[in,out] pcur persistent cursor on rec
@param[in,out] trx dictionary transaction
-@param[in,out] mtr mini-transaction
-@return whether freeing the B-tree was attempted */
-bool dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
+@param[in,out] mtr mini-transaction */
+void dict_drop_index_tree(rec_t* rec, btr_pcur_t* pcur, trx_t* trx, mtr_t* mtr)
MY_ATTRIBUTE((nonnull));
/***************************************************************//**
diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h
index 9f5485bb15c..35309fc1b54 100644
--- a/storage/innobase/include/dict0dict.h
+++ b/storage/innobase/include/dict0dict.h
@@ -32,12 +32,13 @@ Created 1/8/1996 Heikki Tuuri
#include "dict0mem.h"
#include "fsp0fsp.h"
#include <deque>
-#include "dict0pagecompress.h"
extern bool innodb_table_stats_not_found;
extern bool innodb_index_stats_not_found;
-#include "sync0rw.h"
+/** the first table or index ID for other than hard-coded system tables */
+constexpr uint8_t DICT_HDR_FIRST_ID= 10;
+
/********************************************************************//**
Get the database name length in a table name.
@return database name length */
@@ -130,19 +131,14 @@ dict_table_close(
MY_ATTRIBUTE((nonnull));
/*********************************************************************//**
Closes the only open handle to a table and drops a table while assuring
-that dict_sys->mutex is held the whole time. This assures that the table
+that dict_sys.mutex is held the whole time. This assures that the table
is not evicted after the close when the count of open handles goes to zero.
-Because dict_sys->mutex is held, we do not need to call
-dict_table_prevent_eviction(). */
+Because dict_sys.mutex is held, we do not need to call prevent_eviction(). */
void
dict_table_close_and_drop(
/*======================*/
trx_t* trx, /*!< in: data dictionary transaction */
dict_table_t* table); /*!< in/out: table */
-/**********************************************************************//**
-Inits the data dictionary module. */
-void
-dict_init(void);
/*********************************************************************//**
Gets the minimum number of bytes per character.
@@ -287,13 +283,6 @@ dict_col_name_is_reserved(
/*======================*/
const char* name) /*!< in: column name */
MY_ATTRIBUTE((nonnull, warn_unused_result));
-/********************************************************************//**
-Acquire the autoinc lock. */
-void
-dict_table_autoinc_lock(
-/*====================*/
- dict_table_t* table) /*!< in/out: table */
- MY_ATTRIBUTE((nonnull));
/** Unconditionally set the AUTO_INCREMENT counter.
@param[in,out] table table or partition
@param[in] value next available AUTO_INCREMENT value */
@@ -302,7 +291,7 @@ UNIV_INLINE
void
dict_table_autoinc_initialize(dict_table_t* table, ib_uint64_t value)
{
- ut_ad(dict_table_autoinc_own(table));
+ ut_ad(mutex_own(&table->autoinc_mutex));
table->autoinc = value;
}
@@ -315,7 +304,7 @@ UNIV_INLINE
ib_uint64_t
dict_table_autoinc_read(const dict_table_t* table)
{
- ut_ad(dict_table_autoinc_own(table));
+ ut_ad(mutex_own(&table->autoinc_mutex));
return(table->autoinc);
}
@@ -329,7 +318,7 @@ UNIV_INLINE
bool
dict_table_autoinc_update_if_greater(dict_table_t* table, ib_uint64_t value)
{
- ut_ad(dict_table_autoinc_own(table));
+ ut_ad(mutex_own(&table->autoinc_mutex));
if (value > table->autoinc) {
@@ -340,13 +329,6 @@ dict_table_autoinc_update_if_greater(dict_table_t* table, ib_uint64_t value)
return(false);
}
-/********************************************************************//**
-Release the autoinc lock. */
-void
-dict_table_autoinc_unlock(
-/*======================*/
- dict_table_t* table) /*!< in/out: table */
- MY_ATTRIBUTE((nonnull));
/**********************************************************************//**
Adds system columns to a table object. */
void
@@ -356,22 +338,6 @@ dict_table_add_system_columns(
mem_heap_t* heap) /*!< in: temporary heap */
MY_ATTRIBUTE((nonnull));
/**********************************************************************//**
-Removes a table object from the dictionary cache. */
-void
-dict_table_remove_from_cache(
-/*=========================*/
- dict_table_t* table) /*!< in, own: table */
- MY_ATTRIBUTE((nonnull));
-/**********************************************************************//**
-Removes a table object from the dictionary cache. */
-void
-dict_table_remove_from_cache_low(
-/*=============================*/
- dict_table_t* table, /*!< in, own: table */
- ibool lru_evict) /*!< in: TRUE if table being evicted
- to make room in the table LRU list */
- MY_ATTRIBUTE((nonnull));
-/**********************************************************************//**
Renames a table object.
@return TRUE if success */
dberr_t
@@ -694,65 +660,14 @@ do { \
dict_table_skip_corrupt_index(index); \
} while (0)
-/********************************************************************//**
-Check whether the index is the clustered index.
-@return nonzero for clustered index, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_clust(
-/*================*/
- const dict_index_t* index) /*!< in: index */
- MY_ATTRIBUTE((warn_unused_result));
-
-/** Check if index is auto-generated clustered index.
-@param[in] index index
-
-@return true if index is auto-generated clustered index. */
-UNIV_INLINE
-bool
-dict_index_is_auto_gen_clust(
- const dict_index_t* index);
-
-/********************************************************************//**
-Check whether the index is unique.
-@return nonzero for unique index, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_unique(
-/*=================*/
- const dict_index_t* index) /*!< in: index */
- MY_ATTRIBUTE((warn_unused_result));
-/********************************************************************//**
-Check whether the index is a Spatial Index.
-@return nonzero for Spatial Index, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_spatial(
-/*==================*/
- const dict_index_t* index) /*!< in: index */
- MY_ATTRIBUTE((warn_unused_result));
-
+#define dict_index_is_clust(index) (index)->is_clust()
+#define dict_index_is_auto_gen_clust(index) (index)->is_gen_clust()
+#define dict_index_is_unique(index) (index)->is_unique()
+#define dict_index_is_spatial(index) (index)->is_spatial()
+#define dict_index_is_ibuf(index) (index)->is_ibuf()
+#define dict_index_is_sec_or_ibuf(index) !(index)->is_primary()
#define dict_index_has_virtual(index) (index)->has_virtual()
-/********************************************************************//**
-Check whether the index is the insert buffer tree.
-@return nonzero for insert buffer, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_ibuf(
-/*===============*/
- const dict_index_t* index) /*!< in: index */
- MY_ATTRIBUTE((warn_unused_result));
-/********************************************************************//**
-Check whether the index is a secondary index or the insert buffer tree.
-@return nonzero for insert buffer, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_sec_or_ibuf(
-/*======================*/
- const dict_index_t* index) /*!< in: index */
- MY_ATTRIBUTE((warn_unused_result));
-
/** Get all the FTS indexes on a table.
@param[in] table table
@param[out] indexes all FTS indexes on this table
@@ -908,15 +823,8 @@ dict_index_get_min_size(
/*====================*/
const dict_index_t* index) /*!< in: index */
MY_ATTRIBUTE((nonnull, warn_unused_result));
-/********************************************************************//**
-Check whether the table uses the compact page format.
-@return TRUE if table uses the compact page format */
-UNIV_INLINE
-bool
-dict_table_is_comp(
-/*===============*/
- const dict_table_t* table) /*!< in: table */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
+
+#define dict_table_is_comp(table) (table)->not_redundant()
/** Determine if a table uses atomic BLOBs (no locally stored prefix).
@param[in] table InnoDB table
@@ -928,6 +836,18 @@ dict_table_has_atomic_blobs(const dict_table_t* table)
return(DICT_TF_HAS_ATOMIC_BLOBS(table->flags));
}
+/** @return potential max length stored inline for externally stored fields */
+inline size_t dict_table_t::get_overflow_field_local_len() const
+{
+ if (dict_table_has_atomic_blobs(this)) {
+ /* ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED: do not
+ store any BLOB prefix locally */
+ return BTR_EXTERN_FIELD_REF_SIZE;
+ }
+ /* up to MySQL 5.1: store a 768-byte prefix locally */
+ return BTR_EXTERN_FIELD_REF_SIZE + DICT_ANTELOPE_MAX_INDEX_COL_LEN;
+}
+
/** Set the various values in a dict_table_t::flags pointer.
@param[in,out] flags, Pointer to a 4 byte Table Flags
@param[in] format, File Format
@@ -962,44 +882,34 @@ ulint
dict_tf_to_fsp_flags(ulint table_flags)
MY_ATTRIBUTE((const));
-/** Extract the page size from table flags.
+
+/** Extract the ROW_FORMAT=COMPRESSED page size from table flags.
@param[in] flags flags
-@return compressed page size, or 0 if not compressed */
-UNIV_INLINE
-const page_size_t
-dict_tf_get_page_size(
- ulint flags)
-MY_ATTRIBUTE((const));
+@return ROW_FORMAT=COMPRESSED page size
+@retval 0 if not compressed */
+inline ulint dict_tf_get_zip_size(ulint flags)
+{
+ flags &= DICT_TF_MASK_ZIP_SSIZE;
+ return flags
+ ? (UNIV_ZIP_SIZE_MIN >> 1)
+ << (FSP_FLAGS_GET_ZIP_SSIZE(flags >> DICT_TF_POS_ZIP_SSIZE
+ << FSP_FLAGS_POS_ZIP_SSIZE))
+ : 0;
+}
/** Determine the extent size (in pages) for the given table
@param[in] table the table whose extent size is being
calculated.
@return extent size in pages (256, 128 or 64) */
-ulint
-dict_table_extent_size(
- const dict_table_t* table);
+inline ulint dict_table_extent_size(const dict_table_t* table)
+{
+ if (ulint zip_size = table->space->zip_size()) {
+ return (1ULL << 20) / zip_size;
+ }
-/** Get the table page size. */
-#define dict_table_page_size(table) page_size_t(table->space->flags)
+ return FSP_EXTENT_SIZE;
+}
-/*********************************************************************//**
-Obtain exclusive locks on all index trees of the table. This is to prevent
-accessing index trees while InnoDB is updating internal metadata for
-operations such as truncate tables. */
-UNIV_INLINE
-void
-dict_table_x_lock_indexes(
-/*======================*/
- dict_table_t* table) /*!< in: table */
- MY_ATTRIBUTE((nonnull));
-/*********************************************************************//**
-Release the exclusive locks on all index tree. */
-UNIV_INLINE
-void
-dict_table_x_unlock_indexes(
-/*========================*/
- dict_table_t* table) /*!< in: table */
- MY_ATTRIBUTE((nonnull));
/********************************************************************//**
Checks if a column is in the ordering columns of the clustered index of a
table. Column prefixes are treated like whole columns.
@@ -1061,10 +971,6 @@ dict_make_room_in_cache(
ulint max_tables, /*!< in: max tables allowed in cache */
ulint pct_check); /*!< in: max percent to check */
-/** Clears the virtual column's index list before index is being freed.
-@param[in] index Index being freed */
-void dict_index_remove_from_v_col_list(dict_index_t* index);
-
/** Adds an index to the dictionary cache, with possible indexing newly
added column.
@param[in,out] index index; NOTE! The index memory
@@ -1210,21 +1116,6 @@ dict_index_get_nth_col_or_prefix_pos(
ulint* prefix_col_pos) /*!< out: col num if prefix
*/
__attribute__((warn_unused_result));
-
-/********************************************************************//**
-Returns TRUE if the index contains a column or a prefix of that column.
-@param[in] index index
-@param[in] n column number
-@param[in] is_virtual whether it is a virtual col
-@return TRUE if contains the column or its prefix */
-bool
-dict_index_contains_col_or_prefix(
-/*==============================*/
- const dict_index_t* index, /*!< in: index */
- ulint n, /*!< in: column number */
- bool is_virtual)
- /*!< in: whether it is a virtual col */
- MY_ATTRIBUTE((warn_unused_result));
/********************************************************************//**
Looks for a matching field in an index. The column has to be the same. The
column in index must be complete, or must contain a prefix longer than the
@@ -1249,16 +1140,6 @@ dict_table_get_nth_col_pos(
ulint n, /*!< in: column number */
ulint* prefix_col_pos) /*!< out: col num if prefix */
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
-/********************************************************************//**
-Returns the position of a system column in an index.
-@return position, ULINT_UNDEFINED if not contained */
-UNIV_INLINE
-ulint
-dict_index_get_sys_col_pos(
-/*=======================*/
- const dict_index_t* index, /*!< in: index */
- ulint type) /*!< in: DATA_ROW_ID, ... */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
/*******************************************************************//**
Adds a column to index. */
void
@@ -1292,7 +1173,7 @@ dict_field_get_col(
/**********************************************************************//**
Returns an index object if it is found in the dictionary cache.
-Assumes that dict_sys->mutex is already being held.
+Assumes that dict_sys.mutex is already being held.
@return index, NULL if not found */
dict_index_t*
dict_index_get_if_in_cache_low(
@@ -1356,21 +1237,6 @@ dict_index_build_node_ptr(
ulint level) /*!< in: level of rec in tree:
0 means leaf level */
MY_ATTRIBUTE((nonnull, warn_unused_result));
-/**********************************************************************//**
-Copies an initial segment of a physical record, long enough to specify an
-index entry uniquely.
-@return pointer to the prefix record */
-rec_t*
-dict_index_copy_rec_order_prefix(
-/*=============================*/
- const dict_index_t* index, /*!< in: index */
- const rec_t* rec, /*!< in: record for which to
- copy prefix */
- ulint* n_fields,/*!< out: number of fields copied */
- byte** buf, /*!< in/out: memory buffer for the
- copied prefix, or NULL */
- ulint* buf_size)/*!< in/out: buffer size */
- MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Convert a physical record into a search tuple.
@param[in] rec index record (not necessarily in an index page)
@param[in] index index
@@ -1455,53 +1321,9 @@ dict_index_calc_min_rec_len(
/*========================*/
const dict_index_t* index) /*!< in: index */
MY_ATTRIBUTE((nonnull, warn_unused_result));
-/** Reserve the dictionary system mutex. */
-void
-dict_mutex_enter_for_mysql_func(const char *file, unsigned line);
-#define dict_mutex_enter_for_mysql() \
- dict_mutex_enter_for_mysql_func(__FILE__, __LINE__)
-
-/********************************************************************//**
-Releases the dictionary system mutex for MySQL. */
-void
-dict_mutex_exit_for_mysql(void);
-/*===========================*/
-
-/** Create a dict_table_t's stats latch or delay for lazy creation.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose stats latch to create
-@param[in] enabled if false then the latch is disabled
-and dict_table_stats_lock()/unlock() become noop on this table. */
-void
-dict_table_stats_latch_create(
- dict_table_t* table,
- bool enabled);
-
-/** Destroy a dict_table_t's stats latch.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose stats latch to destroy */
-void
-dict_table_stats_latch_destroy(
- dict_table_t* table);
-
-/** Lock the appropriate latch to protect a given table's statistics.
-@param[in] table table whose stats to lock
-@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
-void
-dict_table_stats_lock(
- dict_table_t* table,
- ulint latch_mode);
-
-/** Unlock the latch that has been locked by dict_table_stats_lock().
-@param[in] table table whose stats to unlock
-@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
-void
-dict_table_stats_unlock(
- dict_table_t* table,
- ulint latch_mode);
+#define dict_mutex_enter_for_mysql() mutex_enter(&dict_sys.mutex)
+#define dict_mutex_exit_for_mysql() mutex_exit(&dict_sys.mutex)
/********************************************************************//**
Checks if the database name in two table names is the same.
@@ -1547,23 +1369,6 @@ dict_table_is_fts_column(
ulint col_no, /* in: col number to search for */
bool is_virtual)/*!< in: whether it is a virtual column */
MY_ATTRIBUTE((warn_unused_result));
-/**********************************************************************//**
-Prevent table eviction by moving a table to the non-LRU list from the
-LRU list if it is not already there. */
-UNIV_INLINE
-void
-dict_table_prevent_eviction(
-/*========================*/
- dict_table_t* table) /*!< in: table to prevent eviction */
- MY_ATTRIBUTE((nonnull));
-
-/**********************************************************************//**
-Move a table to the non LRU end of the LRU list. */
-void
-dict_table_move_from_lru_to_non_lru(
-/*================================*/
- dict_table_t* table) /*!< in: table to move from LRU to non-LRU */
- MY_ATTRIBUTE((nonnull));
/** Looks for an index with the given id given a table instance.
@param[in] table table instance
@@ -1575,14 +1380,6 @@ dict_table_find_index_on_id(
index_id_t id)
MY_ATTRIBUTE((nonnull(1)));
-/**********************************************************************//**
-Move to the most recently used segment of the LRU list. */
-void
-dict_move_to_mru(
-/*=============*/
- dict_table_t* table) /*!< in: table to move to MRU */
- MY_ATTRIBUTE((nonnull));
-
/** Maximum number of columns in a foreign key constraint. Please Note MySQL
has a much lower limit on the number of columns allowed in a foreign key
constraint */
@@ -1594,13 +1391,10 @@ extern FILE* dict_foreign_err_file;
extern ib_mutex_t dict_foreign_err_mutex; /* mutex protecting the
foreign key error messages */
-/** the dictionary system */
-extern dict_sys_t* dict_sys;
-/** the data dictionary rw-latch protecting dict_sys */
-extern rw_lock_t dict_operation_lock;
-
-/* Dictionary system struct */
-struct dict_sys_t{
+/** InnoDB data dictionary cache */
+class dict_sys_t
+{
+public:
DictSysMutex mutex; /*!< mutex protecting the data
dictionary; protects also the
disk-based dictionary system tables;
@@ -1608,6 +1402,15 @@ struct dict_sys_t{
and DROP TABLE, as well as reading
the dictionary data for a table from
system tables */
+ /** @brief the data dictionary rw-latch protecting dict_sys
+
+ Table create, drop, etc. reserve this in X-mode; implicit or
+ backround operations purge, rollback, foreign key checks reserve this
+ in S-mode; not all internal InnoDB operations are covered by MDL.
+
+ This latch also prevents lock waits when accessing the InnoDB
+ data dictionary tables. @see trx_t::dict_operation_lock_mode */
+ rw_lock_t latch;
row_id_t row_id; /*!< the next row id to assign;
NOTE that at a checkpoint this
must be written to the dict system
@@ -1616,8 +1419,8 @@ struct dict_sys_t{
the log records */
hash_table_t* table_hash; /*!< hash table of the tables, based
on name */
- hash_table_t* table_id_hash; /*!< hash table of the tables, based
- on id */
+ /** hash table of persistent table IDs */
+ hash_table_t* table_id_hash;
dict_table_t* sys_tables; /*!< SYS_TABLES table */
dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
@@ -1631,8 +1434,145 @@ struct dict_sys_t{
UT_LIST_BASE_NODE_T(dict_table_t)
table_non_LRU; /*!< List of tables that can't be
evicted from the cache */
+private:
+ bool m_initialised;
+ /** the sequence of temporary table IDs */
+ std::atomic<table_id_t> temp_table_id;
+ /** hash table of temporary table IDs */
+ hash_table_t* temp_id_hash;
+public:
+ /** @return a new temporary table ID */
+ table_id_t get_temporary_table_id() {
+ return temp_table_id.fetch_add(1, std::memory_order_relaxed);
+ }
+
+ /** Look up a temporary table.
+ @param id temporary table ID
+ @return temporary table
+ @retval NULL if the table does not exist
+ (should only happen during the rollback of CREATE...SELECT) */
+ dict_table_t* get_temporary_table(table_id_t id)
+ {
+ ut_ad(mutex_own(&mutex));
+ dict_table_t* table;
+ ulint fold = ut_fold_ull(id);
+ HASH_SEARCH(id_hash, temp_id_hash, fold, dict_table_t*, table,
+ ut_ad(table->cached), table->id == id);
+ if (UNIV_LIKELY(table != NULL)) {
+ DBUG_ASSERT(table->is_temporary());
+ DBUG_ASSERT(table->id >= DICT_HDR_FIRST_ID);
+ table->acquire();
+ }
+ return table;
+ }
+
+ /** Look up a persistent table.
+ @param id table ID
+ @return table
+ @retval NULL if not cached */
+ dict_table_t* get_table(table_id_t id)
+ {
+ ut_ad(mutex_own(&mutex));
+ dict_table_t* table;
+ ulint fold = ut_fold_ull(id);
+ HASH_SEARCH(id_hash, table_id_hash, fold, dict_table_t*, table,
+ ut_ad(table->cached), table->id == id);
+ DBUG_ASSERT(!table || !table->is_temporary());
+ return table;
+ }
+
+ /**
+ Constructor. Further initialisation happens in create().
+ */
+
+ dict_sys_t() : m_initialised(false), temp_table_id(DICT_HDR_FIRST_ID) {}
+
+ bool is_initialised() const { return m_initialised; }
+
+ /** Initialise the data dictionary cache. */
+ void create();
+
+ /** Close the data dictionary cache on shutdown. */
+ void close();
+
+ /** Resize the hash tables based on the current buffer pool size. */
+ void resize();
+
+ /** Add a table definition to the data dictionary cache */
+ inline void add(dict_table_t* table);
+ /** Remove a table definition from the data dictionary cache.
+ @param[in,out] table cached table definition to be evicted
+ @param[in] lru whether this is part of least-recently-used evictiono
+ @param[in] keep whether to keep (not free) the object */
+ void remove(dict_table_t* table, bool lru = false, bool keep = false);
+
+#ifdef UNIV_DEBUG
+ /** Find a table */
+ template <bool in_lru> bool find(dict_table_t* table)
+ {
+ ut_ad(table);
+ ut_ad(table->can_be_evicted == in_lru);
+ ut_ad(mutex_own(&mutex));
+ for (const dict_table_t* t = UT_LIST_GET_FIRST(in_lru
+ ? table_LRU : table_non_LRU);
+ t; t = UT_LIST_GET_NEXT(table_LRU, t))
+ {
+ if (t == table) return true;
+ ut_ad(t->can_be_evicted == in_lru);
+ }
+ return false;
+ }
+ /** Find a table */
+ bool find(dict_table_t* table)
+ {
+ return table->can_be_evicted ? find<true>(table) : find<false>(table);
+ }
+#endif
+
+ /** Move a table to the non-LRU list from the LRU list. */
+ void prevent_eviction(dict_table_t* table)
+ {
+ ut_ad(find(table));
+ if (table->can_be_evicted)
+ {
+ table->can_be_evicted = FALSE;
+ UT_LIST_REMOVE(table_LRU, table);
+ UT_LIST_ADD_LAST(table_non_LRU, table);
+ }
+ }
+ /** Acquire a reference to a cached table. */
+ inline void acquire(dict_table_t* table);
+
+#ifdef UNIV_DEBUG
+ /** Assert that the data dictionary is locked */
+ void assert_locked()
+ {
+ ut_ad(mutex_own(&mutex));
+ ut_ad(rw_lock_own(&latch, RW_LOCK_X));
+ }
+#endif
+ /** Lock the data dictionary cache. */
+ void lock(const char* file, unsigned line)
+ {
+ rw_lock_x_lock_func(&latch, 0, file, line);
+ mutex_enter_loc(&mutex, file, line);
+ }
+
+ /** Unlock the data dictionary cache. */
+ void unlock()
+ {
+ mutex_exit(&mutex);
+ rw_lock_x_unlock(&latch);
+ }
};
+/** the data dictionary cache */
+extern dict_sys_t dict_sys;
+
+#define dict_table_prevent_eviction(table) dict_sys.prevent_eviction(table)
+#define dict_sys_lock() dict_sys.lock(__FILE__, __LINE__)
+#define dict_sys_unlock() dict_sys.unlock()
+
/** dummy index for ROW_FORMAT=REDUNDANT supremum and infimum records */
extern dict_index_t* dict_ind_redundant;
@@ -1716,16 +1656,6 @@ dict_fs2utf8(
size_t table_utf8_size)/*!< in: table_utf8 size */
MY_ATTRIBUTE((nonnull));
-/** Resize the hash tables besed on the current buffer pool size. */
-void
-dict_resize();
-
-/**********************************************************************//**
-Closes the data dictionary module. */
-void
-dict_close(void);
-/*============*/
-
/**********************************************************************//**
Check whether the table is corrupted.
@return nonzero for corrupted table, zero for valid tables */
diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic
index 4174580c918..b6d15f28a69 100644
--- a/storage/innobase/include/dict0dict.ic
+++ b/storage/innobase/include/dict0dict.ic
@@ -25,6 +25,7 @@ Created 1/8/1996 Heikki Tuuri
***********************************************************************/
#include "fsp0sysspace.h"
+#include "dict0pagecompress.h"
/*********************************************************************//**
Gets the minimum number of bytes per character.
@@ -241,83 +242,6 @@ dict_table_get_next_index(
#endif /* UNIV_DEBUG */
/********************************************************************//**
-Check whether the index is the clustered index.
-@return nonzero for clustered index, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_clust(
-/*================*/
- const dict_index_t* index) /*!< in: index */
-{
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- return(index->type & DICT_CLUSTERED);
-}
-
-/** Check if index is auto-generated clustered index.
-@param[in] index index
-
-@return true if index is auto-generated clustered index. */
-UNIV_INLINE
-bool
-dict_index_is_auto_gen_clust(
- const dict_index_t* index)
-{
- return(index->type == DICT_CLUSTERED);
-}
-
-/********************************************************************//**
-Check whether the index is unique.
-@return nonzero for unique index, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_unique(
-/*=================*/
- const dict_index_t* index) /*!< in: index */
-{
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- return(index->type & DICT_UNIQUE);
-}
-
-/********************************************************************//**
-Check whether the index is a Spatial Index.
-@return nonzero for Spatial Index, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_spatial(
-/*==================*/
- const dict_index_t* index) /*!< in: index */
-{
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- return ulint(UNIV_EXPECT(index->type & DICT_SPATIAL, 0));
-}
-
-/********************************************************************//**
-Check whether the index is the insert buffer tree.
-@return nonzero for insert buffer, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_ibuf(
-/*===============*/
- const dict_index_t* index) /*!< in: index */
-{
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- return(index->type & DICT_IBUF);
-}
-
-/********************************************************************//**
-Check whether the index is a secondary index or the insert buffer tree.
-@return nonzero for insert buffer, zero for other indexes */
-UNIV_INLINE
-ulint
-dict_index_is_sec_or_ibuf(
-/*======================*/
- const dict_index_t* index) /*!< in: index */
-{
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- return((index->type & (DICT_CLUSTERED | DICT_IBUF)) != DICT_CLUSTERED);
-}
-
-/********************************************************************//**
Gets the number of user-defined non-virtual columns in a table in the
dictionary cache.
@return number of user-defined (e.g., not ROW_ID) non-virtual
@@ -462,7 +386,8 @@ dict_table_get_nth_v_col(
ut_ad(table);
ut_ad(pos < table->n_v_def);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
- ut_ad(!table->v_cols[pos].m_col.is_instant());
+ ut_ad(!table->v_cols[pos].m_col.is_added());
+ ut_ad(!table->v_cols[pos].m_col.is_dropped());
return &table->v_cols[pos];
}
@@ -501,19 +426,6 @@ dict_table_get_sys_col_no(
return unsigned(table->n_cols) + (sys - DATA_N_SYS_COLS);
}
-/********************************************************************//**
-Check whether the table uses the compact page format.
-@return TRUE if table uses the compact page format */
-UNIV_INLINE
-bool
-dict_table_is_comp(
-/*===============*/
- const dict_table_t* table) /*!< in: table */
-{
- ut_ad(table);
- return (table->flags & DICT_TF_COMPACT) != 0;
-}
-
/************************************************************************
Check if the table has an FTS index. */
UNIV_INLINE
@@ -720,20 +632,34 @@ dict_tf_to_fsp_flags(ulint table_flags)
DBUG_EXECUTE_IF("dict_tf_to_fsp_flags_failure",
return(ULINT_UNDEFINED););
- /* Adjust bit zero. */
- fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0;
+ /* No ROW_FORMAT=COMPRESSED for innodb_checksum_algorithm=full_crc32 */
+ if ((srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32
+ || srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_FULL_CRC32)
+ && !(table_flags & DICT_TF_MASK_ZIP_SSIZE)) {
+
+ fsp_flags = 1U << FSP_FLAGS_FCRC32_POS_MARKER
+ | FSP_FLAGS_FCRC32_PAGE_SSIZE();
+
+ if (page_compression_level) {
+ fsp_flags |= innodb_compression_algorithm
+ << FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO;
+ }
+ } else {
+ /* Adjust bit zero. */
+ fsp_flags = DICT_TF_HAS_ATOMIC_BLOBS(table_flags) ? 1 : 0;
- /* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */
- fsp_flags |= table_flags
- & (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS);
+ /* ZIP_SSIZE and ATOMIC_BLOBS are at the same position. */
+ fsp_flags |= table_flags
+ & (DICT_TF_MASK_ZIP_SSIZE | DICT_TF_MASK_ATOMIC_BLOBS);
- fsp_flags |= FSP_FLAGS_PAGE_SSIZE();
+ fsp_flags |= FSP_FLAGS_PAGE_SSIZE();
- if (page_compression_level) {
- fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION;
+ if (page_compression_level) {
+ fsp_flags |= FSP_FLAGS_MASK_PAGE_COMPRESSION;
+ }
}
- ut_a(fsp_flags_is_valid(fsp_flags, false));
+ ut_a(fil_space_t::is_valid_flags(fsp_flags, false));
if (DICT_TF_HAS_DATA_DIR(table_flags)) {
fsp_flags |= 1U << FSP_FLAGS_MEM_DATA_DIR;
@@ -779,50 +705,6 @@ dict_tf_to_sys_tables_type(
return(type);
}
-/** Extract the page size info from table flags.
-@param[in] flags flags
-@return a structure containing the compressed and uncompressed
-page sizes and a boolean indicating if the page is compressed. */
-UNIV_INLINE
-const page_size_t
-dict_tf_get_page_size(
- ulint flags)
-{
- const ulint zip_ssize = DICT_TF_GET_ZIP_SSIZE(flags);
-
- if (zip_ssize == 0) {
- return(univ_page_size);
- }
-
- const ulint zip_size = (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize;
-
- ut_ad(zip_size <= UNIV_ZIP_SIZE_MAX);
-
- return(page_size_t(zip_size, srv_page_size, true));
-}
-
-/*********************************************************************//**
-Obtain exclusive locks on all index trees of the table. This is to prevent
-accessing index trees while InnoDB is updating internal metadata for
-operations such as truncate tables. */
-UNIV_INLINE
-void
-dict_table_x_lock_indexes(
-/*======================*/
- dict_table_t* table) /*!< in: table */
-{
- dict_index_t* index;
-
- ut_ad(mutex_own(&dict_sys->mutex));
-
- /* Loop through each index of the table and lock them */
- for (index = dict_table_get_first_index(table);
- index != NULL;
- index = dict_table_get_next_index(index)) {
- rw_lock_x_lock(dict_index_get_lock(index));
- }
-}
-
/*********************************************************************//**
Returns true if the particular FTS index in the table is still syncing
in the background, false otherwise.
@@ -844,24 +726,6 @@ dict_fts_index_syncing(
}
return(false);
}
-/*********************************************************************//**
-Release the exclusive locks on all index tree. */
-UNIV_INLINE
-void
-dict_table_x_unlock_indexes(
-/*========================*/
- dict_table_t* table) /*!< in: table */
-{
- dict_index_t* index;
-
- ut_ad(mutex_own(&dict_sys->mutex));
-
- for (index = dict_table_get_first_index(table);
- index != NULL;
- index = dict_table_get_next_index(index)) {
- rw_lock_x_unlock(dict_index_get_lock(index));
- }
-}
/********************************************************************//**
Gets the number of fields in the internal representation of an index,
@@ -979,30 +843,6 @@ dict_index_get_nth_field(
}
#endif /* UNIV_DEBUG */
-/********************************************************************//**
-Returns the position of a system column in an index.
-@return position, ULINT_UNDEFINED if not contained */
-UNIV_INLINE
-ulint
-dict_index_get_sys_col_pos(
-/*=======================*/
- const dict_index_t* index, /*!< in: index */
- ulint type) /*!< in: DATA_ROW_ID, ... */
-{
- ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
- ut_ad(!dict_index_is_ibuf(index));
-
- if (dict_index_is_clust(index)) {
-
- return(dict_col_get_clust_pos(
- dict_table_get_sys_col(index->table, type),
- index));
- }
-
- return(dict_index_get_nth_col_pos(
- index, dict_table_get_sys_col_no(index->table, type), NULL));
-}
-
/*********************************************************************//**
Gets the field column.
@return field->col, pointer to the table column */
@@ -1233,9 +1073,7 @@ dict_table_is_fts_column(
index = (dict_index_t*) ib_vector_getp(indexes, i);
- if (dict_index_contains_col_or_prefix(
- index, col_no, is_virtual)) {
-
+ if (index->contains_col_or_prefix(col_no, is_virtual)) {
return(i);
}
}
@@ -1300,21 +1138,6 @@ dict_max_v_field_len_store_undo(
return(max_log_len);
}
-/**********************************************************************//**
-Prevent table eviction by moving a table to the non-LRU list from the
-LRU list if it is not already there. */
-UNIV_INLINE
-void
-dict_table_prevent_eviction(
-/*========================*/
- dict_table_t* table) /*!< in: table to prevent eviction */
-{
- ut_ad(mutex_own(&dict_sys->mutex));
- if (table->can_be_evicted) {
- dict_table_move_from_lru_to_non_lru(table);
- }
-}
-
/********************************************************************//**
Check whether the table is corrupted.
@return nonzero for corrupted table, zero for valid tables */
@@ -1358,8 +1181,8 @@ inline
void
dict_table_t::acquire()
{
- ut_ad(mutex_own(&dict_sys->mutex));
- my_atomic_add32_explicit(&n_ref_count, 1, MY_MEMORY_ORDER_RELAXED);
+ ut_ad(mutex_own(&dict_sys.mutex));
+ n_ref_count++;
}
/** Release the table handle.
@@ -1368,8 +1191,7 @@ inline
bool
dict_table_t::release()
{
- int32 n = my_atomic_add32_explicit(
- &n_ref_count, -1, MY_MEMORY_ORDER_RELAXED);
+ auto n = n_ref_count--;
ut_ad(n > 0);
return n == 1;
}
diff --git a/storage/innobase/include/dict0load.h b/storage/innobase/include/dict0load.h
index aa3de6d0b17..afc017fd9d1 100644
--- a/storage/innobase/include/dict0load.h
+++ b/storage/innobase/include/dict0load.h
@@ -82,7 +82,7 @@ dict_get_first_table_name_in_db(
/** Make sure the data_file_name is saved in dict_table_t if needed.
Try to read it from the fil_system first, then from SYS_DATAFILES.
@param[in] table Table object
-@param[in] dict_mutex_own true if dict_sys->mutex is owned already */
+@param[in] dict_mutex_own true if dict_sys.mutex is owned already */
void
dict_get_and_save_data_dir_path(
dict_table_t* table,
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 1a22470569e..31f10f6f9a9 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -2,7 +2,7 @@
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2019, MariaDB Corporation.
+Copyright (c) 2013, 2020, 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
@@ -44,9 +44,9 @@ Created 1/8/1996 Heikki Tuuri
#include "fts0fts.h"
#include "buf0buf.h"
#include "gis0type.h"
-#include "os0once.h"
#include "fil0fil.h"
#include "fil0crypt.h"
+#include <sql_const.h>
#include <set>
#include <algorithm>
#include <iterator>
@@ -573,6 +573,10 @@ struct dict_col_t{
this column. Our current max limit is
3072 (REC_VERSION_56_MAX_INDEX_COL_LEN)
bytes. */
+private:
+ /** Special value of ind for a dropped column */
+ static const unsigned DROPPED = 1023;
+public:
/** Detach the column from an index.
@param[in] index index to be detached from */
@@ -602,7 +606,8 @@ struct dict_col_t{
ut_ad(mtype == DATA_INT || mtype == DATA_FIXBINARY);
return mtype == DATA_INT;
}
- /** @return whether this is system versioned */
+ /** @return whether this user column (not row_start, row_end)
+ has System Versioning property */
bool is_versioned() const { return !(~prtype & DATA_VERSIONED); }
/** @return whether this is the system version start */
bool vers_sys_start() const
@@ -616,29 +621,121 @@ struct dict_col_t{
}
/** @return whether this is an instantly-added column */
- bool is_instant() const
+ bool is_added() const
{
DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data);
return def_val.len != UNIV_SQL_DEFAULT;
}
+ /** Flag the column instantly dropped */
+ void set_dropped() { ind = DROPPED; }
+ /** Flag the column instantly dropped.
+ @param[in] not_null whether the column was NOT NULL
+ @param[in] len2 whether the length exceeds 255 bytes
+ @param[in] fixed_len the fixed length in bytes, or 0 */
+ void set_dropped(bool not_null, bool len2, unsigned fixed)
+ {
+ DBUG_ASSERT(!len2 || !fixed);
+ prtype = not_null
+ ? DATA_NOT_NULL | DATA_BINARY_TYPE
+ : DATA_BINARY_TYPE;
+ if (fixed) {
+ mtype = DATA_FIXBINARY;
+ len = fixed;
+ } else {
+ mtype = DATA_BINARY;
+ len = len2 ? 65535 : 255;
+ }
+ mbminlen = mbmaxlen = 0;
+ ind = DROPPED;
+ ord_part = 0;
+ max_prefix = 0;
+ }
+ /** @return whether the column was instantly dropped */
+ bool is_dropped() const { return ind == DROPPED; }
+ /** @return whether the column was instantly dropped
+ @param[in] index the clustered index */
+ inline bool is_dropped(const dict_index_t& index) const;
+
/** Get the default value of an instantly-added column.
@param[out] len value length (in bytes), or UNIV_SQL_NULL
@return default value
@retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */
const byte* instant_value(ulint* len) const
{
- DBUG_ASSERT(is_instant());
+ DBUG_ASSERT(is_added());
*len = def_val.len;
return static_cast<const byte*>(def_val.data);
}
/** Remove the 'instant ADD' status of the column */
- void remove_instant()
+ void clear_instant()
{
- DBUG_ASSERT(is_instant());
def_val.len = UNIV_SQL_DEFAULT;
def_val.data = NULL;
}
+
+ /** @return whether two columns have compatible data type encoding */
+ bool same_type(const dict_col_t &other) const
+ {
+ if (mtype != other.mtype)
+ {
+ /* For latin1_swedish_ci, DATA_CHAR and DATA_VARCHAR
+ will be used instead of DATA_MYSQL and DATA_VARMYSQL.
+ As long as mtype,prtype are being written to InnoDB
+ data dictionary tables, we cannot simplify this. */
+ switch (mtype) {
+ default:
+ return false;
+ case DATA_VARCHAR:
+ if (other.mtype != DATA_VARMYSQL)
+ return false;
+ goto check_encoding;
+ case DATA_VARMYSQL:
+ if (other.mtype != DATA_VARCHAR)
+ return false;
+ goto check_encoding;
+ case DATA_CHAR:
+ if (other.mtype != DATA_MYSQL)
+ return false;
+ goto check_encoding;
+ case DATA_MYSQL:
+ if (other.mtype != DATA_CHAR)
+ return false;
+ goto check_encoding;
+ }
+ }
+ else if (dtype_is_string_type(mtype))
+ {
+ check_encoding:
+ const uint16_t cset= dtype_get_charset_coll(prtype);
+ const uint16_t ocset= dtype_get_charset_coll(other.prtype);
+ return cset == ocset || dict_col_t::same_encoding(cset, ocset);
+ }
+
+ return true;
+ }
+
+ /** @return whether two collations codes have the same character encoding */
+ static bool same_encoding(uint16_t a, uint16_t b);
+
+ /** Determine if the columns have the same format
+ except for is_nullable() and is_versioned().
+ @param[in] other column to compare to
+ @return whether the columns have the same format */
+ bool same_format(const dict_col_t& other) const
+ {
+ return same_type(other)
+ && len >= other.len
+ && mbminlen == other.mbminlen
+ && mbmaxlen == other.mbmaxlen
+ && !((prtype ^ other.prtype)
+ & ~(DATA_NOT_NULL | DATA_VERSIONED
+ | CHAR_COLL_MASK << 16
+ | DATA_LONG_TRUE_VARCHAR));
+ }
+
+ /** @return whether the column values are comparable by memcmp() */
+ inline bool is_binary() const { return prtype & DATA_BINARY_TYPE; }
};
/** Index information put in a list of virtual column structure. Index
@@ -655,9 +752,6 @@ struct dict_v_idx_t {
: index(index), nth_field(nth_field) {}
};
-/** Index list to put in dict_v_col_t */
-typedef std::list<dict_v_idx_t, ut_allocator<dict_v_idx_t> > dict_v_idx_list;
-
/** Data structure for a virtual column in a table */
struct dict_v_col_t{
/** column structure */
@@ -667,15 +761,39 @@ struct dict_v_col_t{
dict_col_t** base_col;
/** number of base column */
- ulint num_base;
+ unsigned num_base:10;
/** column pos in table */
- ulint v_pos;
+ unsigned v_pos:10;
- /** Virtual index list, and column position in the index,
- the allocated memory is not from table->heap */
- dict_v_idx_list* v_indexes;
+ /** number of indexes */
+ unsigned n_v_indexes:12;
+ /** Virtual index list, and column position in the index */
+ std::forward_list<dict_v_idx_t, ut_allocator<dict_v_idx_t> >
+ v_indexes;
+
+ /** Detach the column from an index.
+ @param[in] index index to be detached from */
+ void detach(const dict_index_t& index)
+ {
+ if (!n_v_indexes) return;
+ auto i = v_indexes.before_begin();
+ ut_d(unsigned n = 0);
+ do {
+ auto prev = i++;
+ if (i == v_indexes.end()) {
+ ut_ad(n == n_v_indexes);
+ return;
+ }
+ ut_ad(++n <= n_v_indexes);
+ if (i->index == &index) {
+ v_indexes.erase_after(prev);
+ n_v_indexes--;
+ return;
+ }
+ } while (i != v_indexes.end());
+ }
};
/** Data structure for newly added virtual column in a table */
@@ -703,7 +821,8 @@ struct dict_s_col_t {
};
/** list to put stored column for create_table_info_t */
-typedef std::list<dict_s_col_t, ut_allocator<dict_s_col_t> > dict_s_col_list;
+typedef std::forward_list<dict_s_col_t, ut_allocator<dict_s_col_t> >
+dict_s_col_list;
/** @brief DICT_ANTELOPE_MAX_INDEX_COL_LEN is measured in bytes and
is the maximum indexed column length (or indexed prefix length) in
@@ -811,17 +930,15 @@ extern ulong zip_pad_max;
an uncompressed page should be left as padding to avoid compression
failures. This estimate is based on a self-adapting heuristic. */
struct zip_pad_info_t {
- SysMutex* mutex; /*!< mutex protecting the info */
- ulint pad; /*!< number of bytes used as pad */
+ SysMutex mutex; /*!< mutex protecting the info */
+ Atomic_counter<ulint>
+ pad; /*!< number of bytes used as pad */
ulint success;/*!< successful compression ops during
current round */
ulint failure;/*!< failed compression ops during
current round */
ulint n_rounds;/*!< number of currently successful
rounds */
- volatile os_once::state_t
- mutex_created;
- /*!< Creation state of mutex member */
};
/** Number of samples of data size kept when page compression fails for
@@ -834,7 +951,7 @@ const char innobase_index_reserve_name[] = "GEN_CLUST_INDEX";
/** Data structure for an index. Most fields will be
initialized to 0, NULL or FALSE in dict_mem_index_create(). */
-struct dict_index_t{
+struct dict_index_t {
index_id_t id; /*!< id of the index */
mem_heap_t* heap; /*!< memory heap */
id_name_t name; /*!< index name */
@@ -893,13 +1010,13 @@ struct dict_index_t{
dictionary cache */
unsigned to_be_dropped:1;
/*!< TRUE if the index is to be dropped;
- protected by dict_operation_lock */
+ protected by dict_sys.latch */
unsigned online_status:2;
/*!< enum online_index_status.
Transitions from ONLINE_INDEX_COMPLETE (to
ONLINE_INDEX_CREATION) are protected
- by dict_operation_lock and
- dict_sys->mutex. Other changes are
+ by dict_sys.latch and
+ dict_sys.mutex. Other changes are
protected by index->lock. */
unsigned uncommitted:1;
/*!< a flag that is set for secondary indexes
@@ -909,6 +1026,8 @@ struct dict_index_t{
#ifdef UNIV_DEBUG
/** whether this is a dummy index object */
bool is_dummy;
+ /** whether btr_cur_instant_init() is in progress */
+ bool in_instant_init;
uint32_t magic_n;/*!< magic number */
/** Value of dict_index_t::magic_n */
# define DICT_INDEX_MAGIC_N 76789786
@@ -1023,7 +1142,7 @@ struct dict_index_t{
page cannot be read or decrypted */
inline bool is_readable() const;
- /** @return whether instant ADD COLUMN is in effect */
+ /** @return whether instant ALTER TABLE is in effect */
inline bool is_instant() const;
/** @return whether the index is the primary key index
@@ -1033,12 +1152,38 @@ struct dict_index_t{
return DICT_CLUSTERED == (type & (DICT_CLUSTERED | DICT_IBUF));
}
+ /** @return whether this is a generated clustered index */
+ bool is_gen_clust() const { return type == DICT_CLUSTERED; }
+
+ /** @return whether this is a clustered index */
+ bool is_clust() const { return type & DICT_CLUSTERED; }
+
+ /** @return whether this is a unique index */
+ bool is_unique() const { return type & DICT_UNIQUE; }
+
/** @return whether this is a spatial index */
bool is_spatial() const { return UNIV_UNLIKELY(type & DICT_SPATIAL); }
+ /** @return whether this is the change buffer */
+ bool is_ibuf() const { return UNIV_UNLIKELY(type & DICT_IBUF); }
+
/** @return whether the index includes virtual columns */
bool has_virtual() const { return type & DICT_VIRTUAL; }
+ /** @return the position of DB_TRX_ID */
+ unsigned db_trx_id() const {
+ DBUG_ASSERT(is_primary());
+ DBUG_ASSERT(n_uniq);
+ DBUG_ASSERT(n_uniq <= MAX_REF_PARTS);
+ return n_uniq;
+ }
+ /** @return the position of DB_ROLL_PTR */
+ unsigned db_roll_ptr() const { return db_trx_id() + 1; }
+
+ /** @return the offset of the metadata BLOB field,
+ or the first user field after the PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR */
+ unsigned first_user_field() const { return db_trx_id() + 2; }
+
/** @return whether the index is corrupted */
inline bool is_corrupted() const;
@@ -1084,24 +1229,20 @@ struct dict_index_t{
return fields[n].col->instant_value(len);
}
- /** Adjust clustered index metadata for instant ADD COLUMN.
- @param[in] clustered index definition after instant ADD COLUMN */
- void instant_add_field(const dict_index_t& instant);
-
- /** Remove the 'instant ADD' status of a clustered index.
- Protected by index root page x-latch or table X-lock. */
- void remove_instant()
- {
- DBUG_ASSERT(is_primary());
- if (!is_instant()) {
- return;
- }
- for (unsigned i = n_core_fields; i < n_fields; i++) {
- fields[i].col->remove_instant();
- }
- n_core_fields = n_fields;
- n_core_null_bytes = UT_BITS_IN_BYTES(unsigned(n_nullable));
- }
+ /** Adjust index metadata for instant ADD/DROP/reorder COLUMN.
+ @param[in] clustered index definition after instant ALTER TABLE */
+ inline void instant_add_field(const dict_index_t& instant);
+ /** Remove instant ADD COLUMN metadata. */
+ inline void clear_instant_add();
+ /** Remove instant ALTER TABLE metadata. */
+ inline void clear_instant_alter();
+
+ /** Construct the metadata record for instant ALTER TABLE.
+ @param[in] row dummy or default values for existing columns
+ @param[in,out] heap memory heap for allocations
+ @return metadata record */
+ inline dtuple_t*
+ instant_metadata(const dtuple_t& row, mem_heap_t* heap) const;
/** Check if record in clustered index is historical row.
@param[in] rec clustered row
@@ -1117,6 +1258,16 @@ struct dict_index_t{
bool
vers_history_row(const rec_t* rec, bool &history_row);
+ /** Reconstruct the clustered index fields. */
+ inline void reconstruct_fields();
+
+ /** Check if the index contains a column or a prefix of that column.
+ @param[in] n column number
+ @param[in] is_virtual whether it is a virtual col
+ @return whether the index contains the column or its prefix */
+ bool contains_col_or_prefix(ulint n, bool is_virtual) const
+ MY_ATTRIBUTE((warn_unused_result));
+
/** This ad-hoc class is used by record_size_info only. */
class record_size_info_t {
public:
@@ -1182,19 +1333,8 @@ struct dict_index_t{
@param[in] index index to be detached from */
inline void dict_col_t::detach(const dict_index_t& index)
{
- if (!is_virtual()) {
- return;
- }
-
- if (dict_v_idx_list* v_indexes = reinterpret_cast<const dict_v_col_t*>
- (this)->v_indexes) {
- for (dict_v_idx_list::iterator i = v_indexes->begin();
- i != v_indexes->end(); i++) {
- if (i->index == &index) {
- v_indexes->erase(i);
- return;
- }
- }
+ if (is_virtual()) {
+ reinterpret_cast<dict_v_col_t*>(this)->detach(index);
}
}
@@ -1510,6 +1650,64 @@ struct dict_vcol_templ_t {
dict_vcol_templ_t() : vtempl(0), mysql_table_query_id(~0ULL) {}
};
+/** Metadata on clustered index fields starting from first_user_field() */
+class field_map_element_t
+{
+ /** Number of bits for representing a column number */
+ static constexpr uint16_t IND_BITS = 10;
+
+ /** Set if the column of the field has been instantly dropped */
+ static constexpr uint16_t DROPPED = 1U << (IND_BITS + 5);
+
+ /** Set if the column was dropped and originally declared NOT NULL */
+ static constexpr uint16_t NOT_NULL = 1U << (IND_BITS + 4);
+
+ /** Column index (if !(data & DROPPED)): table->cols[data & IND],
+ or field length (if (data & DROPPED)):
+ (data & IND) = 0 if variable-length with max_len < 256 bytes;
+ (data & IND) = 1 if variable-length with max_len > 255 bytes;
+ (data & IND) = 1 + L otherwise, with L=fixed length of the column */
+ static constexpr uint16_t IND = (1U << IND_BITS) - 1;
+
+ /** Field metadata */
+ uint16_t data;
+
+ void clear_not_null() { data &= ~NOT_NULL; }
+public:
+ bool is_dropped() const { return data & DROPPED; }
+ void set_dropped() { data |= DROPPED; }
+ bool is_not_null() const { return data & NOT_NULL; }
+ void set_not_null() { ut_ad(is_dropped()); data |= NOT_NULL; }
+ uint16_t ind() const { return data & IND; }
+ void set_ind(uint16_t i)
+ {
+ DBUG_ASSERT(i <= IND);
+ DBUG_ASSERT(!ind());
+ data |= i;
+ }
+ field_map_element_t& operator= (uint16_t value)
+ {
+ data = value;
+ return *this;
+ }
+ operator uint16_t() { return data; }
+};
+
+static_assert(sizeof(field_map_element_t) == 2,
+ "Size mismatch for a persistent data item!");
+
+/** Instantly dropped or reordered columns */
+struct dict_instant_t
+{
+ /** Number of dropped columns */
+ unsigned n_dropped;
+ /** Dropped columns */
+ dict_col_t* dropped;
+ /** Map of clustered index non-PK fields[i - first_user_field()]
+ to table columns */
+ field_map_element_t* field_map;
+};
+
/** These are used when MySQL FRM and InnoDB data dictionary are
in inconsistent state. */
typedef enum {
@@ -1528,11 +1726,7 @@ struct dict_table_t {
/** Get reference count.
@return current value of n_ref_count */
- inline int32 get_ref_count()
- {
- return my_atomic_load32_explicit(&n_ref_count,
- MY_MEMORY_ORDER_RELAXED);
- }
+ inline uint32_t get_ref_count() const { return n_ref_count; }
/** Acquire the table handle. */
inline void acquire();
@@ -1552,6 +1746,9 @@ struct dict_table_t {
return flags2 & DICT_TF2_TEMPORARY;
}
+ /** @return whether the table is not in ROW_FORMAT=REDUNDANT */
+ bool not_redundant() const { return flags & DICT_TF_COMPACT; }
+
/** @return whether this table is readable
@retval true normally
@retval false if this is a single-table tablespace
@@ -1570,35 +1767,92 @@ struct dict_table_t {
return strstr(name, "/" TEMP_FILE_PREFIX) != NULL;
}
- /** @return whether instant ADD COLUMN is in effect */
+ /** @return whether instant ALTER TABLE is in effect */
bool is_instant() const
{
return(UT_LIST_GET_FIRST(indexes)->is_instant());
}
- /** @return whether the table supports instant ADD COLUMN */
+ /** @return whether the table supports instant ALTER TABLE */
bool supports_instant() const
{
return(!(flags & DICT_TF_MASK_ZIP_SSIZE));
}
- /** Adjust metadata for instant ADD COLUMN.
- @param[in] table table definition after instant ADD COLUMN */
- void instant_add_column(const dict_table_t& table);
+ /** @return the number of instantly dropped columns */
+ unsigned n_dropped() const { return instant ? instant->n_dropped : 0; }
+
+ /** Look up an old column.
+ @param[in] cols the old columns of the table
+ @param[in] col_map map from old table columns to altered ones
+ @param[in] n_cols number of old columns
+ @param[in] i the number of the new column
+ @return old column
+ @retval NULL if column i was added to the table */
+ static const dict_col_t* find(const dict_col_t* cols,
+ const ulint* col_map, ulint n_cols,
+ ulint i)
+ {
+ for (ulint o = n_cols; o--; ) {
+ if (col_map[o] == i) {
+ return &cols[o];
+ }
+ }
+ return NULL;
+ }
- /** Roll back instant_add_column().
- @param[in] old_n_cols original n_cols
- @param[in] old_cols original cols
- @param[in] old_col_names original col_names */
- void rollback_instant(
+ /** Serialise metadata of dropped or reordered columns.
+ @param[in,out] heap memory heap for allocation
+ @param[out] field data field with the metadata */
+ inline void serialise_columns(mem_heap_t* heap, dfield_t* field) const;
+
+ /** Reconstruct dropped or reordered columns.
+ @param[in] metadata data from serialise_columns()
+ @param[in] len length of the metadata, in bytes
+ @return whether parsing the metadata failed */
+ bool deserialise_columns(const byte* metadata, ulint len);
+
+ /** Set is_instant() before instant_column().
+ @param[in] old previous table definition
+ @param[in] col_map map from old.cols[]
+ and old.v_cols[] to this
+ @param[out] first_alter_pos 0, or
+ 1 + first changed column position */
+ inline void prepare_instant(const dict_table_t& old,
+ const ulint* col_map,
+ unsigned& first_alter_pos);
+
+ /** Adjust table metadata for instant ADD/DROP/reorder COLUMN.
+ @param[in] table table on which prepare_instant() was invoked
+ @param[in] col_map mapping from cols[] and v_cols[] to table
+ @return whether the metadata record must be updated */
+ inline bool instant_column(const dict_table_t& table,
+ const ulint* col_map);
+
+ /** Roll back instant_column().
+ @param[in] old_n_cols original n_cols
+ @param[in] old_cols original cols
+ @param[in] old_col_names original col_names
+ @param[in] old_instant original instant structure
+ @param[in] old_fields original fields
+ @param[in] old_n_fields original number of fields
+ @param[in] old_n_core_fields original number of core fields
+ @param[in] old_n_v_cols original n_v_cols
+ @param[in] old_v_cols original v_cols
+ @param[in] old_v_col_names original v_col_names
+ @param[in] col_map column map */
+ inline void rollback_instant(
unsigned old_n_cols,
dict_col_t* old_cols,
- const char* old_col_names);
-
- /** Trim the instantly added columns when an insert into SYS_COLUMNS
- is rolled back during ALTER TABLE or recovery.
- @param[in] n number of surviving non-system columns */
- void rollback_instant(unsigned n);
+ const char* old_col_names,
+ dict_instant_t* old_instant,
+ dict_field_t* old_fields,
+ unsigned old_n_fields,
+ unsigned old_n_core_fields,
+ unsigned old_n_v_cols,
+ dict_v_col_t* old_v_cols,
+ const char* old_v_col_names,
+ const ulint* col_map);
/** Add the table definition to the data dictionary cache */
void add_to_cache();
@@ -1616,23 +1870,28 @@ struct dict_table_t {
void inc_fk_checks()
{
#ifdef UNIV_DEBUG
- lint fk_checks= (lint)
+ int32_t fk_checks=
#endif
- my_atomic_addlint(&n_foreign_key_checks_running, 1);
+ n_foreign_key_checks_running++;
ut_ad(fk_checks >= 0);
}
void dec_fk_checks()
{
#ifdef UNIV_DEBUG
- lint fk_checks= (lint)
+ int32_t fk_checks=
#endif
- my_atomic_addlint(&n_foreign_key_checks_running, ulint(-1));
+ n_foreign_key_checks_running--;
ut_ad(fk_checks > 0);
}
/** For overflow fields returns potential max length stored inline */
- size_t get_overflow_field_local_len() const;
+ inline size_t get_overflow_field_local_len() const;
+private:
+ /** Initialize instant->field_map.
+ @param[in] table table definition to copy from */
+ inline void init_instant(const dict_table_t& table);
+public:
/** Id of the table. */
table_id_t id;
/** Hash chain node. */
@@ -1691,8 +1950,7 @@ struct dict_table_t {
/** TRUE if the table is to be dropped, but not yet actually dropped
(could in the background drop list). It is turned on at the beginning
of row_drop_table_for_mysql() and turned off just before we start to
- update system tables for the drop. It is protected by
- dict_operation_lock. */
+ update system tables for the drop. It is protected by dict_sys.latch. */
unsigned to_be_dropped:1;
/** Number of non-virtual columns defined so far. */
@@ -1742,6 +2000,9 @@ struct dict_table_t {
reason s_cols is a part of dict_table_t */
dict_s_col_list* s_cols;
+ /** Instantly dropped or reordered columns, or NULL if none */
+ dict_instant_t* instant;
+
/** Column names packed in a character string
"name1\0name2\0...nameN\0". Until the string contains n_cols, it will
be allocated from a temporary heap. The final string will be allocated
@@ -1786,7 +2047,7 @@ struct dict_table_t {
/** Count of how many foreign key check operations are currently being
performed on the table. We cannot drop the table while there are
foreign key checks running on it. */
- ulint n_foreign_key_checks_running;
+ Atomic_counter<int32_t> n_foreign_key_checks_running;
/** Transactions whose view low limit is greater than this number are
not allowed to store to the MySQL query cache or retrieve from it.
@@ -1808,9 +2069,6 @@ struct dict_table_t {
/** Statistics for query optimization. @{ */
- /** Creation state of 'stats_latch'. */
- volatile os_once::state_t stats_latch_created;
-
/** This latch protects:
dict_table_t::stat_initialized,
dict_table_t::stat_n_rows (*),
@@ -1822,7 +2080,7 @@ struct dict_table_t {
dict_table_t::indexes*::stat_n_leaf_pages.
(*) Those are not always protected for
performance reasons. */
- rw_lock_t* stats_latch;
+ rw_lock_t stats_latch;
/** TRUE if statistics have been calculated the first time after
database startup or table creation. */
@@ -1904,7 +2162,7 @@ struct dict_table_t {
/** The state of the background stats thread wrt this table.
See BG_STAT_NONE, BG_STAT_IN_PROGRESS and BG_STAT_SHOULD_QUIT.
- Writes are covered by dict_sys->mutex. Dirty reads are possible. */
+ Writes are covered by dict_sys.mutex. Dirty reads are possible. */
#define BG_SCRUB_IN_PROGRESS ((byte)(1 << 2))
/*!< BG_SCRUB_IN_PROGRESS is set in
@@ -1920,7 +2178,7 @@ struct dict_table_t {
/** The state of the background stats thread wrt this table.
See BG_STAT_NONE, BG_STAT_IN_PROGRESS and BG_STAT_SHOULD_QUIT.
- Writes are covered by dict_sys->mutex. Dirty reads are possible. */
+ Writes are covered by dict_sys.mutex. Dirty reads are possible. */
byte stats_bg_flag;
bool stats_error_printed;
@@ -1946,11 +2204,8 @@ struct dict_table_t {
from a select. */
lock_t* autoinc_lock;
- /** Creation state of autoinc_mutex member */
- volatile os_once::state_t autoinc_mutex_created;
-
/** Mutex protecting the autoincrement counter. */
- ib_mutex_t* autoinc_mutex;
+ ib_mutex_t autoinc_mutex;
/** Autoinc counter value to give to the next inserted row. */
ib_uint64_t autoinc;
@@ -1986,7 +2241,7 @@ private:
/** Count of how many handles are opened to this table. Dropping of the
table is NOT allowed until this count gets to zero. MySQL does NOT
itself check the number of open handles at DROP. */
- int32 n_ref_count;
+ Atomic_counter<uint32_t> n_ref_count;
public:
/** List of locks on the table. Protected by lock_sys.mutex. */
@@ -2022,12 +2277,15 @@ inline bool dict_index_t::is_readable() const { return table->is_readable(); }
inline bool dict_index_t::is_instant() const
{
ut_ad(n_core_fields > 0);
- ut_ad(n_core_fields <= n_fields);
+ ut_ad(n_core_fields <= n_fields || table->n_dropped());
ut_ad(n_core_fields == n_fields
|| (type & ~(DICT_UNIQUE | DICT_CORRUPT)) == DICT_CLUSTERED);
ut_ad(n_core_fields == n_fields || table->supports_instant());
ut_ad(n_core_fields == n_fields || !table->is_temporary());
- return(n_core_fields != n_fields);
+ ut_ad(!table->instant || !table->is_temporary());
+
+ return n_core_fields != n_fields
+ || (is_primary() && table->instant);
}
inline bool dict_index_t::is_corrupted() const
@@ -2037,6 +2295,81 @@ inline bool dict_index_t::is_corrupted() const
|| (table && table->corrupted));
}
+inline void dict_index_t::clear_instant_add()
+{
+ DBUG_ASSERT(is_primary());
+ DBUG_ASSERT(is_instant());
+ DBUG_ASSERT(!table->instant);
+ for (unsigned i = n_core_fields; i < n_fields; i++) {
+ fields[i].col->clear_instant();
+ }
+ n_core_fields = n_fields;
+ n_core_null_bytes = UT_BITS_IN_BYTES(unsigned(n_nullable));
+}
+
+inline void dict_index_t::clear_instant_alter()
+{
+ DBUG_ASSERT(is_primary());
+ DBUG_ASSERT(n_fields == n_def);
+
+ if (!table->instant) {
+ if (is_instant()) {
+ clear_instant_add();
+ }
+ return;
+ }
+
+#ifndef DBUG_OFF
+ for (unsigned i = first_user_field(); i--; ) {
+ DBUG_ASSERT(!fields[i].col->is_dropped());
+ DBUG_ASSERT(!fields[i].col->is_nullable());
+ }
+#endif
+ const dict_col_t* ai_col = table->persistent_autoinc
+ ? fields[table->persistent_autoinc - 1].col
+ : NULL;
+ dict_field_t* const begin = &fields[first_user_field()];
+ dict_field_t* end = &fields[n_fields];
+
+ for (dict_field_t* d = begin; d < end; ) {
+ /* Move fields for dropped columns to the end. */
+ if (!d->col->is_dropped()) {
+ d++;
+ } else {
+ if (d->col->is_nullable()) {
+ n_nullable--;
+ }
+
+ std::swap(*d, *--end);
+ }
+ }
+
+ DBUG_ASSERT(&fields[n_fields - table->n_dropped()] == end);
+ n_core_fields = n_fields = n_def = end - fields;
+ n_core_null_bytes = UT_BITS_IN_BYTES(n_nullable);
+ std::sort(begin, end, [](const dict_field_t& a, const dict_field_t& b)
+ { return a.col->ind < b.col->ind; });
+ table->instant = NULL;
+ if (ai_col) {
+ auto a = std::find_if(begin, end,
+ [ai_col](const dict_field_t& f)
+ { return f.col == ai_col; });
+ table->persistent_autoinc = (a == end) ? 0 : 1 + (a - fields);
+ }
+}
+
+/** @return whether the column was instantly dropped
+@param[in] index the clustered index */
+inline bool dict_col_t::is_dropped(const dict_index_t& index) const
+{
+ DBUG_ASSERT(index.is_primary());
+ DBUG_ASSERT(!is_dropped() == !index.table->instant);
+ DBUG_ASSERT(!is_dropped() || (this >= index.table->instant->dropped
+ && this < index.table->instant->dropped
+ + index.table->instant->n_dropped));
+ return is_dropped();
+}
+
/*******************************************************************//**
Initialise the table lock list. */
void
@@ -2057,87 +2390,6 @@ struct dict_foreign_add_to_referenced_table {
}
};
-/** Destroy the autoinc latch of the given table.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose stats latch to destroy */
-inline
-void
-dict_table_autoinc_destroy(
- dict_table_t* table)
-{
- if (table->autoinc_mutex_created == os_once::DONE
- && table->autoinc_mutex != NULL) {
- mutex_free(table->autoinc_mutex);
- UT_DELETE(table->autoinc_mutex);
- }
-}
-
-/** Request for lazy creation of the autoinc latch of a given table.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose autoinc latch is to be created. */
-inline
-void
-dict_table_autoinc_create_lazy(
- dict_table_t* table)
-{
- table->autoinc_mutex = NULL;
- table->autoinc_mutex_created = os_once::NEVER_DONE;
-}
-
-/** Request a lazy creation of dict_index_t::zip_pad::mutex.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] index index whose zip_pad mutex is to be created */
-inline
-void
-dict_index_zip_pad_mutex_create_lazy(
- dict_index_t* index)
-{
- index->zip_pad.mutex = NULL;
- index->zip_pad.mutex_created = os_once::NEVER_DONE;
-}
-
-/** Destroy the zip_pad_mutex of the given index.
-This function is only called from either single threaded environment
-or from a thread that has not shared the table object with other threads.
-@param[in,out] table table whose stats latch to destroy */
-inline
-void
-dict_index_zip_pad_mutex_destroy(
- dict_index_t* index)
-{
- if (index->zip_pad.mutex_created == os_once::DONE
- && index->zip_pad.mutex != NULL) {
- mutex_free(index->zip_pad.mutex);
- UT_DELETE(index->zip_pad.mutex);
- }
-}
-
-/** Release the zip_pad_mutex of a given index.
-@param[in,out] index index whose zip_pad_mutex is to be released */
-inline
-void
-dict_index_zip_pad_unlock(
- dict_index_t* index)
-{
- mutex_exit(index->zip_pad.mutex);
-}
-
-#ifdef UNIV_DEBUG
-/** Check if the current thread owns the autoinc_mutex of a given table.
-@param[in] table the autoinc_mutex belongs to this table
-@return true, if the current thread owns the autoinc_mutex, false otherwise.*/
-inline
-bool
-dict_table_autoinc_own(
- const dict_table_t* table)
-{
- return(mutex_own(table->autoinc_mutex));
-}
-#endif /* UNIV_DEBUG */
-
/** Check whether the col is used in spatial index or regular index.
@param[in] col column to check
@return spatial status */
diff --git a/storage/innobase/include/dict0priv.h b/storage/innobase/include/dict0priv.h
index e56848d1954..3f2792054e0 100644
--- a/storage/innobase/include/dict0priv.h
+++ b/storage/innobase/include/dict0priv.h
@@ -45,18 +45,6 @@ dict_table_check_if_in_cache_low(
/*=============================*/
const char* table_name); /*!< in: table name */
-/**********************************************************************//**
-Returns a table object based on table id.
-@return table, NULL if does not exist */
-UNIV_INLINE
-dict_table_t*
-dict_table_open_on_id_low(
-/*=====================*/
- table_id_t table_id, /*!< in: table id */
- dict_err_ignore_t ignore_err, /*!< in: errors to ignore
- when loading the table */
- ibool open_only_if_in_cache);
-
#include "dict0priv.ic"
#endif /* dict0priv.h */
diff --git a/storage/innobase/include/dict0priv.ic b/storage/innobase/include/dict0priv.ic
index 7b584c7e1cb..ff645378175 100644
--- a/storage/innobase/include/dict0priv.ic
+++ b/storage/innobase/include/dict0priv.ic
@@ -25,7 +25,6 @@ Created Wed 13 Oct 2010 16:10:14 EST Sunny Bains
#include "dict0dict.h"
#include "dict0load.h"
-#include "dict0priv.h"
/**********************************************************************//**
Gets a table; loads it to the dictionary cache if necessary. A low-level
@@ -40,7 +39,7 @@ dict_table_get_low(
dict_table_t* table;
ut_ad(table_name);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
table = dict_table_check_if_in_cache_low(table_name);
@@ -64,40 +63,6 @@ dict_table_get_low(
}
/**********************************************************************//**
-Returns a table object based on table id.
-@return table, NULL if does not exist */
-UNIV_INLINE
-dict_table_t*
-dict_table_open_on_id_low(
-/*======================*/
- table_id_t table_id, /*!< in: table id */
- dict_err_ignore_t ignore_err, /*!< in: errors to ignore
- when loading the table */
- ibool open_only_if_in_cache)
-{
- dict_table_t* table;
- ulint fold;
-
- ut_ad(mutex_own(&dict_sys->mutex));
-
- /* Look for the table name in the hash table */
- fold = ut_fold_ull(table_id);
-
- HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
- dict_table_t*, table, ut_ad(table->cached),
- table->id == table_id);
- if (table == NULL && !open_only_if_in_cache) {
- table = dict_load_table_on_id(table_id, ignore_err);
- }
-
- ut_ad(!table || table->cached);
-
- /* TODO: should get the type information from MySQL */
-
- return(table);
-}
-
-/**********************************************************************//**
Checks if a table is in the dictionary cache.
@return table, NULL if not found */
UNIV_INLINE
@@ -114,12 +79,12 @@ dict_table_check_if_in_cache_low(
("table: '%s'", table_name));
ut_ad(table_name);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
/* Look for the table name in the hash table */
table_fold = ut_fold_string(table_name);
- HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
+ HASH_SEARCH(name_hash, dict_sys.table_hash, table_fold,
dict_table_t*, table, ut_ad(table->cached),
!strcmp(table->name.m_name, table_name));
DBUG_RETURN(table);
diff --git a/storage/innobase/include/dict0stats.h b/storage/innobase/include/dict0stats.h
index 98956412ae2..ab001130364 100644
--- a/storage/innobase/include/dict0stats.h
+++ b/storage/innobase/include/dict0stats.h
@@ -187,6 +187,19 @@ dict_stats_rename_table(
char* errstr, /*!< out: error string if != DB_SUCCESS
is returned */
size_t errstr_sz); /*!< in: errstr size */
+/*********************************************************************//**
+Renames an index in InnoDB persistent stats storage.
+This function creates its own transaction and commits it.
+@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
+if the persistent stats do not exist. */
+dberr_t
+dict_stats_rename_index(
+/*====================*/
+ const dict_table_t* table, /*!< in: table whose index
+ is renamed */
+ const char* old_index_name, /*!< in: old index name */
+ const char* new_index_name) /*!< in: new index name */
+ __attribute__((warn_unused_result));
/** Save an individual index's statistic into the persistent statistics
storage.
diff --git a/storage/innobase/include/dict0stats.ic b/storage/innobase/include/dict0stats.ic
index 31065d15c45..446d91f4c04 100644
--- a/storage/innobase/include/dict0stats.ic
+++ b/storage/innobase/include/dict0stats.ic
@@ -75,7 +75,7 @@ dict_stats_is_persistent_enabled(const dict_table_t* table)
+ dict_stats_update(DICT_STATS_RECALC_TRANSIENT) on a table that has
just been PS-enabled.
This is acceptable. Avoiding this would mean that we would have to
- protect the ::stat_persistent with dict_table_stats_lock() like the
+ protect the ::stat_persistent with dict_table_t::stats_latch like the
other ::stat_ members which would be too big performance penalty,
especially when this function is called from
dict_stats_update_if_needed(). */
@@ -148,7 +148,7 @@ dict_stats_init(
/*============*/
dict_table_t* table) /*!< in/out: table */
{
- ut_ad(!mutex_own(&dict_sys->mutex));
+ ut_ad(!mutex_own(&dict_sys.mutex));
if (table->stat_initialized) {
return;
@@ -174,14 +174,14 @@ dict_stats_deinit(
/*==============*/
dict_table_t* table) /*!< in/out: table */
{
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
ut_a(table->get_ref_count() == 0);
- dict_table_stats_lock(table, RW_X_LATCH);
+ rw_lock_x_lock(&table->stats_latch);
if (!table->stat_initialized) {
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
return;
}
@@ -223,5 +223,5 @@ dict_stats_deinit(
}
#endif /* UNIV_DEBUG_VALGRIND */
- dict_table_stats_unlock(table, RW_X_LATCH);
+ rw_lock_x_unlock(&table->stats_latch);
}
diff --git a/storage/innobase/include/dict0stats_bg.h b/storage/innobase/include/dict0stats_bg.h
index 66b98629033..526139643d1 100644
--- a/storage/innobase/include/dict0stats_bg.h
+++ b/storage/innobase/include/dict0stats_bg.h
@@ -72,7 +72,7 @@ dict_stats_stop_bg(
dict_table_t* table) /*!< in/out: table */
{
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
if (!(table->stats_bg_flag & BG_STAT_IN_PROGRESS)) {
return(true);
@@ -90,7 +90,7 @@ and restore the lock before it exits.
The background stats thread is guaranteed not to start using the specified
table after this function returns and before the caller unlocks the data
dictionary because it sets the BG_STAT_IN_PROGRESS bit in table->stats_bg_flag
-under dict_sys->mutex. */
+under dict_sys.mutex. */
void
dict_stats_wait_bg_to_stop_using_table(
/*===================================*/
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index 1e16e501a48..d0da45ab218 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -30,7 +30,6 @@ Created 1/8/1996 Heikki Tuuri
#include <ut0mutex.h>
#include <rem0types.h>
-struct dict_sys_t;
struct dict_col_t;
struct dict_field_t;
struct dict_index_t;
diff --git a/storage/innobase/include/fil0crypt.h b/storage/innobase/include/fil0crypt.h
index 870858b4ccd..fd0d3e12601 100644
--- a/storage/innobase/include/fil0crypt.h
+++ b/storage/innobase/include/fil0crypt.h
@@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 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
@@ -26,11 +26,9 @@ Created 04/01/2015 Jan Lindström
#ifndef fil0crypt_h
#define fil0crypt_h
-#ifndef UNIV_INNOCHECKSUM
#include "os0event.h"
#include "my_crypt.h"
#include "fil0fil.h"
-#endif /*! UNIV_INNOCHECKSUM */
/**
* Magic pattern in start of crypt data on page 0
@@ -281,13 +279,11 @@ fil_space_merge_crypt_data(
const fil_space_crypt_t* src);
/** Initialize encryption parameters from a tablespace header page.
-@param[in] page_size page size of the tablespace
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] page first page of the tablespace
@return crypt data from page 0
@retval NULL if not present or not valid */
-UNIV_INTERN
-fil_space_crypt_t*
-fil_space_read_crypt_data(const page_size_t& page_size, const byte* page)
+fil_space_crypt_t* fil_space_read_crypt_data(ulint zip_size, const byte* page)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/**
@@ -313,14 +309,16 @@ fil_parse_write_crypt_data(
MY_ATTRIBUTE((warn_unused_result));
/** Encrypt a buffer.
-@param[in,out] crypt_data Crypt data
-@param[in] space space_id
-@param[in] offset Page offset
-@param[in] lsn Log sequence number
-@param[in] src_frame Page to encrypt
-@param[in] page_size Page size
-@param[in,out] dst_frame Output buffer
+@param[in,out] crypt_data Crypt data
+@param[in] space space_id
+@param[in] offset Page offset
+@param[in] lsn Log sequence number
+@param[in] src_frame Page to encrypt
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in,out] dst_frame Output buffer
+@param[in] use_full_checksum full crc32 algo is used
@return encrypted buffer or NULL */
+UNIV_INTERN
byte*
fil_encrypt_buf(
fil_space_crypt_t* crypt_data,
@@ -328,8 +326,9 @@ fil_encrypt_buf(
ulint offset,
lsn_t lsn,
const byte* src_frame,
- const page_size_t& page_size,
- byte* dst_frame)
+ ulint zip_size,
+ byte* dst_frame,
+ bool use_full_checksum)
MY_ATTRIBUTE((warn_unused_result));
/**
@@ -351,20 +350,24 @@ fil_space_encrypt(
byte* dst_frame)
MY_ATTRIBUTE((warn_unused_result));
-/**
-Decrypt a page.
-@param[in,out] crypt_data crypt_data
+
+/** Decrypt a page.
+@param]in] space_id space id
+@param[in] crypt_data crypt_data
@param[in] tmp_frame Temporary buffer
-@param[in] page_size Page size
+@param[in] physical_size page size
+@param[in] fsp_flags Tablespace flags
@param[in,out] src_frame Page to decrypt
-@param[out] err DB_SUCCESS or error
+@param[out] err DB_SUCCESS or DB_DECRYPTION_FAILED
@return true if page decrypted, false if not.*/
UNIV_INTERN
bool
fil_space_decrypt(
+ ulint space_id,
fil_space_crypt_t* crypt_data,
byte* tmp_frame,
- const page_size_t& page_size,
+ ulint physical_size,
+ ulint fsp_flags,
byte* src_frame,
dberr_t* err);
@@ -383,17 +386,14 @@ fil_space_decrypt(
byte* src_frame)
MY_ATTRIBUTE((warn_unused_result));
-/******************************************************************
+/**
Calculate post encryption checksum
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] dst_frame Block where checksum is calculated
-@return page checksum or BUF_NO_CHECKSUM_MAGIC
+@return page checksum
not needed. */
-UNIV_INTERN
uint32_t
-fil_crypt_calculate_checksum(
- const page_size_t& page_size,
- const byte* dst_frame)
+fil_crypt_calculate_checksum(ulint zip_size, const byte* dst_frame)
MY_ATTRIBUTE((warn_unused_result));
/*********************************************************************
@@ -491,10 +491,9 @@ calculated checksum as if it does page could be valid unencrypted,
encrypted, or corrupted.
@param[in,out] page page frame (checksum is temporarily modified)
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return true if page is encrypted AND OK, false otherwise */
-bool
-fil_space_verify_crypt_checksum(const byte* page, const page_size_t& page_size)
+bool fil_space_verify_crypt_checksum(const byte* page, ulint zip_size)
MY_ATTRIBUTE((warn_unused_result));
#endif /* fil0crypt_h */
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index a754b978cbe..a24b2a43fda 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -27,12 +27,16 @@ Created 10/25/1995 Heikki Tuuri
#ifndef fil0fil_h
#define fil0fil_h
+#include "fsp0types.h"
+
#ifndef UNIV_INNOCHECKSUM
#include "log0recv.h"
#include "dict0types.h"
-#include "page0size.h"
#include "intrusive_list.h"
+#ifdef UNIV_LINUX
+# include <set>
+#endif
struct unflushed_spaces_tag_t;
struct rotation_list_tag_t;
@@ -41,8 +45,6 @@ struct rotation_list_tag_t;
extern my_bool srv_use_doublewrite_buf;
extern struct buf_dblwr_t* buf_dblwr;
class page_id_t;
-struct trx_t;
-class truncate_t;
/** Structure containing encryption specification */
struct fil_space_crypt_t;
@@ -76,10 +78,17 @@ fil_type_is_data(
struct fil_node_t;
+#endif
+
/** Tablespace or log data space */
+#ifndef UNIV_INNOCHECKSUM
struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
intrusive::list_node<rotation_list_tag_t>
+#else
+struct fil_space_t
+#endif
{
+#ifndef UNIV_INNOCHECKSUM
ulint id; /*!< space id */
hash_node_t hash; /*!< hash chain node */
char* name; /*!< Tablespace name */
@@ -93,26 +102,21 @@ struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
/** Log sequence number of the latest MLOG_INDEX_LOAD record
that was found while parsing the redo log */
lsn_t enable_lsn;
+ /** set when an .ibd file is about to be deleted,
+ or an undo tablespace is about to be truncated.
+ When this is set following new ops are not allowed:
+ * read IO request
+ * ibuf merge
+ * file flush
+ Note that we can still possibly have new write operations
+ because we don't check this flag when doing flush batches. */
bool stop_new_ops;
- /*!< we set this true when we start
- deleting a single-table tablespace.
- When this is set following new ops
- are not allowed:
- * read IO request
- * ibuf merge
- * file flush
- Note that we can still possibly have
- new write operations because we don't
- check this flag when doing flush
- batches. */
/** whether undo tablespace truncation is in progress */
bool is_being_truncated;
#ifdef UNIV_DEBUG
- ulint redo_skipped_count;
- /*!< reference count for operations who want
- to skip redo log in the file space in order
- to make modify_check() pass.
- Uses my_atomic_loadlint() and friends. */
+ /** reference count for operations who want to skip redo log in the
+ file space in order to make modify_check() pass. */
+ Atomic_counter<ulint> redo_skipped_count;
#endif
fil_type_t purpose;/*!< purpose */
UT_LIST_BASE_NODE_T(fil_node_t) chain;
@@ -130,10 +134,6 @@ struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
/*!< recovered tablespace size in pages;
0 if no size change was read from the redo log,
or if the size change was implemented */
- ulint flags; /*!< FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
- see fsp0types.h,
- fsp_flags_is_valid(),
- page_size_t(ulint) (constructor) */
ulint n_reserved_extents;
/*!< number of reserved free extents for
ongoing operations like B-tree page split */
@@ -141,20 +141,20 @@ struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
the tablespace to disk; dropping of the
tablespace is forbidden if this is positive */
/** Number of pending buffer pool operations accessing the tablespace
- without holding a table lock or dict_operation_lock S-latch
+ without holding a table lock or dict_sys.latch S-latch
that would prevent the table (and tablespace) from being
dropped. An example is change buffer merge.
The tablespace cannot be dropped while this is nonzero,
or while fil_node_t::n_pending is nonzero.
- Protected by fil_system.mutex and my_atomic_loadlint() and friends. */
- ulint n_pending_ops;
+ Protected by fil_system.mutex and std::atomic. */
+ std::atomic<ulint> n_pending_ops;
/** Number of pending block read or write operations
(when a write is imminent or a read has recently completed).
The tablespace object cannot be freed while this is nonzero,
but it can be detached from fil_system.
Note that fil_node_t::n_pending tracks actual pending I/O requests.
- Protected by fil_system.mutex and my_atomic_loadlint() and friends. */
- ulint n_pending_ios;
+ Protected by fil_system.mutex and std::atomic. */
+ std::atomic<ulint> n_pending_ios;
rw_lock_t latch; /*!< latch protecting the file space storage
allocation */
UT_LIST_NODE_T(fil_space_t) named_spaces;
@@ -248,7 +248,10 @@ struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
/** Note that the tablespace has been imported.
Initially, purpose=FIL_TYPE_IMPORT so that no redo log is
written while the space ID is being updated in each page. */
- void set_imported();
+ inline void set_imported();
+
+ /** @return whether the storage device is rotational (HDD, not SSD) */
+ inline bool is_rotational() const;
/** Open each file. Only invoked on fil_system.temp_space.
@return whether all files were opened */
@@ -257,38 +260,290 @@ struct fil_space_t : intrusive::list_node<unflushed_spaces_tag_t>,
void close();
/** Acquire a tablespace reference. */
- void acquire() { my_atomic_addlint(&n_pending_ops, 1); }
+ void acquire() { n_pending_ops++; }
/** Release a tablespace reference. */
- void release()
+ void release() { ut_ad(referenced()); n_pending_ops--; }
+ /** @return whether references are being held */
+ bool referenced() const { return n_pending_ops; }
+
+ /** Acquire a tablespace reference for I/O. */
+ void acquire_for_io() { n_pending_ios++; }
+ /** Release a tablespace reference for I/O. */
+ void release_for_io() { ut_ad(pending_io()); n_pending_ios--; }
+ /** @return whether I/O is pending */
+ bool pending_io() const { return n_pending_ios; }
+#endif /* !UNIV_INNOCHECKSUM */
+ /** FSP_SPACE_FLAGS and FSP_FLAGS_MEM_ flags;
+ check fsp0types.h to more info about flags. */
+ ulint flags;
+
+ /** Determine if full_crc32 is used for a data file
+ @param[in] flags tablespace flags (FSP_FLAGS)
+ @return whether the full_crc32 algorithm is active */
+ static bool full_crc32(ulint flags) {
+ return flags & FSP_FLAGS_FCRC32_MASK_MARKER;
+ }
+ /** @return whether innodb_checksum_algorithm=full_crc32 is active */
+ bool full_crc32() const { return full_crc32(flags); }
+ /** Determine the logical page size.
+ @param flags tablespace flags (FSP_FLAGS)
+ @return the logical page size
+ @retval 0 if the flags are invalid */
+ static unsigned logical_size(ulint flags) {
+
+ ulint page_ssize = 0;
+
+ if (full_crc32(flags)) {
+ page_ssize = FSP_FLAGS_FCRC32_GET_PAGE_SSIZE(flags);
+ } else {
+ page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
+ }
+
+ switch (page_ssize) {
+ case 3: return 4096;
+ case 4: return 8192;
+ case 5:
+ { ut_ad(full_crc32(flags)); return 16384; }
+ case 0:
+ { ut_ad(!full_crc32(flags)); return 16384; }
+ case 6: return 32768;
+ case 7: return 65536;
+ default: return 0;
+ }
+ }
+ /** Determine the ROW_FORMAT=COMPRESSED page size.
+ @param flags tablespace flags (FSP_FLAGS)
+ @return the ROW_FORMAT=COMPRESSED page size
+ @retval 0 if ROW_FORMAT=COMPRESSED is not used */
+ static unsigned zip_size(ulint flags) {
+
+ if (full_crc32(flags)) {
+ return 0;
+ }
+
+ ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
+ return zip_ssize
+ ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize : 0;
+ }
+ /** Determine the physical page size.
+ @param flags tablespace flags (FSP_FLAGS)
+ @return the physical page size */
+ static unsigned physical_size(ulint flags) {
+
+ if (full_crc32(flags)) {
+ return logical_size(flags);
+ }
+
+ ulint zip_ssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
+ return zip_ssize
+ ? (UNIV_ZIP_SIZE_MIN >> 1) << zip_ssize
+ : unsigned(srv_page_size);
+ }
+ /** @return the ROW_FORMAT=COMPRESSED page size
+ @retval 0 if ROW_FORMAT=COMPRESSED is not used */
+ unsigned zip_size() const { return zip_size(flags); }
+ /** @return the physical page size */
+ unsigned physical_size() const { return physical_size(flags); }
+ /** Check whether the compression enabled in tablespace.
+ @param[in] flags tablespace flags */
+ static bool is_compressed(ulint flags) {
+
+ if (full_crc32(flags)) {
+ ulint algo = FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO(
+ flags);
+ DBUG_ASSERT(algo <= PAGE_ALGORITHM_LAST);
+ return algo > 0;
+ }
+
+ return FSP_FLAGS_HAS_PAGE_COMPRESSION(flags);
+ }
+ /** @return whether the compression enabled for the tablespace. */
+ bool is_compressed() const { return is_compressed(flags); }
+
+ /** Get the compression algorithm for full crc32 format.
+ @param[in] flags tablespace flags
+ @return algorithm type of tablespace */
+ static ulint get_compression_algo(ulint flags)
{
- ut_ad(referenced());
- my_atomic_addlint(&n_pending_ops, ulint(-1));
+ return full_crc32(flags)
+ ? FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO(flags)
+ : 0;
}
- /** @return whether references are being held */
- bool referenced() { return my_atomic_loadlint(&n_pending_ops); }
- /** @return whether references are being held */
- bool referenced() const
+ /** @return the page_compressed algorithm
+ @retval 0 if not page_compressed */
+ ulint get_compression_algo() const {
+ return fil_space_t::get_compression_algo(flags);
+ }
+ /** Determine if the page_compressed page contains an extra byte
+ for exact compressed stream length
+ @param[in] flags tablespace flags
+ @return whether the extra byte is needed */
+ static bool full_crc32_page_compressed_len(ulint flags)
{
- return const_cast<fil_space_t*>(this)->referenced();
+ DBUG_ASSERT(full_crc32(flags));
+ switch (get_compression_algo(flags)) {
+ case PAGE_LZ4_ALGORITHM:
+ case PAGE_LZO_ALGORITHM:
+ case PAGE_SNAPPY_ALGORITHM:
+ return true;
+ }
+ return false;
}
- /** Acquire a tablespace reference for I/O. */
- void acquire_for_io() { my_atomic_addlint(&n_pending_ios, 1); }
- /** Release a tablespace reference for I/O. */
- void release_for_io()
+ /** Whether the full checksum matches with non full checksum flags.
+ @param[in] flags flags present
+ @param[in] expected expected flags
+ @return true if it is equivalent */
+ static bool is_flags_full_crc32_equal(ulint flags, ulint expected)
{
- ut_ad(pending_io());
- my_atomic_addlint(&n_pending_ios, ulint(-1));
+ ut_ad(full_crc32(flags));
+ ulint page_ssize = FSP_FLAGS_FCRC32_GET_PAGE_SSIZE(flags);
+
+ if (full_crc32(expected)) {
+ /* The data file may have been created with a
+ different innodb_compression_algorithm. But
+ we only support one innodb_page_size for all files. */
+ return page_ssize
+ == FSP_FLAGS_FCRC32_GET_PAGE_SSIZE(expected);
+ }
+
+ ulint space_page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(expected);
+
+ if (page_ssize == 5) {
+ if (space_page_ssize) {
+ return false;
+ }
+ } else if (space_page_ssize != page_ssize) {
+ return false;
+ }
+
+ return true;
}
- /** @return whether I/O is pending */
- bool pending_io() { return my_atomic_loadlint(&n_pending_ios); }
- /** @return whether I/O is pending */
- bool pending_io() const
+ /** Whether old tablespace flags match full_crc32 flags.
+ @param[in] flags flags present
+ @param[in] expected expected flags
+ @return true if it is equivalent */
+ static bool is_flags_non_full_crc32_equal(ulint flags, ulint expected)
+ {
+ ut_ad(!full_crc32(flags));
+
+ if (!full_crc32(expected)) {
+ return false;
+ }
+
+ ulint page_ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
+ ulint space_page_ssize = FSP_FLAGS_FCRC32_GET_PAGE_SSIZE(
+ expected);
+
+ if (page_ssize) {
+ if (space_page_ssize != 5) {
+ return false;
+ }
+ } else if (space_page_ssize != page_ssize) {
+ return false;
+ }
+
+ return true;
+ }
+ /** Whether both fsp flags are equivalent */
+ static bool is_flags_equal(ulint flags, ulint expected)
+ {
+ if (!((flags ^ expected) & ~(1U << FSP_FLAGS_POS_RESERVED))) {
+ return true;
+ }
+
+ return full_crc32(flags)
+ ? is_flags_full_crc32_equal(flags, expected)
+ : is_flags_non_full_crc32_equal(flags, expected);
+ }
+ /** Validate the tablespace flags for full crc32 format.
+ @param[in] flags the content of FSP_SPACE_FLAGS
+ @return whether the flags are correct in full crc32 format */
+ static bool is_fcrc32_valid_flags(ulint flags)
+ {
+ ut_ad(flags & FSP_FLAGS_FCRC32_MASK_MARKER);
+ const ulint page_ssize = physical_size(flags);
+ if (page_ssize < 3 || page_ssize & 8) {
+ return false;
+ }
+
+ flags >>= FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO;
+
+ return flags <= PAGE_ALGORITHM_LAST;
+ }
+ /** Validate the tablespace flags.
+ @param[in] flags content of FSP_SPACE_FLAGS
+ @param[in] is_ibd whether this is an .ibd file
+ (not system tablespace)
+ @return whether the flags are correct. */
+ static bool is_valid_flags(ulint flags, bool is_ibd)
{
- return const_cast<fil_space_t*>(this)->pending_io();
+ DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
+ return false;);
+
+ if (full_crc32(flags)) {
+ return is_fcrc32_valid_flags(flags);
+ }
+
+ if (flags == 0) {
+ return true;
+ }
+
+ if (flags & ~FSP_FLAGS_MASK) {
+ return false;
+ }
+
+ if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE
+ | FSP_FLAGS_MASK_ATOMIC_BLOBS))
+ == FSP_FLAGS_MASK_ATOMIC_BLOBS) {
+ /* If the "atomic blobs" flag (indicating
+ ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag
+ is set, then the "post Antelope"
+ (ROW_FORMAT!=REDUNDANT) flag must also be set. */
+ return false;
+ }
+
+ /* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag
+ of MySQL 5.6 and MariaDB 10.0, which we ignore.
+ In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20,
+ bits 10..14 would be nonzero 0bsssaa where sss is
+ nonzero PAGE_SSIZE (3, 4, 6, or 7)
+ and aa is ATOMIC_WRITES (not 0b11). */
+ if (FSP_FLAGS_GET_RESERVED(flags) & ~1U) {
+ return false;
+ }
+
+ const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
+ if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) {
+ /* the page_size is not between 4k and 64k;
+ 16k should be encoded as 0, not 5 */
+ return false;
+ }
+
+ const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
+ if (zssize == 0) {
+ /* not ROW_FORMAT=COMPRESSED */
+ } else if (zssize > (ssize ? ssize : 5)) {
+ /* Invalid KEY_BLOCK_SIZE */
+ return false;
+ } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE
+ | FSP_FLAGS_MASK_ATOMIC_BLOBS)) {
+ /* both these flags should be set for
+ ROW_FORMAT=COMPRESSED */
+ return false;
+ }
+
+ /* The flags do look valid. But, avoid misinterpreting
+ buggy MariaDB 10.1 format flags for
+ PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL={0,2,3}
+ as valid-looking PAGE_SSIZE if this is known to be
+ an .ibd file and we are using the default innodb_page_size=16k. */
+ return(ssize == 0 || !is_ibd
+ || srv_page_size != UNIV_PAGE_SIZE_ORIG);
}
};
+#ifndef UNIV_INNOCHECKSUM
/** Value of fil_space_t::magic_n */
#define FIL_SPACE_MAGIC_N 89472
@@ -302,6 +557,8 @@ struct fil_node_t {
pfs_os_file_t handle;
/** whether the file actually is a raw device or disk partition */
bool is_raw_disk;
+ /** whether the file is on non-rotational media (SSD) */
+ bool on_ssd;
/** size of the file in database pages (0 if not known yet);
the possible last incomplete megabyte may be ignored
if space->id == 0 */
@@ -344,6 +601,14 @@ struct fil_node_t {
@return whether the page was found valid */
bool read_page0(bool first);
+ /** Determine some file metadata when creating or reading the file.
+ @param file the file that is being created, or OS_FILE_CLOSED */
+ void find_metadata(os_file_t file = OS_FILE_CLOSED
+#ifdef UNIV_LINUX
+ , struct stat* statbuf = NULL
+#endif
+ );
+
/** Close the file handle. */
void close();
};
@@ -351,6 +616,24 @@ struct fil_node_t {
/** Value of fil_node_t::magic_n */
#define FIL_NODE_MAGIC_N 89389
+inline void fil_space_t::set_imported()
+{
+ ut_ad(purpose == FIL_TYPE_IMPORT);
+ purpose = FIL_TYPE_TABLESPACE;
+ UT_LIST_GET_FIRST(chain)->find_metadata();
+}
+
+inline bool fil_space_t::is_rotational() const
+{
+ for (const fil_node_t* node = UT_LIST_GET_FIRST(chain);
+ node != NULL; node = UT_LIST_GET_NEXT(chain, node)) {
+ if (!node->on_ssd) {
+ return true;
+ }
+ }
+ return false;
+}
+
/** Common InnoDB file extensions */
enum ib_extention {
NO_EXT = 0,
@@ -389,19 +672,12 @@ typedef byte fil_faddr_t; /*!< 'type' definition in C: an address
#define FIL_ADDR_BYTE 4U /* then comes 2-byte byte offset within page*/
#define FIL_ADDR_SIZE 6U /* address size is 6 bytes */
-#ifndef UNIV_INNOCHECKSUM
-
/** File space address */
struct fil_addr_t {
ulint page; /*!< page number within a space */
ulint boffset; /*!< byte offset within the page */
};
-/** The null file address */
-extern const fil_addr_t fil_addr_null;
-
-#endif /* !UNIV_INNOCHECKSUM */
-
/** The byte offsets on a file page for various variables @{ */
#define FIL_PAGE_SPACE_OR_CHKSUM 0 /*!< in < MySQL-4.0.14 space id the
page belongs to (== 0) but in later
@@ -442,19 +718,19 @@ extern const fil_addr_t fil_addr_null;
MySQL/InnoDB 5.1.7 or later, the
contents of this field is valid
for all uncompressed pages. */
-#define FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION 26U /*!< for the first page
- in a system tablespace data file
- (ibdata*, not *.ibd): the file has
- been flushed to disk at least up
- to this lsn
- for other pages: a 32-bit key version
- used to encrypt the page + 32-bit checksum
- or 64 bits of zero if no encryption
- */
+
+/** For the first page in a system tablespace data file(ibdata*, not *.ibd):
+the file has been flushed to disk at least up to this lsn
+For other pages: 32-bit key version used to encrypt the page + 32-bit checksum
+or 64 bites of zero if no encryption */
+#define FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION 26U
/** This overloads FIL_PAGE_FILE_FLUSH_LSN for RTREE Split Sequence Number */
#define FIL_RTREE_SPLIT_SEQ_NUM FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+/** Start of the page_compressed content */
+#define FIL_PAGE_COMP_ALGO FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+
/** starting from 4.1.x this contains the space id of the page */
#define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34U
@@ -462,25 +738,45 @@ extern const fil_addr_t fil_addr_null;
#define FIL_PAGE_DATA 38U /*!< start of the data on the page */
-/* Following are used when page compression is used */
-#define FIL_PAGE_COMPRESSED_SIZE 2 /*!< Number of bytes used to store
- actual payload data size on
- compressed pages. */
-#define FIL_PAGE_COMPRESSION_METHOD_SIZE 2
- /*!< Number of bytes used to store
- actual compression method. */
+/** 32-bit key version used to encrypt the page in full_crc32 format.
+For non-encrypted page, it contains 0. */
+#define FIL_PAGE_FCRC32_KEY_VERSION 0
+
+/** page_compressed without innodb_checksum_algorithm=full_crc32 @{ */
+/** Number of bytes used to store actual payload data size on
+page_compressed pages when not using full_crc32. */
+#define FIL_PAGE_COMP_SIZE 0
+
+/** Number of bytes for FIL_PAGE_COMP_SIZE */
+#define FIL_PAGE_COMP_METADATA_LEN 2
+
+/** Number of bytes used to store actual compression method
+for encrypted tables when not using full_crc32. */
+#define FIL_PAGE_ENCRYPT_COMP_ALGO 2
+
+/** Extra header size for encrypted page_compressed pages when
+not using full_crc32 */
+#define FIL_PAGE_ENCRYPT_COMP_METADATA_LEN 4
/* @} */
+
/** File page trailer @{ */
#define FIL_PAGE_END_LSN_OLD_CHKSUM 8 /*!< the low 4 bytes of this are used
to store the page checksum, the
last 4 bytes should be identical
to the last 4 bytes of FIL_PAGE_LSN */
#define FIL_PAGE_DATA_END 8 /*!< size of the page trailer */
+
+/** Store the last 4 bytes of FIL_PAGE_LSN */
+#define FIL_PAGE_FCRC32_END_LSN 8
+
+/** Store crc32 checksum at the end of the page */
+#define FIL_PAGE_FCRC32_CHECKSUM 4
/* @} */
/** File page types (values of FIL_PAGE_TYPE) @{ */
-#define FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED 37401 /*!< Page is compressed and
- then encrypted */
+/** page_compressed, encrypted=YES (not used for full_crc32) */
+#define FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED 37401
+/** page_compressed (not used for full_crc32) */
#define FIL_PAGE_PAGE_COMPRESSED 34354 /*!< page compressed page */
#define FIL_PAGE_INDEX 17855 /*!< B-tree node */
#define FIL_PAGE_RTREE 17854 /*!< R-tree node (SPATIAL INDEX) */
@@ -513,6 +809,12 @@ extern const fil_addr_t fil_addr_null;
Note: FIL_PAGE_TYPE_INSTANT maps to the same as FIL_PAGE_INDEX. */
#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_UNKNOWN
/*!< Last page type */
+/** Set in FIL_PAGE_TYPE if for full_crc32 pages in page_compressed format.
+If the flag is set, then the following holds for the remaining bits
+of FIL_PAGE_TYPE:
+Bits 0..7 will contain the compressed page size in bytes.
+Bits 8..14 are reserved and must be 0. */
+#define FIL_PAGE_COMPRESS_FCRC32_MARKER 15
/* @} */
/** @return whether the page type is B-tree or R-tree index */
@@ -597,6 +899,22 @@ struct fil_system_t {
private:
bool m_initialised;
+#ifdef UNIV_LINUX
+ /** available block devices that reside on non-rotational storage */
+ std::vector<dev_t> ssd;
+public:
+ /** @return whether a file system device is on non-rotational storage */
+ bool is_ssd(dev_t dev) const
+ {
+ /* Linux seems to allow up to 15 partitions per block device.
+ If the detected ssd carries "partition number 0" (it is the whole device),
+ compare the candidate file system number without the partition number. */
+ for (const auto s : ssd)
+ if (dev == s || (dev & ~15U) == s)
+ return true;
+ return false;
+ }
+#endif
public:
ib_mutex_t mutex; /*!< The mutex protecting the cache */
fil_space_t* sys_space; /*!< The innodb_system tablespace */
@@ -749,16 +1067,6 @@ fil_space_get_flags(
/*================*/
ulint id); /*!< in: space id */
-/** Returns the page size of the space and whether it is compressed or not.
-The tablespace must be cached in the memory cache.
-@param[in] id space id
-@param[out] found true if tablespace was found
-@return page size */
-const page_size_t
-fil_space_get_page_size(
- ulint id,
- bool* found);
-
/*******************************************************************//**
Opens all log files and system tablespace data files. They stay open until the
database server shutdown. This should be called at a server startup after the
@@ -804,10 +1112,8 @@ for concurrency control.
@param[in] id tablespace ID
@param[in] silent whether to silently ignore missing tablespaces
@return the tablespace
-@retval NULL if missing or being deleted or truncated */
-UNIV_INTERN
-fil_space_t*
-fil_space_acquire_low(ulint id, bool silent)
+@retval NULL if missing or being deleted */
+fil_space_t* fil_space_acquire_low(ulint id, bool silent)
MY_ATTRIBUTE((warn_unused_result));
/** Acquire a tablespace when it could be dropped concurrently.
@@ -1085,7 +1391,7 @@ fil_space_extend(
@param[in] type IO context
@param[in] sync true if synchronous aio is desired
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] byte_offset remainder of offset in bytes; in aio this
must be divisible by the OS block size
@param[in] len how many bytes to read or write; this must
@@ -1097,14 +1403,14 @@ fil_space_extend(
@param[in] message message for aio handler if non-sync aio
used, else ignored
@param[in] ignore_missing_space true=ignore missing space during read
-@return DB_SUCCESS, DB_TABLESPACE_DELETED or DB_TABLESPACE_TRUNCATED
+@return DB_SUCCESS, or DB_TABLESPACE_DELETED
if we are trying to do i/o on a tablespace which does not exist */
dberr_t
fil_io(
const IORequest& type,
bool sync,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
ulint byte_offset,
ulint len,
void* buf,
diff --git a/storage/innobase/include/fil0fil.ic b/storage/innobase/include/fil0fil.ic
index 31466f38546..24e4157d1f3 100644
--- a/storage/innobase/include/fil0fil.ic
+++ b/storage/innobase/include/fil0fil.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 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
@@ -75,17 +75,25 @@ fil_get_page_type_name(
}
}
-/****************************************************************//**
-Validate page type.
+#ifdef UNIV_DEBUG
+/** Validate page type.
+@param[in] space Tablespace object
+@param[in] page page to validate
@return true if valid, false if not */
UNIV_INLINE
bool
fil_page_type_validate(
- const byte* page) /*!< in: page */
+ fil_space_t* space,
+ const byte* page)
{
-#ifdef UNIV_DEBUG
ulint page_type = mach_read_from_2(page + FIL_PAGE_TYPE);
+ if ((page_type & 1U << FIL_PAGE_COMPRESS_FCRC32_MARKER)
+ && space->full_crc32()
+ && space->is_compressed()) {
+ return true;
+ }
+
/* Validate page type */
if (!((page_type == FIL_PAGE_PAGE_COMPRESSED ||
page_type == FIL_PAGE_PAGE_COMPRESSED_ENCRYPTED ||
@@ -106,25 +114,31 @@ fil_page_type_validate(
page_type == FIL_PAGE_TYPE_ZBLOB2 ||
page_type == FIL_PAGE_TYPE_UNKNOWN))) {
- ulint space = mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+ ulint space_id = mach_read_from_4(
+ page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
+
ulint offset = mach_read_from_4(page + FIL_PAGE_OFFSET);
- fil_system_enter();
- fil_space_t* rspace = fil_space_get_by_id(space);
- fil_system_exit();
+
+ ulint key_version = mach_read_from_4(
+ page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+
+ if (space && space->full_crc32()) {
+ key_version = mach_read_from_4(
+ page + FIL_PAGE_FCRC32_KEY_VERSION);
+ }
/* Dump out the page info */
- ib::fatal() << "Page " << space << ":" << offset
- << " name " << (rspace ? rspace->name : "???")
+ ib::fatal() << "Page " << space_id << ":" << offset
+ << " name " << (space ? space->name : "???")
<< " page_type " << page_type
- << " key_version "
- << mach_read_from_4(page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION)
+ << " key_version " << key_version
<< " lsn " << mach_read_from_8(page + FIL_PAGE_LSN)
<< " compressed_len " << mach_read_from_2(page + FIL_PAGE_DATA);
return false;
}
-#endif /* UNIV_DEBUG */
return true;
}
+#endif /* UNIV_DEBUG */
#endif /* fil0fil_ic */
diff --git a/storage/innobase/include/fil0pagecompress.h b/storage/innobase/include/fil0pagecompress.h
index 545e05da769..9baf3289380 100644
--- a/storage/innobase/include/fil0pagecompress.h
+++ b/storage/innobase/include/fil0pagecompress.h
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (C) 2013, 2018 MariaDB Corporation.
+Copyright (C) 2013, 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
@@ -33,21 +33,29 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
/** Compress a page_compressed page before writing to a data file.
@param[in] buf page to be compressed
@param[out] out_buf compressed page
-@param[in] level compression level
+@param[in] flags tablespace flags
@param[in] block_size file system block size
@param[in] encrypted whether the page will be subsequently encrypted
@return actual length of compressed page
@retval 0 if the page was not compressed */
-ulint fil_page_compress(const byte* buf, byte* out_buf, ulint level,
- ulint block_size, bool encrypted)
+ulint fil_page_compress(
+ const byte* buf,
+ byte* out_buf,
+ ulint flags,
+ ulint block_size,
+ bool encrypted)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Decompress a page that may be subject to page_compressed compression.
@param[in,out] tmp_buf temporary buffer (of innodb_page_size)
@param[in,out] buf compressed page buffer
+@param[in] flags talespace flags
@return size of the compressed data
@retval 0 if decompression failed
@retval srv_page_size if the page was not compressed */
-ulint fil_page_decompress(byte* tmp_buf, byte* buf)
+ulint fil_page_decompress(
+ byte* tmp_buf,
+ byte* buf,
+ ulint flags)
MY_ATTRIBUTE((nonnull, warn_unused_result));
#endif
diff --git a/storage/innobase/include/fsp0file.h b/storage/innobase/include/fsp0file.h
index 8c5b24fbadb..15485769429 100644
--- a/storage/innobase/include/fsp0file.h
+++ b/storage/innobase/include/fsp0file.h
@@ -504,13 +504,13 @@ public:
/* No op - base constructor is called. */
}
- ~RemoteDatafile()
+ ~RemoteDatafile() override
{
shutdown();
}
/** Release the resources. */
- void shutdown();
+ void shutdown() override;
/** Get the link filepath.
@return m_link_filepath */
@@ -532,7 +532,7 @@ public:
in read-only mode so that it can be validated.
@param[in] strict whether to issue error messages
@return DB_SUCCESS or error code */
- dberr_t open_read_only(bool strict);
+ dberr_t open_read_only(bool strict) override;
/** Opens a handle to the file linked to in an InnoDB Symbolic Link
file in read-write mode so that it can be restored from doublewrite
@@ -540,7 +540,7 @@ public:
@param[in] read_only_mode If true, then readonly mode checks
are enforced.
@return DB_SUCCESS or error code */
- dberr_t open_read_write(bool read_only_mode)
+ dberr_t open_read_write(bool read_only_mode) override
MY_ATTRIBUTE((warn_unused_result));
/******************************************************************
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index c51f1748585..75c448c956d 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -28,15 +28,15 @@ Created 12/18/1995 Heikki Tuuri
#define fsp0fsp_h
#include "fsp0types.h"
+#include "fut0lst.h"
+#include "ut0byte.h"
#ifndef UNIV_INNOCHECKSUM
-
-#include "fut0lst.h"
#include "mtr0mtr.h"
#include "page0types.h"
#include "rem0types.h"
-#include "ut0byte.h"
-
+#else
+# include "mach0data.h"
#endif /* !UNIV_INNOCHECKSUM */
/** @return the PAGE_SSIZE flags for the current innodb_page_size */
@@ -45,6 +45,12 @@ Created 12/18/1995 Heikki Tuuri
0U : (srv_page_size_shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1) \
<< FSP_FLAGS_POS_PAGE_SSIZE)
+/** @return the PAGE_SSIZE flags for the current innodb_page_size in
+full checksum format */
+#define FSP_FLAGS_FCRC32_PAGE_SSIZE() \
+ ((srv_page_size_shift - UNIV_ZIP_SIZE_SHIFT_MIN + 1) \
+ << FSP_FLAGS_FCRC32_POS_PAGE_SSIZE)
+
/* @defgroup Compatibility macros for MariaDB 10.1.0 through 10.1.20;
see the table in fsp0types.h @{ */
/** Zero relative shift position of the PAGE_COMPRESSION field */
@@ -201,11 +207,6 @@ typedef byte fseg_inode_t;
(16 + 3 * FLST_BASE_NODE_SIZE \
+ FSEG_FRAG_ARR_N_SLOTS * FSEG_FRAG_SLOT_SIZE)
-#define FSP_SEG_INODES_PER_PAGE(page_size) \
- ((page_size.physical() - FSEG_ARR_OFFSET - 10) / FSEG_INODE_SIZE)
- /* Number of segment inodes which fit on a
- single page */
-
#define FSEG_MAGIC_N_VALUE 97937874
#define FSEG_FILLFACTOR 8 /* If this value is x, then if
@@ -290,33 +291,6 @@ the extent are free and which contain old tuple version to clean. */
#ifndef UNIV_INNOCHECKSUM
/* @} */
-/** Calculate the number of pages to extend a datafile.
-We extend single-table tablespaces first one extent at a time,
-but 4 at a time for bigger tablespaces. It is not enough to extend always
-by one extent, because we need to add at least one extent to FSP_FREE.
-A single extent descriptor page will track many extents. And the extent
-that uses its extent descriptor page is put onto the FSP_FREE_FRAG list.
-Extents that do not use their extent descriptor page are added to FSP_FREE.
-The physical page size is used to determine how many extents are tracked
-on one extent descriptor page. See xdes_calc_descriptor_page().
-@param[in] page_size page_size of the datafile
-@param[in] size current number of pages in the datafile
-@return number of pages to extend the file. */
-ulint
-fsp_get_pages_to_extend_ibd(
- const page_size_t& page_size,
- ulint size);
-
-/** Calculate the number of physical pages in an extent for this file.
-@param[in] page_size page_size of the datafile
-@return number of pages in an extent for this file. */
-UNIV_INLINE
-ulint
-fsp_get_extent_size_in_pages(const page_size_t& page_size)
-{
- return (FSP_EXTENT_SIZE << srv_page_size_shift) / page_size.physical();
-}
-
/**********************************************************************//**
Reads the space id from the first page of a tablespace.
@return space id, ULINT UNDEFINED if error */
@@ -347,13 +321,15 @@ fsp_header_get_flags(const page_t* page)
}
/** Get the byte offset of encryption information in page 0.
-@param[in] ps page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return byte offset relative to FSP_HEADER_OFFSET */
inline MY_ATTRIBUTE((pure, warn_unused_result))
-ulint
-fsp_header_get_encryption_offset(const page_size_t& ps)
+ulint fsp_header_get_encryption_offset(ulint zip_size)
{
- return XDES_ARR_OFFSET + XDES_SIZE * ps.physical() / FSP_EXTENT_SIZE;
+ return zip_size
+ ? XDES_ARR_OFFSET + XDES_SIZE * zip_size / FSP_EXTENT_SIZE
+ : XDES_ARR_OFFSET + (XDES_SIZE << srv_page_size_shift)
+ / FSP_EXTENT_SIZE;
}
/** Check the encryption key from the first page of a tablespace.
@@ -514,6 +490,7 @@ fsp_reserve_free_extents(
@param[in] offset page number
@param[in] ahi whether we may need to drop the adaptive
hash index
+@param[in] log whether to write MLOG_INIT_FREE_PAGE record
@param[in,out] mtr mini-transaction */
void
fseg_free_page_func(
@@ -523,13 +500,14 @@ fseg_free_page_func(
#ifdef BTR_CUR_HASH_ADAPT
bool ahi,
#endif /* BTR_CUR_HASH_ADAPT */
+ bool log,
mtr_t* mtr);
#ifdef BTR_CUR_HASH_ADAPT
-# define fseg_free_page(header, space, offset, ahi, mtr) \
- fseg_free_page_func(header, space, offset, ahi, mtr)
+# define fseg_free_page(header, space, offset, ahi, log, mtr) \
+ fseg_free_page_func(header, space, offset, ahi, log, mtr)
#else /* BTR_CUR_HASH_ADAPT */
-# define fseg_free_page(header, space, offset, ahi, mtr) \
- fseg_free_page_func(header, space, offset, mtr)
+# define fseg_free_page(header, space, offset, ahi, log, mtr) \
+ fseg_free_page_func(header, space, offset, log, mtr)
#endif /* BTR_CUR_HASH_ADAPT */
/** Determine whether a page is free.
@param[in,out] space tablespace
@@ -623,13 +601,12 @@ fil_block_check_type(
/** Checks if a page address is an extent descriptor page address.
@param[in] page_id page id
-@param[in] page_size page size
-@return TRUE if a descriptor page */
-UNIV_INLINE
-ibool
-fsp_descr_page(
- const page_id_t page_id,
- const page_size_t& page_size);
+@param[in] physical_size page size
+@return whether a descriptor page */
+inline bool fsp_descr_page(const page_id_t page_id, ulint physical_size)
+{
+ return (page_id.page_no() & (physical_size - 1)) == FSP_XDES_OFFSET;
+}
/** Initialize a file page whose prior contents should be ignored.
@param[in,out] block buffer pool block */
@@ -676,7 +653,7 @@ fsp_flags_convert_from_101(ulint flags)
{
DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
return(ULINT_UNDEFINED););
- if (flags == 0) {
+ if (flags == 0 || fil_space_t::full_crc32(flags)) {
return(flags);
}
@@ -771,7 +748,7 @@ fsp_flags_convert_from_101(ulint flags)
flags = ((flags & 0x3f) | ssize << FSP_FLAGS_POS_PAGE_SSIZE
| FSP_FLAGS_GET_PAGE_COMPRESSION_MARIADB101(flags)
<< FSP_FLAGS_POS_PAGE_COMPRESSION);
- ut_ad(fsp_flags_is_valid(flags, false));
+ ut_ad(fil_space_t::is_valid_flags(flags, false));
return(flags);
}
@@ -785,7 +762,7 @@ bool
fsp_flags_match(ulint expected, ulint actual)
{
expected &= ~FSP_FLAGS_MEM_MASK;
- ut_ad(fsp_flags_is_valid(expected, false));
+ ut_ad(fil_space_t::is_valid_flags(expected, false));
if (actual == expected) {
return(true);
@@ -795,16 +772,6 @@ fsp_flags_match(ulint expected, ulint actual)
return(actual == expected);
}
-/** Calculates the descriptor index within a descriptor page.
-@param[in] page_size page size
-@param[in] offset page offset
-@return descriptor index */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_index(
- const page_size_t& page_size,
- ulint offset);
-
/**********************************************************************//**
Gets a descriptor bit of a page.
@return TRUE if free */
@@ -817,15 +784,42 @@ xdes_get_bit(
ulint offset);/*!< in: page offset within extent:
0 ... FSP_EXTENT_SIZE - 1 */
-/** Calculates the page where the descriptor of a page resides.
-@param[in] page_size page size
+/** Determine the descriptor index within a descriptor page.
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] offset page offset
+@return descriptor index */
+inline ulint xdes_calc_descriptor_index(ulint zip_size, ulint offset)
+{
+ return ut_2pow_remainder<ulint>(offset,
+ zip_size ? zip_size : srv_page_size)
+ / FSP_EXTENT_SIZE;
+}
+
+/** Determine the descriptor page number for a page.
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] offset page offset
@return descriptor page offset */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_page(
- const page_size_t& page_size,
- ulint offset);
+inline ulint xdes_calc_descriptor_page(ulint zip_size, ulint offset)
+{
+ compile_time_assert(UNIV_PAGE_SIZE_MAX > XDES_ARR_OFFSET
+ + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX)
+ * XDES_SIZE_MAX);
+ compile_time_assert(UNIV_PAGE_SIZE_MIN > XDES_ARR_OFFSET
+ + (UNIV_PAGE_SIZE_MIN / FSP_EXTENT_SIZE_MIN)
+ * XDES_SIZE_MIN);
+
+ ut_ad(srv_page_size > XDES_ARR_OFFSET
+ + (srv_page_size / FSP_EXTENT_SIZE)
+ * XDES_SIZE);
+ ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET
+ + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE)
+ * XDES_SIZE);
+ ut_ad(!zip_size
+ || zip_size > XDES_ARR_OFFSET
+ + (zip_size / FSP_EXTENT_SIZE) * XDES_SIZE);
+ return ut_2pow_round<ulint>(offset,
+ zip_size ? zip_size : srv_page_size);
+}
#endif /* UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/fsp0fsp.ic b/storage/innobase/include/fsp0fsp.ic
index 9f28aacaff5..31b9d8c5dbe 100644
--- a/storage/innobase/include/fsp0fsp.ic
+++ b/storage/innobase/include/fsp0fsp.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2017, MariaDB Corporation.
+Copyright (c) 2013, 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
@@ -24,37 +24,6 @@ File space management
Created 12/18/1995 Heikki Tuuri
*******************************************************/
-#ifndef UNIV_INNOCHECKSUM
-
-/** Checks if a page address is an extent descriptor page address.
-@param[in] page_id page id
-@param[in] page_size page size
-@return TRUE if a descriptor page */
-UNIV_INLINE
-ibool
-fsp_descr_page(
- const page_id_t page_id,
- const page_size_t& page_size)
-{
- return((page_id.page_no() & (page_size.physical() - 1))
- == FSP_XDES_OFFSET);
-}
-
-/** Calculates the descriptor index within a descriptor page.
-@param[in] page_size page size
-@param[in] offset page offset
-@return descriptor index */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_index(
- const page_size_t& page_size,
- ulint offset)
-{
- return(ut_2pow_remainder(offset, page_size.physical())
- / FSP_EXTENT_SIZE);
-}
-#endif /*!UNIV_INNOCHECKSUM */
-
/**********************************************************************//**
Gets a descriptor bit of a page.
@return TRUE if free */
@@ -75,44 +44,5 @@ xdes_get_bit(
ulint bit_index = index % 8;
ulint byte_index = index / 8;
- return(ut_bit_get_nth(
- mach_read_ulint(descr + XDES_BITMAP + byte_index,
- MLOG_1BYTE),
- bit_index));
-}
-
-#ifndef UNIV_INNOCHECKSUM
-/** Calculates the page where the descriptor of a page resides.
-@param[in] page_size page size
-@param[in] offset page offset
-@return descriptor page offset */
-UNIV_INLINE
-ulint
-xdes_calc_descriptor_page(
- const page_size_t& page_size,
- ulint offset)
-{
- compile_time_assert(UNIV_PAGE_SIZE_MAX > XDES_ARR_OFFSET
- + (UNIV_PAGE_SIZE_MAX / FSP_EXTENT_SIZE_MAX)
- * XDES_SIZE_MAX);
- compile_time_assert(UNIV_PAGE_SIZE_MIN > XDES_ARR_OFFSET
- + (UNIV_PAGE_SIZE_MIN / FSP_EXTENT_SIZE_MIN)
- * XDES_SIZE_MIN);
-
- ut_ad(srv_page_size > XDES_ARR_OFFSET
- + (srv_page_size / FSP_EXTENT_SIZE)
- * XDES_SIZE);
- ut_ad(UNIV_ZIP_SIZE_MIN > XDES_ARR_OFFSET
- + (UNIV_ZIP_SIZE_MIN / FSP_EXTENT_SIZE)
- * XDES_SIZE);
-
-#ifdef UNIV_DEBUG
- if (page_size.is_compressed()) {
- ut_a(page_size.physical() > XDES_ARR_OFFSET
- + (page_size.physical() / FSP_EXTENT_SIZE) * XDES_SIZE);
- }
-#endif /* UNIV_DEBUG */
-
- return(ut_2pow_round(offset, page_size.physical()));
+ return ut_bit_get_nth(descr[XDES_BITMAP + byte_index], bit_index);
}
-#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/fsp0pagecompress.h b/storage/innobase/include/fsp0pagecompress.h
index fc0b907dfa7..27423858435 100644
--- a/storage/innobase/include/fsp0pagecompress.h
+++ b/storage/innobase/include/fsp0pagecompress.h
@@ -27,17 +27,6 @@ Created 11/12/2013 Jan Lindström jan.lindstrom@skysql.com
#ifndef fsp0pagecompress_h
#define fsp0pagecompress_h
-/* Supported page compression methods */
-
-#define PAGE_UNCOMPRESSED 0
-#define PAGE_ZLIB_ALGORITHM 1
-#define PAGE_LZ4_ALGORITHM 2
-#define PAGE_LZO_ALGORITHM 3
-#define PAGE_LZMA_ALGORITHM 4
-#define PAGE_BZIP2_ALGORITHM 5
-#define PAGE_SNAPPY_ALGORITHM 6
-#define PAGE_ALGORITHM_LAST PAGE_SNAPPY_ALGORITHM
-
/**********************************************************************//**
Reads the page compression level from the first page of a tablespace.
@return page compression level, or 0 if uncompressed */
diff --git a/storage/innobase/include/fsp0space.h b/storage/innobase/include/fsp0space.h
index 5bd70e4f80d..632c65e14cc 100644
--- a/storage/innobase/include/fsp0space.h
+++ b/storage/innobase/include/fsp0space.h
@@ -127,7 +127,7 @@ public:
@param[in] fsp_flags tablespace flags */
void set_flags(ulint fsp_flags)
{
- ut_ad(fsp_flags_is_valid(fsp_flags, false));
+ ut_ad(fil_space_t::is_valid_flags(fsp_flags, false));
m_flags = fsp_flags;
}
diff --git a/storage/innobase/include/fsp0sysspace.h b/storage/innobase/include/fsp0sysspace.h
index d3a79ec23a9..bcb8dd5e5e9 100644
--- a/storage/innobase/include/fsp0sysspace.h
+++ b/storage/innobase/include/fsp0sysspace.h
@@ -49,7 +49,7 @@ public:
/* No op */
}
- ~SysTablespace()
+ ~SysTablespace() override
{
shutdown();
}
diff --git a/storage/innobase/include/fsp0types.h b/storage/innobase/include/fsp0types.h
index 5c77b62723a..69c5346a4f9 100644
--- a/storage/innobase/include/fsp0types.h
+++ b/storage/innobase/include/fsp0types.h
@@ -27,10 +27,6 @@ Created May 26, 2009 Vasil Dimov
#ifndef fsp0types_h
#define fsp0types_h
-#include "univ.i"
-
-#ifndef UNIV_INNOCHECKSUM
-
/** The fil_space_t::id of the redo log. All persistent tablespaces
have a smaller fil_space_t::id. */
#define SRV_LOG_SPACE_FIRST_ID 0xFFFFFFF0U
@@ -39,6 +35,16 @@ have a smaller fil_space_t::id. */
#include "ut0byte.h"
+/* Possible values of innodb_compression_algorithm */
+#define PAGE_UNCOMPRESSED 0
+#define PAGE_ZLIB_ALGORITHM 1
+#define PAGE_LZ4_ALGORITHM 2
+#define PAGE_LZO_ALGORITHM 3
+#define PAGE_LZMA_ALGORITHM 4
+#define PAGE_BZIP2_ALGORITHM 5
+#define PAGE_SNAPPY_ALGORITHM 6
+#define PAGE_ALGORITHM_LAST PAGE_SNAPPY_ALGORITHM
+
/** @name Flags for inserting records in order
If records are inserted in order, there are the following
flags to tell this (their type is made byte for the compiler
@@ -50,7 +56,6 @@ fseg_alloc_free_page) */
#define FSP_NO_DIR ((byte)113) /*!< no order */
/* @} */
-#endif /* !UNIV_INNOCHECKSUM */
/** File space extent size in pages
page size | file space extent size
----------+-----------------------
@@ -73,7 +78,6 @@ page size | file space extent size
offset */
#define FSEG_PAGE_DATA FIL_PAGE_DATA
-#ifndef UNIV_INNOCHECKSUM
/** @name File segment header
The file segment header points to the inode describing the file segment. */
/* @{ */
@@ -88,6 +92,7 @@ typedef byte fseg_header_t;
header, in bytes */
/* @} */
+#ifndef UNIV_INNOCHECKSUM
#ifdef UNIV_DEBUG
struct mtr_t;
@@ -224,6 +229,15 @@ to ROW_FORMAT=REDUNDANT and ROW_FORMAT=COMPACT. */
/** A mask of all the known/used bits in FSP_SPACE_FLAGS */
#define FSP_FLAGS_MASK (~(~0U << FSP_FLAGS_WIDTH))
+/** Number of flag bits used to indicate the tablespace page size */
+#define FSP_FLAGS_FCRC32_WIDTH_PAGE_SSIZE 4
+
+/** Marker to indicate whether tablespace is in full checksum format. */
+#define FSP_FLAGS_FCRC32_WIDTH_MARKER 1
+
+/** Stores the compressed algo for full checksum format. */
+#define FSP_FLAGS_FCRC32_WIDTH_COMPRESSED_ALGO 3
+
/* FSP_SPACE_FLAGS position and name in MySQL 5.6/MariaDB 10.0 or older
and MariaDB 10.1.20 or older MariaDB 10.1 and in MariaDB 10.1.21
or newer.
@@ -286,6 +300,19 @@ these are only used in MySQL 5.7 and used for compatibility. */
#define FSP_FLAGS_POS_PAGE_COMPRESSION (FSP_FLAGS_POS_RESERVED \
+ FSP_FLAGS_WIDTH_RESERVED)
+/** Zero relative shift position of the PAGE_SIZE field
+in full crc32 format */
+#define FSP_FLAGS_FCRC32_POS_PAGE_SSIZE 0
+
+/** Zero relative shift position of the MARKER field in full crc32 format. */
+#define FSP_FLAGS_FCRC32_POS_MARKER (FSP_FLAGS_FCRC32_POS_PAGE_SSIZE \
+ + FSP_FLAGS_FCRC32_WIDTH_PAGE_SSIZE)
+
+/** Zero relative shift position of the compressed algorithm stored
+in full crc32 format. */
+#define FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO (FSP_FLAGS_FCRC32_POS_MARKER \
+ + FSP_FLAGS_FCRC32_WIDTH_MARKER)
+
/** Bit mask of the POST_ANTELOPE field */
#define FSP_FLAGS_MASK_POST_ANTELOPE \
((~(~0U << FSP_FLAGS_WIDTH_POST_ANTELOPE)) \
@@ -315,6 +342,21 @@ these are only used in MySQL 5.7 and used for compatibility. */
#define FSP_FLAGS_MASK_MEM_COMPRESSION_LEVEL \
(15U << FSP_FLAGS_MEM_COMPRESSION_LEVEL)
+/** Bit mask of the PAGE_SIZE field in full crc32 format */
+#define FSP_FLAGS_FCRC32_MASK_PAGE_SSIZE \
+ ((~(~0U << FSP_FLAGS_FCRC32_WIDTH_PAGE_SSIZE)) \
+ << FSP_FLAGS_FCRC32_POS_PAGE_SSIZE)
+
+/** Bit mask of the MARKER field in full crc32 format */
+#define FSP_FLAGS_FCRC32_MASK_MARKER \
+ ((~(~0U << FSP_FLAGS_FCRC32_WIDTH_MARKER)) \
+ << FSP_FLAGS_FCRC32_POS_MARKER)
+
+/** Bit mask of the COMPRESSED ALGO field in full crc32 format */
+#define FSP_FLAGS_FCRC32_MASK_COMPRESSED_ALGO \
+ ((~(~0U << FSP_FLAGS_FCRC32_WIDTH_COMPRESSED_ALGO)) \
+ << FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO)
+
/** Return the value of the POST_ANTELOPE field */
#define FSP_FLAGS_GET_POST_ANTELOPE(flags) \
((flags & FSP_FLAGS_MASK_POST_ANTELOPE) \
@@ -339,10 +381,14 @@ these are only used in MySQL 5.7 and used for compatibility. */
#define FSP_FLAGS_HAS_PAGE_COMPRESSION(flags) \
((flags & FSP_FLAGS_MASK_PAGE_COMPRESSION) \
>> FSP_FLAGS_POS_PAGE_COMPRESSION)
-
-/** Return the contents of the UNUSED bits */
-#define FSP_FLAGS_GET_UNUSED(flags) \
- (flags >> FSP_FLAGS_POS_UNUSED)
+/** @return the PAGE_SSIZE flags in full crc32 format */
+#define FSP_FLAGS_FCRC32_GET_PAGE_SSIZE(flags) \
+ ((flags & FSP_FLAGS_FCRC32_MASK_PAGE_SSIZE) \
+ >> FSP_FLAGS_FCRC32_POS_PAGE_SSIZE)
+/** @return the COMPRESSED_ALGO flags in full crc32 format */
+#define FSP_FLAGS_FCRC32_GET_COMPRESSED_ALGO(flags) \
+ ((flags & FSP_FLAGS_FCRC32_MASK_COMPRESSED_ALGO) \
+ >> FSP_FLAGS_FCRC32_POS_COMPRESSED_ALGO)
/** @return the value of the DATA_DIR field */
#define FSP_FLAGS_HAS_DATA_DIR(flags) \
@@ -354,67 +400,4 @@ these are only used in MySQL 5.7 and used for compatibility. */
/* @} */
-/** Validate the tablespace flags, which are stored in the
-tablespace header at offset FSP_SPACE_FLAGS.
-@param[in] flags the contents of FSP_SPACE_FLAGS
-@param[in] is_ibd whether this is an .ibd file (not system tablespace)
-@return whether the flags are correct (not in the buggy 10.1) format */
-MY_ATTRIBUTE((warn_unused_result, const))
-UNIV_INLINE
-bool
-fsp_flags_is_valid(ulint flags, bool is_ibd)
-{
- DBUG_EXECUTE_IF("fsp_flags_is_valid_failure",
- return(false););
- if (flags == 0) {
- return(true);
- }
- if (flags & ~FSP_FLAGS_MASK) {
- return(false);
- }
- if ((flags & (FSP_FLAGS_MASK_POST_ANTELOPE | FSP_FLAGS_MASK_ATOMIC_BLOBS))
- == FSP_FLAGS_MASK_ATOMIC_BLOBS) {
- /* If the "atomic blobs" flag (indicating
- ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED) flag
- is set, then the "post Antelope" (ROW_FORMAT!=REDUNDANT) flag
- must also be set. */
- return(false);
- }
- /* Bits 10..14 should be 0b0000d where d is the DATA_DIR flag
- of MySQL 5.6 and MariaDB 10.0, which we ignore.
- In the buggy FSP_SPACE_FLAGS written by MariaDB 10.1.0 to 10.1.20,
- bits 10..14 would be nonzero 0bsssaa where sss is
- nonzero PAGE_SSIZE (3, 4, 6, or 7)
- and aa is ATOMIC_WRITES (not 0b11). */
- if (FSP_FLAGS_GET_RESERVED(flags) & ~1U) {
- return(false);
- }
-
- const ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(flags);
- if (ssize == 1 || ssize == 2 || ssize == 5 || ssize & 8) {
- /* the page_size is not between 4k and 64k;
- 16k should be encoded as 0, not 5 */
- return(false);
- }
- const ulint zssize = FSP_FLAGS_GET_ZIP_SSIZE(flags);
- if (zssize == 0) {
- /* not ROW_FORMAT=COMPRESSED */
- } else if (zssize > (ssize ? ssize : 5)) {
- /* invalid KEY_BLOCK_SIZE */
- return(false);
- } else if (~flags & (FSP_FLAGS_MASK_POST_ANTELOPE
- | FSP_FLAGS_MASK_ATOMIC_BLOBS)) {
- /* both these flags should be set for
- ROW_FORMAT=COMPRESSED */
- return(false);
- }
-
- /* The flags do look valid. But, avoid misinterpreting
- buggy MariaDB 10.1 format flags for
- PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL={0,2,3}
- as valid-looking PAGE_SSIZE if this is known to be
- an .ibd file and we are using the default innodb_page_size=16k. */
- return(ssize == 0 || !is_ibd || srv_page_size != UNIV_PAGE_SIZE_ORIG);
-}
-
#endif /* fsp0types_h */
diff --git a/storage/innobase/include/fts0fts.h b/storage/innobase/include/fts0fts.h
index 7924c9025cd..dde7ad99fe7 100644
--- a/storage/innobase/include/fts0fts.h
+++ b/storage/innobase/include/fts0fts.h
@@ -323,7 +323,7 @@ public:
/** Whether the ADDED table record sync-ed after
crash recovery; protected by bg_threads_mutex */
unsigned added_synced:1;
- /** Whether the table holds dict_sys->mutex;
+ /** Whether the table holds dict_sys.mutex;
protected by bg_threads_mutex */
unsigned dict_locked:1;
@@ -384,9 +384,9 @@ extern bool fts_need_sync;
#define fts_que_graph_free(graph) \
do { \
- mutex_enter(&dict_sys->mutex); \
+ mutex_enter(&dict_sys.mutex); \
que_graph_free(graph); \
- mutex_exit(&dict_sys->mutex); \
+ mutex_exit(&dict_sys.mutex); \
} while (0)
/******************************************************************//**
@@ -584,17 +584,15 @@ fts_get_doc_id_from_row(
want to extract.*/
/** Extract the doc id from the record that belongs to index.
-@param[in] table table
-@param[in] rec record contains FTS_DOC_ID
+@param[in] rec record containing FTS_DOC_ID
@param[in] index index of rec
-@param[in] heap heap memory
+@param[in] offsets rec_get_offsets(rec,index)
@return doc id that was extracted from rec */
doc_id_t
fts_get_doc_id_from_rec(
- dict_table_t* table,
- const rec_t* rec,
- const dict_index_t* index,
- mem_heap_t* heap);
+ const rec_t* rec,
+ const dict_index_t* index,
+ const offset_t* offsets);
/** Add new fts doc id to the update vector.
@param[in] table the table that contains the FTS index.
@@ -751,7 +749,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
dberr_t fts_sync_table(dict_table_t* table, bool wait = true);
/****************************************************************//**
-Free the query graph but check whether dict_sys->mutex is already
+Free the query graph but check whether dict_sys.mutex is already
held */
void
fts_que_graph_free_check_lock(
diff --git a/storage/innobase/include/fts0priv.h b/storage/innobase/include/fts0priv.h
index 9a767378103..018e801409b 100644
--- a/storage/innobase/include/fts0priv.h
+++ b/storage/innobase/include/fts0priv.h
@@ -135,7 +135,7 @@ fts_eval_sql(
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
@param[out] table_name a name up to MAX_FULL_NAME_LEN
-@param[in] dict_locked whether dict_sys->mutex is being held */
+@param[in] dict_locked whether dict_sys.mutex is being held */
void fts_get_table_name(const fts_table_t* fts_table, char* table_name,
bool dict_locked = false)
MY_ATTRIBUTE((nonnull));
@@ -490,7 +490,7 @@ fts_get_table_id(
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Construct the name of an internal FTS table for the given table.
@param[in] fts_table metadata on fulltext-indexed table
-@param[in] dict_locked whether dict_sys->mutex is being held
+@param[in] dict_locked whether dict_sys.mutex is being held
@return the prefix, must be freed with ut_free() */
char* fts_get_table_name_prefix(const fts_table_t* fts_table)
MY_ATTRIBUTE((nonnull, malloc, warn_unused_result));
diff --git a/storage/innobase/include/fut0fut.h b/storage/innobase/include/fut0fut.h
index 3c3f118bd68..a52fc256efa 100644
--- a/storage/innobase/include/fut0fut.h
+++ b/storage/innobase/include/fut0fut.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 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
@@ -27,12 +28,11 @@ Created 12/13/1995 Heikki Tuuri
#ifndef fut0fut_h
#define fut0fut_h
-#include "fil0fil.h"
#include "mtr0mtr.h"
/** Gets a pointer to a file address and latches the page.
@param[in] space space id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] addr file address
@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH
@param[out] ptr_block file page
@@ -43,13 +43,32 @@ UNIV_INLINE
byte*
fut_get_ptr(
ulint space,
- const page_size_t& page_size,
+ ulint zip_size,
fil_addr_t addr,
rw_lock_type_t rw_latch,
mtr_t* mtr,
buf_block_t** ptr_block = NULL)
- MY_ATTRIBUTE((warn_unused_result));
+{
+ buf_block_t* block;
+ byte* ptr = NULL;
-#include "fut0fut.ic"
+ ut_ad(addr.boffset < srv_page_size);
+ ut_ad((rw_latch == RW_S_LATCH)
+ || (rw_latch == RW_X_LATCH)
+ || (rw_latch == RW_SX_LATCH));
+
+ block = buf_page_get(page_id_t(space, addr.page), zip_size,
+ rw_latch, mtr);
+
+ ptr = buf_block_get_frame(block) + addr.boffset;
+
+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
+
+ if (ptr_block != NULL) {
+ *ptr_block = block;
+ }
+
+ return(ptr);
+}
#endif /* fut0fut_h */
diff --git a/storage/innobase/include/fut0fut.ic b/storage/innobase/include/fut0fut.ic
deleted file mode 100644
index b5c1e15e059..00000000000
--- a/storage/innobase/include/fut0fut.ic
+++ /dev/null
@@ -1,68 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/******************************************************************//**
-@file include/fut0fut.ic
-File-based utilities
-
-Created 12/13/1995 Heikki Tuuri
-***********************************************************************/
-
-#include "sync0rw.h"
-#include "buf0buf.h"
-
-/** Gets a pointer to a file address and latches the page.
-@param[in] space space id
-@param[in] page_size page size
-@param[in] addr file address
-@param[in] rw_latch RW_S_LATCH, RW_X_LATCH, RW_SX_LATCH
-@param[in,out] mtr mini-transaction
-@param[out] ptr_block file page
-@return pointer to a byte in (*ptr_block)->frame; the *ptr_block is
-bufferfixed and latched */
-UNIV_INLINE
-byte*
-fut_get_ptr(
- ulint space,
- const page_size_t& page_size,
- fil_addr_t addr,
- rw_lock_type_t rw_latch,
- mtr_t* mtr,
- buf_block_t** ptr_block)
-{
- buf_block_t* block;
- byte* ptr = NULL;
-
- ut_ad(addr.boffset < srv_page_size);
- ut_ad((rw_latch == RW_S_LATCH)
- || (rw_latch == RW_X_LATCH)
- || (rw_latch == RW_SX_LATCH));
-
- block = buf_page_get(page_id_t(space, addr.page), page_size,
- rw_latch, mtr);
-
- ptr = buf_block_get_frame(block) + addr.boffset;
-
- buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
-
- if (ptr_block != NULL) {
- *ptr_block = block;
- }
-
- return(ptr);
-}
diff --git a/storage/innobase/include/fut0lst.h b/storage/innobase/include/fut0lst.h
index 187b673d2fd..9fa928eda23 100644
--- a/storage/innobase/include/fut0lst.h
+++ b/storage/innobase/include/fut0lst.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2018, 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
@@ -26,11 +27,11 @@ Created 11/28/1995 Heikki Tuuri
#ifndef fut0lst_h
#define fut0lst_h
-#ifndef UNIV_INNOCHECKSUM
-
-#include "fil0fil.h"
-#include "mtr0mtr.h"
-
+#ifdef UNIV_INNOCHECKSUM
+# include "fil0fil.h"
+#else
+#include "fut0fut.h"
+#include "mtr0log.h"
/* The C 'types' of base node and list node: these should be used to
write self-documenting code. Of course, the sizeof macro cannot be
@@ -39,14 +40,59 @@ applied to these types! */
typedef byte flst_base_node_t;
typedef byte flst_node_t;
-/* The physical size of a list base node in bytes */
-#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE)
#endif /* !UNIV_INNOCHECKSUM */
+/* The physical size of a list base node in bytes */
+#define FLST_BASE_NODE_SIZE (4 + 2 * FIL_ADDR_SIZE)
/* The physical size of a list node in bytes */
#define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE)
#ifndef UNIV_INNOCHECKSUM
+/* We define the field offsets of a node for the list */
+#define FLST_PREV 0 /* 6-byte address of the previous list element;
+ the page part of address is FIL_NULL, if no
+ previous element */
+#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next
+ list element; the page part of address
+ is FIL_NULL, if no next element */
+
+/* We define the field offsets of a base node for the list */
+#define FLST_LEN 0 /* 32-bit list length field */
+#define FLST_FIRST 4 /* 6-byte address of the first element
+ of the list; undefined if empty list */
+#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the
+ last element of the list; undefined
+ if empty list */
+
+/** Initialize a zero-initialized list base node.
+@param[in,out] block file page
+@param[in] ofs byte offset of the list base node
+@param[in,out] mtr mini-transaction */
+inline void flst_init(buf_block_t* block, uint16_t ofs, mtr_t* mtr)
+{
+ ut_ad(0 == mach_read_from_2(FLST_LEN + ofs + block->frame));
+ ut_ad(0 == mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs
+ + block->frame));
+ ut_ad(0 == mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs
+ + block->frame));
+ compile_time_assert(FIL_NULL == 0xffU * 0x1010101U);
+ mlog_memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
+ mlog_memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
+}
+
+/** Write a null file address.
+@param[in,out] faddr file address to be zeroed otu
+@param[in,out] mtr mini-transaction */
+inline void flst_zero_addr(fil_faddr_t* faddr, mtr_t* mtr)
+{
+ if (mach_read_from_4(faddr + FIL_ADDR_PAGE) != FIL_NULL) {
+ mlog_memset(faddr + FIL_ADDR_PAGE, 4, 0xff, mtr);
+ }
+ if (mach_read_from_2(faddr + FIL_ADDR_BYTE)) {
+ mlog_write_ulint(faddr + FIL_ADDR_BYTE, 0, MLOG_2BYTES, mtr);
+ }
+}
+
/********************************************************************//**
Initializes a list base node. */
UNIV_INLINE
@@ -83,7 +129,7 @@ flst_remove(
@param[in] base base node
@return length */
UNIV_INLINE
-ulint
+uint32_t
flst_get_len(
const flst_base_node_t* base);
/********************************************************************//**
diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic
index 00bb3fe8e9c..ec4181b2c93 100644
--- a/storage/innobase/include/fut0lst.ic
+++ b/storage/innobase/include/fut0lst.ic
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2014, 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
@@ -23,26 +24,8 @@ File-based list utilities
Created 11/28/1995 Heikki Tuuri
***********************************************************************/
-#include "fut0fut.h"
-#include "mtr0log.h"
#include "buf0buf.h"
-/* We define the field offsets of a node for the list */
-#define FLST_PREV 0 /* 6-byte address of the previous list element;
- the page part of address is FIL_NULL, if no
- previous element */
-#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next
- list element; the page part of address
- is FIL_NULL, if no next element */
-
-/* We define the field offsets of a base node for the list */
-#define FLST_LEN 0 /* 32-bit list length field */
-#define FLST_FIRST 4 /* 6-byte address of the first element
- of the list; undefined if empty list */
-#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the
- last element of the list; undefined
- if empty list */
-
/********************************************************************//**
Writes a file address. */
UNIV_INLINE
@@ -79,9 +62,8 @@ flst_read_addr(
ut_ad(faddr && mtr);
- addr.page = mtr_read_ulint(faddr + FIL_ADDR_PAGE, MLOG_4BYTES, mtr);
- addr.boffset = mtr_read_ulint(faddr + FIL_ADDR_BYTE, MLOG_2BYTES,
- mtr);
+ addr.page = mach_read_from_4(faddr + FIL_ADDR_PAGE);
+ addr.boffset = mach_read_from_2(faddr + FIL_ADDR_BYTE);
ut_a(addr.page == FIL_NULL || addr.boffset >= FIL_PAGE_DATA);
ut_a(ut_align_offset(faddr, srv_page_size) >= FIL_PAGE_DATA);
return(addr);
@@ -100,16 +82,18 @@ flst_init(
MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
- mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
- flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
- flst_write_addr(base + FLST_LAST, fil_addr_null, mtr);
+ if (mach_read_from_4(base + FLST_LEN)) {
+ mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
+ }
+ flst_zero_addr(base + FLST_FIRST, mtr);
+ flst_zero_addr(base + FLST_LAST, mtr);
}
/** Get the length of a list.
@param[in] base base node
@return length */
UNIV_INLINE
-ulint
+uint32_t
flst_get_len(
const flst_base_node_t* base)
{
diff --git a/storage/innobase/include/gis0type.h b/storage/innobase/include/gis0type.h
index ee350ea56ce..9d8dc841448 100644
--- a/storage/innobase/include/gis0type.h
+++ b/storage/innobase/include/gis0type.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, MariaDB Corporation.
+Copyright (c) 2018, 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
@@ -35,7 +35,7 @@ Created 2013/03/27 Jimmy Yang
#include "gis0geo.h"
#include <vector>
-#include <list>
+#include <forward_list>
/* Node Sequence Number. Only updated when page splits */
typedef ib_uint32_t node_seq_t;
@@ -133,15 +133,14 @@ typedef struct rtr_info{
/*!< current search mode */
} rtr_info_t;
-typedef std::list<rtr_info_t*, ut_allocator<rtr_info_t*> > rtr_info_active;
-
-/* Tracking structure for all onoging search for an index */
-typedef struct rtr_info_track {
- rtr_info_active* rtr_active; /*!< Active search info */
- ib_mutex_t rtr_active_mutex;
+/* Tracking structure for all ongoing search for an index */
+struct rtr_info_track_t {
+ /** Active search info */
+ std::forward_list<rtr_info_t*, ut_allocator<rtr_info_t*> > rtr_active;
+ ib_mutex_t rtr_active_mutex;
/*!< mutex to protect
rtr_active */
-} rtr_info_track_t;
+};
/* Node Sequence Number and mutex protects it. */
typedef struct rtree_ssn {
diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h
index e3eb02d2fbf..cd7f5355818 100644
--- a/storage/innobase/include/ha_prototypes.h
+++ b/storage/innobase/include/ha_prototypes.h
@@ -531,18 +531,6 @@ normalize_table_name_c_low(
const char* name, /*!< in: table name string */
ibool set_lower_case); /*!< in: TRUE if we want to set
name to lower case */
-/*************************************************************//**
-InnoDB index push-down condition check defined in ha_innodb.cc
-@return ICP_NO_MATCH, ICP_MATCH, or ICP_OUT_OF_RANGE */
-
-#include <my_compare.h>
-
-ICP_RESULT
-innobase_index_cond(
-/*================*/
- void* file) /*!< in/out: pointer to ha_innobase */
- MY_ATTRIBUTE((warn_unused_result));
-
/** Update the system variable with the given value of the InnoDB
buffer pool size.
@param[in] buf_pool_size given value of buffer pool size.*/
diff --git a/storage/innobase/include/ib0mutex.h b/storage/innobase/include/ib0mutex.h
index e496c65e46a..ce0e911dbb4 100644
--- a/storage/innobase/include/ib0mutex.h
+++ b/storage/innobase/include/ib0mutex.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2019, MariaDB Corporation.
+Copyright (c) 2017, 2020, 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
@@ -29,13 +29,12 @@ Created 2013-03-26 Sunny Bains.
#ifndef ib0mutex_h
#define ib0mutex_h
-#include "my_atomic.h"
#include "my_cpu.h"
#include "os0event.h"
#include "sync0arr.h"
/** OS mutex for tracking lock/unlock for debugging */
-template <template <typename> class Policy = NoPolicy>
+template <template <typename> class Policy>
struct OSTrackMutex {
typedef Policy<OSTrackMutex> MutexPolicy;
@@ -152,7 +151,7 @@ private:
#include <sys/syscall.h>
/** Mutex implementation that used the Linux futex. */
-template <template <typename> class Policy = NoPolicy>
+template <template <typename> class Policy>
struct TTASFutexMutex {
typedef Policy<TTASFutexMutex> MutexPolicy;
@@ -167,21 +166,24 @@ struct TTASFutexMutex {
~TTASFutexMutex()
{
- ut_a(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_UNLOCKED);
}
/** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised. */
void init(latch_id_t, const char*, uint32_t) UNIV_NOTHROW
{
- ut_a(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_UNLOCKED);
}
/** Destroy the mutex. */
void destroy() UNIV_NOTHROW
{
/* The destructor can be called at shutdown. */
- ut_a(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_UNLOCKED);
}
/** Acquire the mutex.
@@ -202,9 +204,8 @@ struct TTASFutexMutex {
}
for (n_waits= 0;; n_waits++) {
- if (my_atomic_fas32_explicit(&m_lock_word,
- MUTEX_STATE_WAITERS,
- MY_MEMORY_ORDER_ACQUIRE)
+ if (m_lock_word.exchange(MUTEX_STATE_WAITERS,
+ std::memory_order_acquire)
== MUTEX_STATE_UNLOCKED) {
break;
}
@@ -220,9 +221,8 @@ struct TTASFutexMutex {
/** Release the mutex. */
void exit() UNIV_NOTHROW
{
- if (my_atomic_fas32_explicit(&m_lock_word,
- MUTEX_STATE_UNLOCKED,
- MY_MEMORY_ORDER_RELEASE)
+ if (m_lock_word.exchange(MUTEX_STATE_UNLOCKED,
+ std::memory_order_release)
== MUTEX_STATE_WAITERS) {
syscall(SYS_futex, &m_lock_word, FUTEX_WAKE_PRIVATE,
1, 0, 0, 0);
@@ -234,10 +234,11 @@ struct TTASFutexMutex {
bool try_lock() UNIV_NOTHROW
{
int32 oldval = MUTEX_STATE_UNLOCKED;
- return(my_atomic_cas32_strong_explicit(&m_lock_word, &oldval,
- MUTEX_STATE_LOCKED,
- MY_MEMORY_ORDER_ACQUIRE,
- MY_MEMORY_ORDER_RELAXED));
+ return m_lock_word.compare_exchange_strong(
+ oldval,
+ MUTEX_STATE_LOCKED,
+ std::memory_order_acquire,
+ std::memory_order_relaxed);
}
/** @return non-const version of the policy */
@@ -257,12 +258,12 @@ private:
/** lock_word is the target of the atomic test-and-set instruction
when atomic operations are enabled. */
- int32 m_lock_word;
+ std::atomic<int32> m_lock_word;
};
#endif /* HAVE_IB_LINUX_FUTEX */
-template <template <typename> class Policy = NoPolicy>
+template <template <typename> class Policy>
struct TTASMutex {
typedef Policy<TTASMutex> MutexPolicy;
@@ -277,40 +278,45 @@ struct TTASMutex {
~TTASMutex()
{
- ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_UNLOCKED);
}
/** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised. */
void init(latch_id_t) UNIV_NOTHROW
{
- ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_UNLOCKED);
}
/** Destroy the mutex. */
void destroy() UNIV_NOTHROW
{
/* The destructor can be called at shutdown. */
- ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_UNLOCKED);
}
/** Try and lock the mutex.
@return true on success */
bool try_lock() UNIV_NOTHROW
{
- int32 oldval = MUTEX_STATE_UNLOCKED;
- return(my_atomic_cas32_strong_explicit(&m_lock_word, &oldval,
- MUTEX_STATE_LOCKED,
- MY_MEMORY_ORDER_ACQUIRE,
- MY_MEMORY_ORDER_RELAXED));
+ uint32_t oldval = MUTEX_STATE_UNLOCKED;
+ return m_lock_word.compare_exchange_strong(
+ oldval,
+ MUTEX_STATE_LOCKED,
+ std::memory_order_acquire,
+ std::memory_order_relaxed);
}
/** Release the mutex. */
void exit() UNIV_NOTHROW
{
- ut_ad(m_lock_word == MUTEX_STATE_LOCKED);
- my_atomic_store32_explicit(&m_lock_word, MUTEX_STATE_UNLOCKED,
- MY_MEMORY_ORDER_RELEASE);
+ ut_ad(m_lock_word.load(std::memory_order_relaxed)
+ == MUTEX_STATE_LOCKED);
+ m_lock_word.store(MUTEX_STATE_UNLOCKED,
+ std::memory_order_release);
}
/** Acquire the mutex.
@@ -353,12 +359,11 @@ private:
/** Policy data */
MutexPolicy m_policy;
- /** lock_word is the target of the atomic test-and-set instruction
- when atomic operations are enabled. */
- int32 m_lock_word;
+ /** mutex state */
+ std::atomic<uint32_t> m_lock_word;
};
-template <template <typename> class Policy = NoPolicy>
+template <template <typename> class Policy>
struct TTASEventMutex {
typedef Policy<TTASEventMutex> MutexPolicy;
@@ -376,7 +381,7 @@ struct TTASEventMutex {
~TTASEventMutex()
UNIV_NOTHROW
{
- ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(state() == MUTEX_STATE_UNLOCKED);
}
/** Called when the mutex is "created". Note: Not from the constructor
@@ -385,7 +390,7 @@ struct TTASEventMutex {
void init(latch_id_t id, const char*, uint32_t) UNIV_NOTHROW
{
ut_a(m_event == 0);
- ut_a(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(state() == MUTEX_STATE_UNLOCKED);
m_event = os_event_create(sync_latch_get_name(id));
}
@@ -396,7 +401,7 @@ struct TTASEventMutex {
void destroy()
UNIV_NOTHROW
{
- ut_ad(m_lock_word == MUTEX_STATE_UNLOCKED);
+ ut_ad(state() == MUTEX_STATE_UNLOCKED);
/* We have to free the event before InnoDB shuts down. */
os_event_destroy(m_event);
@@ -408,20 +413,20 @@ struct TTASEventMutex {
bool try_lock()
UNIV_NOTHROW
{
- int32 oldval = MUTEX_STATE_UNLOCKED;
- return(my_atomic_cas32_strong_explicit(&m_lock_word, &oldval,
- MUTEX_STATE_LOCKED,
- MY_MEMORY_ORDER_ACQUIRE,
- MY_MEMORY_ORDER_RELAXED));
+ uint32_t oldval = MUTEX_STATE_UNLOCKED;
+ return m_lock_word.compare_exchange_strong(
+ oldval,
+ MUTEX_STATE_LOCKED,
+ std::memory_order_acquire,
+ std::memory_order_relaxed);
}
/** Release the mutex. */
void exit()
UNIV_NOTHROW
{
- if (my_atomic_fas32_explicit(&m_lock_word,
- MUTEX_STATE_UNLOCKED,
- MY_MEMORY_ORDER_RELEASE)
+ if (m_lock_word.exchange(MUTEX_STATE_UNLOCKED,
+ std::memory_order_release)
== MUTEX_STATE_WAITERS) {
os_event_set(m_event);
sync_array_object_signalled();
@@ -459,11 +464,12 @@ struct TTASEventMutex {
: SYNC_MUTEX,
filename, line, &cell);
- int32 oldval = MUTEX_STATE_LOCKED;
- my_atomic_cas32_strong_explicit(&m_lock_word, &oldval,
- MUTEX_STATE_WAITERS,
- MY_MEMORY_ORDER_RELAXED,
- MY_MEMORY_ORDER_RELAXED);
+ uint32_t oldval = MUTEX_STATE_LOCKED;
+ m_lock_word.compare_exchange_strong(
+ oldval,
+ MUTEX_STATE_WAITERS,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
if (oldval == MUTEX_STATE_UNLOCKED) {
sync_array_free_cell(sync_arr, cell);
@@ -482,9 +488,7 @@ struct TTASEventMutex {
int32 state() const
UNIV_NOTHROW
{
- return(my_atomic_load32_explicit(const_cast<int32*>
- (&m_lock_word),
- MY_MEMORY_ORDER_RELAXED));
+ return m_lock_word.load(std::memory_order_relaxed);
}
/** The event that the mutex will wait in sync0arr.cc
@@ -514,9 +518,8 @@ private:
TTASEventMutex(const TTASEventMutex&);
TTASEventMutex& operator=(const TTASEventMutex&);
- /** lock_word is the target of the atomic test-and-set instruction
- when atomic operations are enabled. */
- int32 m_lock_word;
+ /** mutex state */
+ std::atomic<uint32_t> m_lock_word;
/** Used by sync0arr.cc for the wait queue */
os_event_t m_event;
@@ -530,7 +533,6 @@ with the Performance Schema instrumentation. */
template <typename MutexImpl>
struct PolicyMutex
{
- typedef MutexImpl MutexType;
typedef typename MutexImpl::MutexPolicy Policy;
PolicyMutex() UNIV_NOTHROW : m_impl()
@@ -561,7 +563,7 @@ struct PolicyMutex
pfs_exit();
#endif /* UNIV_PFS_MUTEX */
- policy().release(m_impl);
+ ut_d(policy().context.release(m_impl));
m_impl.exit();
}
@@ -587,11 +589,11 @@ struct PolicyMutex
locker = pfs_begin_lock(&state, name, line);
#endif /* UNIV_PFS_MUTEX */
- policy().enter(m_impl, name, line);
+ ut_d(policy().context.enter(m_impl, name, line));
m_impl.enter(n_spins, n_delay, name, line);
- policy().locked(m_impl, name, line);
+ ut_d(policy().context.locked(m_impl, name, line));
#ifdef UNIV_PFS_MUTEX
pfs_end(locker, 0);
#endif /* UNIV_PFS_MUTEX */
@@ -620,9 +622,9 @@ struct PolicyMutex
if (ret == 0) {
- policy().enter(m_impl, name, line);
+ ut_d(policy().context.enter(m_impl, name, line));
- policy().locked(m_impl, name, line);
+ ut_d(policy().context.locked(m_impl, name, line));
}
#ifdef UNIV_PFS_MUTEX
@@ -636,7 +638,7 @@ struct PolicyMutex
/** @return true if the thread owns the mutex. */
bool is_owned() const UNIV_NOTHROW
{
- return(policy().is_owned());
+ return(policy().context.is_owned());
}
#endif /* UNIV_DEBUG */
@@ -658,6 +660,7 @@ struct PolicyMutex
m_impl.init(id, filename, line);
policy().init(m_impl, id, filename, line);
+ ut_d(policy().context.init(id));
}
/** Free resources (if any) */
@@ -668,6 +671,7 @@ struct PolicyMutex
#endif /* UNIV_PFS_MUTEX */
m_impl.destroy();
policy().destroy();
+ ut_d(policy().context.destroy());
}
/** Required for os_event_t */
diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h
index 00fe1d3b02a..02d38069d94 100644
--- a/storage/innobase/include/ibuf0ibuf.h
+++ b/storage/innobase/include/ibuf0ibuf.h
@@ -119,13 +119,6 @@ ibuf_mtr_commit(
/*============*/
mtr_t* mtr) /*!< in/out: mini-transaction */
MY_ATTRIBUTE((nonnull));
-/*********************************************************************//**
-Initializes an ibuf bitmap page. */
-void
-ibuf_bitmap_page_init(
-/*==================*/
- buf_block_t* block, /*!< in: bitmap page */
- mtr_t* mtr); /*!< in: mtr */
/************************************************************************//**
Resets the free bits of the page in the ibuf bitmap. This is done in a
separate mini-transaction, hence this operation does not restrict
@@ -241,18 +234,19 @@ ibuf_inside(
/** Checks if a page address is an ibuf bitmap page (level 3 page) address.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@return TRUE if a bitmap page */
-UNIV_INLINE
-ibool
-ibuf_bitmap_page(
- const page_id_t page_id,
- const page_size_t& page_size);
+inline bool ibuf_bitmap_page(const page_id_t page_id, ulint zip_size)
+{
+ ut_ad(ut_is_2pow(zip_size));
+ ulint size = zip_size ? zip_size : srv_page_size;
+ return (page_id.page_no() & (size - 1)) == FSP_IBUF_BITMAP_OFFSET;
+}
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id page id
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] x_latch FALSE if relaxed check (avoid latching the
bitmap page)
@param[in] file file name
@@ -260,13 +254,13 @@ bitmap page)
@param[in,out] mtr mtr which will contain an x-latch to the
bitmap page if the page is not one of the fixed address ibuf pages, or NULL,
in which case a new transaction is created.
-@return TRUE if level 2 or level 3 page */
-ibool
+@return true if level 2 or level 3 page */
+bool
ibuf_page_low(
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
#ifdef UNIV_DEBUG
- ibool x_latch,
+ bool x_latch,
#endif /* UNIV_DEBUG */
const char* file,
unsigned line,
@@ -278,22 +272,22 @@ ibuf_page_low(
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id tablespace/page identifier
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction or NULL
@return TRUE if level 2 or level 3 page */
-# define ibuf_page(page_id, page_size, mtr) \
- ibuf_page_low(page_id, page_size, TRUE, __FILE__, __LINE__, mtr)
+# define ibuf_page(page_id, zip_size, mtr) \
+ ibuf_page_low(page_id, zip_size, true, __FILE__, __LINE__, mtr)
#else /* UVIV_DEBUG */
/** Checks if a page is a level 2 or 3 page in the ibuf hierarchy of pages.
Must not be called when recv_no_ibuf_operations==true.
@param[in] page_id tablespace/page identifier
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] mtr mini-transaction or NULL
@return TRUE if level 2 or level 3 page */
-# define ibuf_page(page_id, page_size, mtr) \
- ibuf_page_low(page_id, page_size, __FILE__, __LINE__, mtr)
+# define ibuf_page(page_id, zip_size, mtr) \
+ ibuf_page_low(page_id, zip_size, __FILE__, __LINE__, mtr)
#endif /* UVIV_DEBUG */
/***********************************************************************//**
@@ -304,23 +298,23 @@ void
ibuf_free_excess_pages(void);
/*========================*/
-/** Buffer an operation in the insert/delete buffer, instead of doing it
-directly to the disk page, if this is possible. Does not do it if the index
+/** Buffer an operation in the change buffer, instead of applying it
+directly to the file page, if this is possible. Does not do it if the index
is clustered or unique.
@param[in] op operation type
@param[in] entry index entry to insert
@param[in,out] index index where to insert
@param[in] page_id page id where to insert
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] thr query thread
-@return TRUE if success */
-ibool
+@return true if success */
+bool
ibuf_insert(
ibuf_op_t op,
const dtuple_t* entry,
dict_index_t* index,
const page_id_t page_id,
- const page_size_t& page_size,
+ ulint zip_size,
que_thr_t* thr);
/**
@@ -340,25 +334,22 @@ subsequently was dropped.
@param[in,out] block if page has been read from disk,
pointer to the page x-latched, else NULL
@param[in] page_id page id of the index page
-@param[in] update_ibuf_bitmap normally this is set to TRUE, but
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@param[in] update_ibuf_bitmap normally this is set, but
if we have deleted or are deleting the tablespace, then we naturally do not
want to update a non-existent bitmap page */
void
ibuf_merge_or_delete_for_page(
buf_block_t* block,
const page_id_t page_id,
- const page_size_t* page_size,
- ibool update_ibuf_bitmap);
+ ulint zip_size,
+ bool update_ibuf_bitmap);
+
+/** Delete all change buffer entries for a tablespace,
+in DISCARD TABLESPACE, IMPORT TABLESPACE, or crash recovery.
+@param[in] space missing or to-be-discarded tablespace */
+void ibuf_delete_for_discarded_space(ulint space);
-/*********************************************************************//**
-Deletes all entries in the insert buffer for a given space id. This is used
-in DISCARD TABLESPACE and IMPORT TABLESPACE.
-NOTE: this does not update the page free bitmaps in the space. The space will
-become CORRUPT when you call this function! */
-void
-ibuf_delete_for_discarded_space(
-/*============================*/
- ulint space); /*!< in: space id */
/** Contract the change buffer by reading pages to the buffer pool.
@param[in] full If true, do a full contraction based
on PCT_IO(100). If false, the size of contract batch is determined
@@ -378,16 +369,8 @@ ibuf_merge_space(
/*=============*/
ulint space); /*!< in: space id */
-/*********************************************************************//**
-Parses a redo log record of an ibuf bitmap page init.
-@return end of log record or NULL */
-byte*
-ibuf_parse_bitmap_init(
-/*===================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr,/*!< in: buffer end */
- buf_block_t* block, /*!< in: block or NULL */
- mtr_t* mtr); /*!< in: mtr or NULL */
+/** Apply MLOG_IBUF_BITMAP_INIT when crash-upgrading */
+ATTRIBUTE_COLD void ibuf_bitmap_init_apply(buf_block_t* block);
/******************************************************************//**
Looks if the insert buffer is empty.
diff --git a/storage/innobase/include/ibuf0ibuf.ic b/storage/innobase/include/ibuf0ibuf.ic
index b3e04ee1661..db8c122c0f7 100644
--- a/storage/innobase/include/ibuf0ibuf.ic
+++ b/storage/innobase/include/ibuf0ibuf.ic
@@ -78,11 +78,12 @@ struct ibuf_t{
ulint height; /*!< tree height */
dict_index_t* index; /*!< insert buffer index */
- ulint n_merges; /*!< number of pages merged */
- ulint n_merged_ops[IBUF_OP_COUNT];
+ /** number of pages merged */
+ Atomic_counter<ulint> n_merges;
+ Atomic_counter<ulint> n_merged_ops[IBUF_OP_COUNT];
/*!< number of operations of each type
merged to index pages */
- ulint n_discarded_ops[IBUF_OP_COUNT];
+ Atomic_counter<ulint> n_discarded_ops[IBUF_OP_COUNT];
/*!< number of operations of each type
discarded without merging due to the
tablespace being deleted or the
@@ -149,20 +150,6 @@ ibuf_inside(
return(mtr->is_inside_ibuf());
}
-/** Checks if a page address is an ibuf bitmap page (level 3 page) address.
-@param[in] page_id page id
-@param[in] page_size page size
-@return TRUE if a bitmap page */
-UNIV_INLINE
-ibool
-ibuf_bitmap_page(
- const page_id_t page_id,
- const page_size_t& page_size)
-{
- return((page_id.page_no() & (page_size.physical() - 1))
- == FSP_IBUF_BITMAP_OFFSET);
-}
-
/** Translates the free space on a page to a value in the ibuf bitmap.
@param[in] page_size page size in bytes
@param[in] max_ins_size maximum insert size after reorganize for
@@ -191,29 +178,6 @@ ibuf_index_page_calc_free_bits(
return(n);
}
-/** Translates the ibuf free bits to the free space on a page in bytes.
-@param[in] page_size page_size
-@param[in] bits value for ibuf bitmap bits
-@return maximum insert size after reorganize for the page */
-UNIV_INLINE
-ulint
-ibuf_index_page_calc_free_from_bits(
- const page_size_t& page_size,
- ulint bits)
-{
- ut_ad(bits < 4);
- ut_ad(!page_size.is_compressed()
- || page_size.physical() > IBUF_PAGE_SIZE_PER_FREE_SPACE);
-
- if (bits == 3) {
- return(4 * page_size.physical()
- / IBUF_PAGE_SIZE_PER_FREE_SPACE);
- }
-
- return(bits * (page_size.physical()
- / IBUF_PAGE_SIZE_PER_FREE_SPACE));
-}
-
/*********************************************************************//**
Translates the free space on a compressed page to a value in the ibuf bitmap.
@return value for ibuf bitmap bits */
@@ -227,7 +191,7 @@ ibuf_index_page_calc_free_zip(
const page_zip_des_t* page_zip;
lint zip_max_ins;
- ut_ad(block->page.size.is_compressed());
+ ut_ad(block->page.zip.data);
/* Consider the maximum insert size on the uncompressed page
without reorganizing the page. We must not assume anything
@@ -250,7 +214,7 @@ ibuf_index_page_calc_free_zip(
max_ins_size = (ulint) zip_max_ins;
}
- return(ibuf_index_page_calc_free_bits(block->page.size.physical(),
+ return(ibuf_index_page_calc_free_bits(block->physical_size(),
max_ins_size));
}
@@ -263,14 +227,14 @@ ibuf_index_page_calc_free(
/*======================*/
const buf_block_t* block) /*!< in: buffer block */
{
- if (!block->page.size.is_compressed()) {
+ if (!block->page.zip.data) {
ulint max_ins_size;
max_ins_size = page_get_max_insert_size_after_reorganize(
buf_block_get_frame(block), 1);
return(ibuf_index_page_calc_free_bits(
- block->page.size.physical(), max_ins_size));
+ block->physical_size(), max_ins_size));
} else {
return(ibuf_index_page_calc_free_zip(block));
}
@@ -311,12 +275,12 @@ ibuf_update_free_bits_if_full(
ut_ad(buf_block_get_page_zip(block) == NULL);
before = ibuf_index_page_calc_free_bits(
- block->page.size.physical(), max_ins_size);
+ srv_page_size, max_ins_size);
if (max_ins_size >= increase) {
compile_time_assert(ULINT32_UNDEFINED > UNIV_PAGE_SIZE_MAX);
after = ibuf_index_page_calc_free_bits(
- block->page.size.physical(), max_ins_size - increase);
+ srv_page_size, max_ins_size - increase);
#ifdef UNIV_IBUF_DEBUG
ut_a(after <= ibuf_index_page_calc_free(block));
#endif
diff --git a/storage/innobase/include/log0crypt.h b/storage/innobase/include/log0crypt.h
index 7a14b022e66..8d26ccb2ba3 100644
--- a/storage/innobase/include/log0crypt.h
+++ b/storage/innobase/include/log0crypt.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (C) 2013, 2015, Google Inc. All Rights Reserved.
-Copyright (C) 2014, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (C) 2014, 2018, 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
@@ -73,14 +73,23 @@ UNIV_INTERN
bool
log_crypt_read_checkpoint_buf(const byte* buf);
+/** log_crypt() operation code */
+enum log_crypt_t {
+ /** encrypt a log block without rotating key */
+ LOG_ENCRYPT,
+ /** decrypt a log block */
+ LOG_DECRYPT,
+ /** attempt to rotate the key, and encrypt a log block */
+ LOG_ENCRYPT_ROTATE_KEY
+};
+
/** Encrypt or decrypt log blocks.
@param[in,out] buf log blocks to encrypt or decrypt
@param[in] lsn log sequence number of the start of the buffer
@param[in] size size of the buffer, in bytes
-@param[in] decrypt whether to decrypt instead of encrypting */
-UNIV_INTERN
-void
-log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt = false);
+@param[in] op whether to decrypt, encrypt, or rotate key and encrypt
+@return whether the operation succeeded (encrypt always does) */
+bool log_crypt(byte* buf, lsn_t lsn, ulint size, log_crypt_t op = LOG_ENCRYPT);
/** Encrypt or decrypt a temporary file block.
@param[in] src block to encrypt or decrypt
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 96202a23a63..7908a114477 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -164,19 +164,16 @@ bool
log_set_capacity(ulonglong file_size)
MY_ATTRIBUTE((warn_unused_result));
-/******************************************************//**
-This function is called, e.g., when a transaction wants to commit. It checks
-that the log has been written to the log file up to the last log entry written
-by the transaction. If there is a flush running, it waits and checks if the
-flush flushed enough. If not, starts a new flush. */
-void
-log_write_up_to(
-/*============*/
- lsn_t lsn, /*!< in: log sequence number up to which
- the log should be written, LSN_MAX if not specified */
- bool flush_to_disk);
- /*!< in: true if we want the written log
- also to be flushed to disk */
+/** Ensure that the log has been written to the log file up to a given
+log entry (such as that of a transaction commit). Start a new write, or
+wait and check if an already running write is covering the request.
+@param[in] lsn log sequence number that should be
+included in the redo log file write
+@param[in] flush_to_disk whether the written log should also
+be flushed to the file system
+@param[in] rotate_key whether to rotate the encryption key */
+void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key = false);
+
/** write to the log file up to the last log entry.
@param[in] sync whether we want the written log
also to be flushed to disk. */
@@ -406,13 +403,14 @@ extern my_bool innodb_log_checksums;
#define LOG_BLOCK_HDR_SIZE 12 /* size of the log block header in
bytes */
-/* Offsets of a log block trailer from the end of the block */
+#define LOG_BLOCK_KEY 4 /* encryption key version
+ before LOG_BLOCK_CHECKSUM;
+ in log_t::FORMAT_ENC_10_4 only */
#define LOG_BLOCK_CHECKSUM 4 /* 4 byte checksum of the log block
contents; in InnoDB versions
< 3.23.52 this did not contain the
checksum but the same value as
- .._HDR_NO */
-#define LOG_BLOCK_TRL_SIZE 4 /* trailer size in bytes */
+ LOG_BLOCK_HDR_NO */
/** Offsets inside the checkpoint pages (redo log format version 1) @{ */
/** Checkpoint number */
@@ -463,25 +461,6 @@ or the MySQL version that created the redo log file. */
IB_TO_STR(MYSQL_VERSION_MINOR) "." \
IB_TO_STR(MYSQL_VERSION_PATCH)
-/** The original (not version-tagged) InnoDB redo log format */
-#define LOG_HEADER_FORMAT_3_23 0
-/** The MySQL 5.7.9/MariaDB 10.2.2 log format */
-#define LOG_HEADER_FORMAT_10_2 1
-/** The MariaDB 10.3.2 log format.
-To prevent crash-downgrade to earlier 10.2 due to the inability to
-roll back a retroactively introduced TRX_UNDO_RENAME_TABLE undo log record,
-MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT
-1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2
-(MDEV-13564 backup-friendly TRUNCATE). */
-#define LOG_HEADER_FORMAT_10_3 103
-/** The redo log format identifier corresponding to the current format version.
-Stored in LOG_HEADER_FORMAT. */
-#define LOG_HEADER_FORMAT_CURRENT LOG_HEADER_FORMAT_10_3
-/** Future MariaDB 10.4 log format */
-#define LOG_HEADER_FORMAT_10_4 104
-/** Encrypted MariaDB redo log */
-#define LOG_HEADER_FORMAT_ENCRYPTED (1U<<31)
-
/* @} */
#define LOG_CHECKPOINT_1 OS_FILE_LOG_BLOCK_SIZE
@@ -506,6 +485,24 @@ typedef ib_mutex_t FlushOrderMutex;
/** Redo log buffer */
struct log_t{
+ /** The original (not version-tagged) InnoDB redo log format */
+ static constexpr uint32_t FORMAT_3_23 = 0;
+ /** The MySQL 5.7.9/MariaDB 10.2.2 log format */
+ static constexpr uint32_t FORMAT_10_2 = 1;
+ /** The MariaDB 10.3.2 log format.
+ To prevent crash-downgrade to earlier 10.2 due to the inability to
+ roll back a retroactively introduced TRX_UNDO_RENAME_TABLE undo log record,
+ MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT
+ 1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2
+ (MDEV-13564 backup-friendly TRUNCATE). */
+ static constexpr uint32_t FORMAT_10_3 = 103;
+ /** The MariaDB 10.4.0 log format. */
+ static constexpr uint32_t FORMAT_10_4 = 104;
+ /** Encrypted MariaDB redo log */
+ static constexpr uint32_t FORMAT_ENCRYPTED = 1U << 31;
+ /** The MariaDB 10.4.0 log format (only with innodb_encrypt_log=ON) */
+ static constexpr uint32_t FORMAT_ENC_10_4 = FORMAT_10_4 | FORMAT_ENCRYPTED;
+
MY_ALIGNED(CACHE_LINE_SIZE)
lsn_t lsn; /*!< log sequence number */
ulong buf_free; /*!< first free offset within the log
@@ -554,7 +551,7 @@ struct log_t{
struct files {
/** number of files */
ulint n_files;
- /** format of the redo log: e.g., LOG_HEADER_FORMAT_CURRENT */
+ /** format of the redo log: e.g., FORMAT_10_4 */
uint32_t format;
/** redo log subformat: 0 with separately logged TRUNCATE,
2 with fully redo-logged TRUNCATE (1 in MariaDB 10.2) */
@@ -572,7 +569,7 @@ struct log_t{
lsn_t scanned_lsn;
/** @return whether the redo log is encrypted */
- bool is_encrypted() const { return format & LOG_HEADER_FORMAT_ENCRYPTED; }
+ bool is_encrypted() const { return format & FORMAT_ENCRYPTED; }
/** @return capacity in bytes */
lsn_t capacity() const{ return (file_size - LOG_FILE_HDR_SIZE) * n_files; }
/** Calculate the offset of a log sequence number.
@@ -707,11 +704,34 @@ public:
/** @return whether the redo log is encrypted */
bool is_encrypted() const { return(log.is_encrypted()); }
- bool is_initialised() { return m_initialised; }
+ bool is_initialised() const { return m_initialised; }
/** Complete an asynchronous checkpoint write. */
void complete_checkpoint();
+ /** @return the log block header + trailer size */
+ unsigned framing_size() const
+ {
+ return log.format == FORMAT_ENC_10_4
+ ? LOG_BLOCK_HDR_SIZE + LOG_BLOCK_KEY + LOG_BLOCK_CHECKSUM
+ : LOG_BLOCK_HDR_SIZE + LOG_BLOCK_CHECKSUM;
+ }
+ /** @return the log block payload size */
+ unsigned payload_size() const
+ {
+ return log.format == FORMAT_ENC_10_4
+ ? OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - LOG_BLOCK_CHECKSUM -
+ LOG_BLOCK_KEY
+ : OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE - LOG_BLOCK_CHECKSUM;
+ }
+ /** @return the log block trailer offset */
+ unsigned trailer_offset() const
+ {
+ return log.format == FORMAT_ENC_10_4
+ ? OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM - LOG_BLOCK_KEY
+ : OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM;
+ }
+
/** Initialise the redo log subsystem. */
void create();
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 722e658a24b..7dfa7c0db68 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, 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
@@ -217,7 +217,7 @@ log_block_calc_checksum_format_0(
sum = 1;
sh = 0;
- for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
+ for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM; i++) {
ulint b = (ulint) block[i];
sum &= 0x7FFFFFFFUL;
sum += b;
@@ -239,7 +239,7 @@ ulint
log_block_calc_checksum_crc32(
const byte* block)
{
- return(ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE));
+ return ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_CHECKSUM);
}
/** Calculates the checksum for a log block using the "no-op" algorithm.
@@ -340,7 +340,7 @@ log_reserve_and_write_fast(
#endif /* UNIV_LOG_LSN_DEBUG */
+ log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE;
- if (data_len >= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
+ if (data_len >= log_sys.trailer_offset()) {
/* The string does not fit within the current log block
or the log block would become full */
@@ -485,9 +485,9 @@ log_free_check(void)
#ifdef UNIV_DEBUG
static const latch_level_t latches[] = {
- SYNC_DICT, /* dict_sys->mutex during
+ SYNC_DICT, /* dict_sys.mutex during
commit_try_rebuild() */
- SYNC_DICT_OPERATION, /* dict_operation_lock X-latch during
+ SYNC_DICT_OPERATION, /* dict_sys.latch X-latch during
commit_try_rebuild() */
SYNC_FTS_CACHE, /* fts_cache_t::lock */
SYNC_INDEX_TREE /* index->lock */
diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h
index 866102e6f3d..21ddd2b0388 100644
--- a/storage/innobase/include/log0recv.h
+++ b/storage/innobase/include/log0recv.h
@@ -33,8 +33,7 @@ Created 9/20/1997 Heikki Tuuri
#include "log0log.h"
#include "mtr0types.h"
-#include <list>
-#include <vector>
+#include <deque>
/** Is recv_writer_thread active? */
extern bool recv_writer_thread_active;
@@ -49,7 +48,7 @@ dberr_t
recv_find_max_checkpoint(ulint* max_field)
MY_ATTRIBUTE((nonnull, warn_unused_result));
-/** Reduces recv_sys->n_addrs for the corrupted page.
+/** Reduces recv_sys.n_addrs for the corrupted page.
This function should called when srv_force_recovery > 0.
@param[in] page_id page id of the corrupted page */
void recv_recover_corrupt_page(page_id_t page_id);
@@ -74,17 +73,6 @@ Initiates the rollback of active transactions. */
void
recv_recovery_rollback_active(void);
/*===============================*/
-/** Clean up after recv_sys_init() */
-void
-recv_sys_close();
-/** Initialize the redo log recovery subsystem. */
-void
-recv_sys_init();
-/********************************************************//**
-Frees the recovery system. */
-void
-recv_sys_debug_free(void);
-/*=====================*/
/********************************************************//**
Reset the state of the recovery system variables. */
@@ -110,7 +98,7 @@ enum store_t {
/** Adds data from a new log block to the parsing buffer of recv_sys if
-recv_sys->parse_start_lsn is non-zero.
+recv_sys.parse_start_lsn is non-zero.
@param[in] log_block log block to add
@param[in] scanned_lsn lsn of how far we were able to find
data in this log block
@@ -140,10 +128,6 @@ corresponding to MLOG_INDEX_LOAD.
*/
extern void (*log_optimized_ddl_op)(ulint space_id);
-/** Report backup-unfriendly TRUNCATE operation (with separate log file),
-corresponding to MLOG_TRUNCATE. */
-extern void (*log_truncate)();
-
/** Report an operation to create, delete, or rename a file during backup.
@param[in] space_id tablespace identifier
@param[in] flags tablespace flags (NULL if not create)
@@ -184,7 +168,7 @@ struct recv_t{
struct recv_dblwr_t {
/** Add a page frame to the doublewrite recovery buffer. */
void add(byte* page) {
- pages.push_back(page);
+ pages.push_front(page);
}
/** Find a doublewrite copy of a page.
@@ -194,7 +178,7 @@ struct recv_dblwr_t {
@retval NULL if no page was found */
const byte* find_page(ulint space_id, ulint page_no);
- typedef std::list<byte*, ut_allocator<byte*> > list;
+ typedef std::deque<byte*, ut_allocator<byte*> > list;
/** Recovered doublewrite buffer page frames */
list pages;
@@ -215,14 +199,11 @@ struct recv_sys_t{
buf_flush_t flush_type;/*!< type of the flush request.
BUF_FLUSH_LRU: flush end of LRU, keeping free blocks.
BUF_FLUSH_LIST: flush all of blocks. */
- ibool apply_log_recs;
- /*!< this is TRUE when log rec application to
- pages is allowed; this flag tells the
- i/o-handler if it should do log record
- application */
- ibool apply_batch_on;
- /*!< this is TRUE when a log rec application
- batch is running */
+ /** whether recv_recover_page(), invoked from buf_page_io_complete(),
+ should apply log records*/
+ bool apply_log_recs;
+ /** whether recv_apply_hashed_log_recs() is running */
+ bool apply_batch_on;
byte* buf; /*!< buffer for parsing log records */
size_t buf_size; /*!< size of buf */
ulint len; /*!< amount of data in buf */
@@ -276,6 +257,32 @@ struct recv_sys_t{
/** Lastly added LSN to the hash table of log records. */
lsn_t last_stored_lsn;
+ /** Initialize the redo log recovery subsystem. */
+ void create();
+
+ /** Free most recovery data structures. */
+ void debug_free();
+
+ /** Clean up after create() */
+ void close();
+
+ bool is_initialised() const { return buf_size != 0; }
+
+ /** Store a redo log record for applying.
+ @param type record type
+ @param space tablespace identifier
+ @param page_no page number
+ @param body record body
+ @param rec_end end of record
+ @param lsn start LSN of the mini-transaction
+ @param end_lsn end LSN of the mini-transaction */
+ inline void add(mlog_id_t type, ulint space, ulint page_no,
+ byte* body, byte* rec_end, lsn_t lsn,
+ lsn_t end_lsn);
+
+ /** Empty a fully processed set of stored redo log records. */
+ inline void empty();
+
/** Determine whether redo log recovery progress should be reported.
@param[in] time the current time
@return whether progress should be reported
@@ -292,7 +299,7 @@ struct recv_sys_t{
};
/** The recovery system */
-extern recv_sys_t* recv_sys;
+extern recv_sys_t recv_sys;
/** TRUE when applying redo log records during crash recovery; FALSE
otherwise. Note that this is FALSE while a background thread is
diff --git a/storage/innobase/include/mach0data.h b/storage/innobase/include/mach0data.h
index 8141c8a91e0..3d0e48253eb 100644
--- a/storage/innobase/include/mach0data.h
+++ b/storage/innobase/include/mach0data.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 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
@@ -29,11 +29,10 @@ Created 11/28/1995 Heikki Tuuri
#define mach0data_h
#include "univ.i"
+#include "mtr0types.h"
#ifndef UNIV_INNOCHECKSUM
-#include "mtr0types.h"
-
/* The data and all fields are always stored in a database file
in the same format: ascii, big-endian, ... .
All data in the files MUST be accessed using the functions in this
@@ -368,17 +367,6 @@ mach_write_ulonglong(
#endif /* !UNIV_INNOCHECKSUM */
-/** Read 1 to 4 bytes from a file page buffered in the buffer pool.
-@param[in] ptr pointer where to read
-@param[in] type MLOG_1BYTE, MLOG_2BYTES, or MLOG_4BYTES
-@return value read */
-UNIV_INLINE
-ulint
-mach_read_ulint(
- const byte* ptr,
- mlog_id_t type)
- MY_ATTRIBUTE((warn_unused_result));
-
#include "mach0data.ic"
#endif
diff --git a/storage/innobase/include/mach0data.ic b/storage/innobase/include/mach0data.ic
index 408044292a5..80bd925d70b 100644
--- a/storage/innobase/include/mach0data.ic
+++ b/storage/innobase/include/mach0data.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, 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
@@ -866,28 +866,3 @@ mach_write_ulonglong(
}
#endif /* !UNIV_INNOCHECKSUM */
-
-/** Read 1 to 4 bytes from a file page buffered in the buffer pool.
-@param[in] ptr pointer where to read
-@param[in] type MLOG_1BYTE, MLOG_2BYTES, or MLOG_4BYTES
-@return value read */
-UNIV_INLINE
-ulint
-mach_read_ulint(
- const byte* ptr,
- mlog_id_t type)
-{
- switch (type) {
- case MLOG_1BYTE:
- return(mach_read_from_1(ptr));
- case MLOG_2BYTES:
- return(mach_read_from_2(ptr));
- case MLOG_4BYTES:
- return(mach_read_from_4(ptr));
- default:
- break;
- }
-
- ut_error;
- return(0);
-}
diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h
index dc76b40a3db..0c58f524015 100644
--- a/storage/innobase/include/mtr0log.h
+++ b/storage/innobase/include/mtr0log.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2018, 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
@@ -71,6 +72,23 @@ mlog_log_string(
byte* ptr, /*!< in: pointer written to */
ulint len, /*!< in: string length */
mtr_t* mtr); /*!< in: mini-transaction handle */
+
+/** Initialize a string of bytes.
+@param[in,out] b buffer page
+@param[in] ofs byte offset from block->frame
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void
+mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr);
+
+/** Initialize a string of bytes.
+@param[in,out] byte byte address
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr);
+
/********************************************************//**
Writes initial part of a log record consisting of one-byte item
type and four-byte space and page numbers. */
@@ -180,7 +198,7 @@ mlog_parse_initial_log_record(
ulint* space, /*!< out: space id */
ulint* page_no);/*!< out: page number */
/********************************************************//**
-Parses a log record written by mlog_write_ulint or mlog_write_ull.
+Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset.
@return parsed record end, NULL if not a complete record */
byte*
mlog_parse_nbytes(
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 074f55971b3..f364730b21f 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -54,10 +54,6 @@ savepoint. */
@return old mode */
#define mtr_set_log_mode(m, d) (m)->set_log_mode((d))
-/** Read 1 - 4 bytes from a file page buffered in the buffer pool.
-@return value read */
-#define mtr_read_ulint(p, t, m) (m)->read_ulint((p), (t))
-
/** Release an object in the memo stack.
@return true if released */
#define mtr_memo_release(m, o, t) \
@@ -239,13 +235,6 @@ struct mtr_t {
bool is_named_space(const fil_space_t* space) const;
#endif /* UNIV_DEBUG */
- /** Read 1 - 4 bytes from a file page buffered in the buffer pool.
- @param ptr pointer from where to read
- @param type) MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES
- @return value read */
- inline ulint read_ulint(const byte* ptr, mlog_id_t type) const
- MY_ATTRIBUTE((warn_unused_result));
-
/** Acquire a tablespace X-latch.
@param[in] space_id tablespace ID
@param[in] file file name from where called
diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic
index 4cc55ed13ec..0fe56f960b7 100644
--- a/storage/innobase/include/mtr0mtr.ic
+++ b/storage/innobase/include/mtr0mtr.ic
@@ -170,7 +170,7 @@ mtr_t::release_block_at_savepoint(
ut_a(slot->object == block);
- buf_block_unfix(reinterpret_cast<buf_block_t*>(block));
+ reinterpret_cast<buf_block_t*>(block)->unfix();
buf_page_release_latch(block, slot->type);
@@ -227,21 +227,3 @@ mtr_t::set_log_mode(mtr_log_t mode)
ut_ad(0);
return(old_mode);
}
-
-/**
-Reads 1 - 4 bytes from a file page buffered in the buffer pool.
-@return value read */
-
-ulint
-mtr_t::read_ulint(const byte* ptr, mlog_id_t type) const
-{
- ut_ad(is_active());
-
- ut_ad(memo_contains_page_flagged(
- ptr,
- MTR_MEMO_PAGE_S_FIX
- | MTR_MEMO_PAGE_X_FIX
- | MTR_MEMO_PAGE_SX_FIX));
-
- return(mach_read_ulint(ptr, type));
-}
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index da6686d77c8..bf7484b2337 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -120,7 +120,7 @@ enum mlog_id_t {
/** mark an index record as the predefined minimum record */
MLOG_REC_MIN_MARK = 26,
- /** initialize an ibuf bitmap page */
+ /** initialize an ibuf bitmap page (used in MariaDB 10.2 and 10.3) */
MLOG_IBUF_BITMAP_INIT = 27,
#ifdef UNIV_LOG_LSN_DEBUG
@@ -218,7 +218,8 @@ enum mlog_id_t {
/** initialize a file page */
MLOG_INIT_FILE_PAGE2 = 59,
- /** Table is being truncated. (Marked only for file-per-table) */
+ /** Table is being truncated. (Was used in 10.2 and 10.3;
+ not supported for crash-upgrade to 10.4 or later.) */
MLOG_TRUNCATE = 60,
/** notify that an index tree is being loaded without writing
@@ -229,8 +230,14 @@ enum mlog_id_t {
of a ROW_FORMAT=COMPRESSED table */
MLOG_ZIP_WRITE_TRX_ID = 62,
+ /** initialize a page with a string of identical bytes */
+ MLOG_MEMSET = 63,
+
+ /** Zero-fill a page that is not allocated. */
+ MLOG_INIT_FREE_PAGE = 64,
+
/** biggest value (used in assertions) */
- MLOG_BIGGEST_TYPE = MLOG_ZIP_WRITE_TRX_ID,
+ MLOG_BIGGEST_TYPE = MLOG_INIT_FREE_PAGE,
/** log record for writing/updating crypt data of
a tablespace */
diff --git a/storage/innobase/include/os0api.h b/storage/innobase/include/os0api.h
index 6f42d968c8e..3be7c0afaa4 100644
--- a/storage/innobase/include/os0api.h
+++ b/storage/innobase/include/os0api.h
@@ -1,6 +1,6 @@
/***********************************************************************
-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
@@ -54,22 +54,4 @@ buf_page_get_trim_length(
ulint write_length)
MY_ATTRIBUTE((warn_unused_result));
-/**
-Get should we punch hole to tablespace.
-@param[in] space Tablespace
-@return true, if punch hole should be tried, false if not. */
-bool
-fil_node_should_punch_hole(
- const fil_node_t* node)
- MY_ATTRIBUTE((warn_unused_result));
-
-/**
-Set punch hole to tablespace to given value.
-@param[in] space Tablespace
-@param[in] val value to be set. */
-void
-fil_space_set_punch_hole(
- fil_node_t* node,
- bool val);
-
#endif /* OS_API_H */
diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h
index c896d9da6a2..a87ce5ec07b 100644
--- a/storage/innobase/include/os0file.h
+++ b/storage/innobase/include/os0file.h
@@ -36,7 +36,7 @@ Created 10/21/1995 Heikki Tuuri
#ifndef os0file_h
#define os0file_h
-#include "page0size.h"
+#include "fsp0types.h"
#include "os0api.h"
#ifndef _WIN32
@@ -360,17 +360,8 @@ public:
/** Set the pointer to file node for IO
@param[in] node File node */
- void set_fil_node(fil_node_t* node)
- {
- if (node && !fil_node_should_punch_hole(node)) {
- clear_punch_hole();
- }
-
- m_fil_node = node;
- }
+ inline void set_fil_node(fil_node_t* node);
- /** Compare two requests
- @reutrn true if the are equal */
bool operator==(const IORequest& rhs) const
{
return(m_type == rhs.m_type);
@@ -414,17 +405,7 @@ public:
: 0);
}
- bool should_punch_hole() const {
- return (m_fil_node ?
- fil_node_should_punch_hole(m_fil_node)
- : false);
- }
-
- void space_no_punch_hole() const {
- if (m_fil_node) {
- fil_space_set_punch_hole(m_fil_node, false);
- }
- }
+ inline bool should_punch_hole() const;
/** Free storage space associated with a section of the file.
@param[in] fh Open file handle
@@ -1585,19 +1566,6 @@ os_file_change_size_win32(
#endif /*_WIN32 */
-/** Check if the file system supports sparse files.
-
-Warning: On POSIX systems we try and punch a hole from offset 0 to
-the system configured page size. This should only be called on an empty
-file.
-
-@param[in] fh File handle for the file - if opened
-@return true if the file system supports sparse files */
-bool
-os_is_sparse_file_supported(
- os_file_t fh)
- MY_ATTRIBUTE((warn_unused_result));
-
/** Free storage space associated with a section of the file.
@param[in] fh Open file handle
@param[in] off Starting offset (SEEK_SET)
@@ -1637,16 +1605,6 @@ is_absolute_path(
return(false);
}
-/***********************************************************************//**
-Try to get number of bytes per sector from file system.
-@return file block size */
-UNIV_INTERN
-ulint
-os_file_get_block_size(
-/*===================*/
- os_file_t file, /*!< in: handle to a file */
- const char* name); /*!< in: file name */
-
#include "os0file.ic"
#endif /* os0file_h */
diff --git a/storage/innobase/include/os0once.h b/storage/innobase/include/os0once.h
deleted file mode 100644
index a818b451830..00000000000
--- a/storage/innobase/include/os0once.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2014, Oracle and/or its affiliates. All Rights Reserved.
-
-This program is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free Software
-Foundation; version 2 of the License.
-
-This program is distributed in the hope that it will be useful, but WITHOUT
-ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/os0once.h
-A class that aids executing a given function exactly once in a multi-threaded
-environment.
-
-Created Feb 20, 2014 Vasil Dimov
-*******************************************************/
-
-#ifndef os0once_h
-#define os0once_h
-
-#include "univ.i"
-
-#include "ut0ut.h"
-#include "my_cpu.h"
-
-/** Execute a given function exactly once in a multi-threaded environment
-or wait for the function to be executed by another thread.
-
-Example usage:
-First the user must create a control variable of type os_once::state_t and
-assign it os_once::NEVER_DONE.
-Then the user must pass this variable, together with a function to be
-executed to os_once::do_or_wait_for_done().
-
-Multiple threads can call os_once::do_or_wait_for_done() simultaneously with
-the same (os_once::state_t) control variable. The provided function will be
-called exactly once and when os_once::do_or_wait_for_done() returns then this
-function has completed execution, by this or another thread. In other words
-os_once::do_or_wait_for_done() will either execute the provided function or
-will wait for its execution to complete if it is already called by another
-thread or will do nothing if the function has already completed its execution
-earlier.
-
-This mimics pthread_once(3), but unfortunatelly pthread_once(3) does not
-support passing arguments to the init_routine() function. We should use
-std::call_once() when we start compiling with C++11 enabled. */
-class os_once {
-public:
- /** Control variables' state type */
- typedef ib_uint32_t state_t;
-
- /** Not yet executed. */
- static const state_t NEVER_DONE = 0;
-
- /** Currently being executed by this or another thread. */
- static const state_t IN_PROGRESS = 1;
-
- /** Finished execution. */
- static const state_t DONE = 2;
-
- /** Call a given function or wait its execution to complete if it is
- already called by another thread.
- @param[in,out] state control variable
- @param[in] do_func function to call
- @param[in,out] do_func_arg an argument to pass to do_func(). */
- static
- void
- do_or_wait_for_done(
- volatile state_t* state,
- void (*do_func)(void*),
- void* do_func_arg)
- {
- int32 oldval = NEVER_DONE;
-
- /* Avoid calling my_atomic_cas32() in the most common case. */
- if (*state == DONE) {
- return;
- }
-
- if (my_atomic_cas32((int32*) state, &oldval, IN_PROGRESS)) {
- /* We are the first. Call the function. */
-
- do_func(do_func_arg);
-
- my_atomic_store32((int32*) state, DONE);
- } else {
- /* The state is not NEVER_DONE, so either it is
- IN_PROGRESS (somebody is calling the function right
- now or DONE (it has already been called and completed).
- Wait for it to become DONE. */
- for (;;) {
- const state_t s = *state;
-
- switch (s) {
- case DONE:
- return;
- case IN_PROGRESS:
- break;
- case NEVER_DONE:
- /* fall through */
- default:
- ut_error;
- }
-
- MY_RELAX_CPU();
- }
- }
- }
-};
-
-#endif /* os0once_h */
diff --git a/storage/innobase/include/os0proc.h b/storage/innobase/include/os0proc.h
index 9b0b3cbf628..d8952a56cc9 100644
--- a/storage/innobase/include/os0proc.h
+++ b/storage/innobase/include/os0proc.h
@@ -40,7 +40,7 @@ typedef unsigned long int os_process_id_t;
/** The total amount of memory currently allocated from the operating
system with os_mem_alloc_large(). */
-extern ulint os_total_large_mem_allocated;
+extern Atomic_counter<ulint> os_total_large_mem_allocated;
/** Converts the current process id to a number.
@return process id as a number */
diff --git a/storage/innobase/include/os0thread.h b/storage/innobase/include/os0thread.h
index d99bc841de9..67ee3097274 100644
--- a/storage/innobase/include/os0thread.h
+++ b/storage/innobase/include/os0thread.h
@@ -73,7 +73,7 @@ typedef unsigned int mysql_pfs_key_t;
#endif /* HAVE_PSI_INTERFACE */
/** Number of threads active. */
-extern ulint os_thread_count;
+extern Atomic_counter<ulint> os_thread_count;
/***************************************************************//**
Compares two thread ids for equality.
diff --git a/storage/innobase/include/page0cur.ic b/storage/innobase/include/page0cur.ic
index 1ccb7f9a80d..528b3af9352 100644
--- a/storage/innobase/include/page0cur.ic
+++ b/storage/innobase/include/page0cur.ic
@@ -24,12 +24,7 @@ The page cursor
Created 10/4/1994 Heikki Tuuri
*************************************************************************/
-#include "page0page.h"
-#include "buf0types.h"
-
#ifdef UNIV_DEBUG
-# include "rem0cmp.h"
-
/*********************************************************//**
Gets pointer to the page frame where the cursor is positioned.
@return page */
@@ -280,6 +275,7 @@ page_cur_tuple_insert(
*offsets = rec_get_offsets(rec, index, *offsets,
page_is_leaf(cursor->block->frame),
ULINT_UNDEFINED, heap);
+ ut_ad(size == rec_offs_size(*offsets));
if (buf_block_get_page_zip(cursor->block)) {
rec = page_cur_insert_rec_zip(
diff --git a/storage/innobase/include/page0page.h b/storage/innobase/include/page0page.h
index 0876bc54aaf..31a60bcb4e5 100644
--- a/storage/innobase/include/page0page.h
+++ b/storage/innobase/include/page0page.h
@@ -27,29 +27,23 @@ Created 2/2/1994 Heikki Tuuri
#define page0page_h
#include "page0types.h"
-#ifndef UNIV_INNOCHECKSUM
+#include "fsp0fsp.h"
#include "fil0fil.h"
#include "buf0buf.h"
-#include "data0data.h"
-#include "dict0dict.h"
-#include "rem0types.h"
#include "rem0rec.h"
-#endif /* !UNIV_INNOCHECKSUM*/
-#include "fsp0fsp.h"
#ifndef UNIV_INNOCHECKSUM
+#include "dict0dict.h"
+#include "data0data.h"
#include "mtr0mtr.h"
-#ifdef UNIV_MATERIALIZE
-#undef UNIV_INLINE
-#define UNIV_INLINE
-#endif
-
/* PAGE HEADER
===========
Index page header starts at the first offset left free by the FIL-module */
typedef byte page_header_t;
+#else
+# include "mach0data.h"
#endif /* !UNIV_INNOCHECKSUM */
#define PAGE_HEADER FSEG_PAGE_DATA /* index page header starts at this
@@ -164,12 +158,12 @@ Otherwise written as 0. @see PAGE_ROOT_AUTO_INC */
not necessarily collation order;
this record may have been deleted */
-/* Directions of cursor movement */
-#define PAGE_LEFT 1
-#define PAGE_RIGHT 2
-#define PAGE_SAME_REC 3
-#define PAGE_SAME_PAGE 4
-#define PAGE_NO_DIRECTION 5
+/* Directions of cursor movement (stored in PAGE_DIRECTION field) */
+constexpr uint16_t PAGE_LEFT= 1;
+constexpr uint16_t PAGE_RIGHT= 2;
+constexpr uint16_t PAGE_SAME_REC= 3;
+constexpr uint16_t PAGE_SAME_PAGE= 4;
+constexpr uint16_t PAGE_NO_DIRECTION= 5;
#ifndef UNIV_INNOCHECKSUM
@@ -1013,13 +1007,6 @@ page_get_direction(const page_t* page)
inline
uint16_t
page_get_instant(const page_t* page);
-/** Assign the PAGE_INSTANT field.
-@param[in,out] page clustered index root page
-@param[in] n original number of clustered index fields
-@param[in,out] mtr mini-transaction */
-inline
-void
-page_set_instant(page_t* page, unsigned n, mtr_t* mtr);
/**********************************************************//**
Create an uncompressed B-tree index page.
@@ -1041,16 +1028,10 @@ page_create_zip(
buf_block_t* block, /*!< in/out: a buffer frame
where the page is created */
dict_index_t* index, /*!< in: the index of the
- page, or NULL when applying
- TRUNCATE log
- record during recovery */
+ page */
ulint level, /*!< in: the B-tree level of
the page */
trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */
- const redo_page_compress_t* page_comp_info,
- /*!< in: used for applying
- TRUNCATE log
- record during recovery */
mtr_t* mtr); /*!< in/out: mini-transaction
handle */
/**********************************************************//**
@@ -1338,11 +1319,6 @@ const rec_t*
page_find_rec_max_not_deleted(
const page_t* page);
-#ifdef UNIV_MATERIALIZE
-#undef UNIV_INLINE
-#define UNIV_INLINE UNIV_INLINE_ORIGINAL
-#endif
-
#endif /* !UNIV_INNOCHECKSUM */
#include "page0page.ic"
diff --git a/storage/innobase/include/page0page.ic b/storage/innobase/include/page0page.ic
index 94887a0925a..28ee193c6e5 100644
--- a/storage/innobase/include/page0page.ic
+++ b/storage/innobase/include/page0page.ic
@@ -29,18 +29,10 @@ Created 2/2/1994 Heikki Tuuri
#ifndef UNIV_INNOCHECKSUM
#include "mach0data.h"
-#ifdef UNIV_DEBUG
-# include "log0recv.h"
-#endif /* !UNIV_DEBUG */
#include "rem0cmp.h"
#include "mtr0log.h"
#include "page0zip.h"
-#ifdef UNIV_MATERIALIZE
-#undef UNIV_INLINE
-#define UNIV_INLINE
-#endif
-
/*************************************************************//**
Returns the max trx id field value. */
UNIV_INLINE
@@ -1106,29 +1098,6 @@ page_get_instant(const page_t* page)
#endif /* UNIV_DEBUG */
return(i >> 3);
}
-
-/** Assign the PAGE_INSTANT field.
-@param[in,out] page clustered index root page
-@param[in] n original number of clustered index fields
-@param[in,out] mtr mini-transaction */
-inline
-void
-page_set_instant(page_t* page, unsigned n, mtr_t* mtr)
-{
- ut_ad(fil_page_get_type(page) == FIL_PAGE_TYPE_INSTANT);
- ut_ad(n > 0);
- ut_ad(n < REC_MAX_N_FIELDS);
- uint16_t i = page_header_get_field(page, PAGE_INSTANT);
- ut_ad(i <= PAGE_NO_DIRECTION);
- i |= n << 3;
- mlog_write_ulint(PAGE_HEADER + PAGE_INSTANT + page, i,
- MLOG_2BYTES, mtr);
-}
#endif /* !UNIV_INNOCHECKSUM */
-#ifdef UNIV_MATERIALIZE
-#undef UNIV_INLINE
-#define UNIV_INLINE UNIV_INLINE_ORIGINAL
-#endif
-
#endif
diff --git a/storage/innobase/include/page0size.h b/storage/innobase/include/page0size.h
deleted file mode 100644
index ca1e704eda1..00000000000
--- a/storage/innobase/include/page0size.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 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
-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 Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/page0size.h
-A class describing a page size.
-
-Created Nov 14, 2013 Vasil Dimov
-*******************************************************/
-
-#ifndef page0size_t
-#define page0size_t
-
-#include "fsp0types.h"
-
-#define FIELD_REF_SIZE 20U
-
-/** A BLOB field reference full of zero, for use in assertions and
-tests.Initially, BLOB field references are set to zero, in
-dtuple_convert_big_rec(). */
-extern const byte field_ref_zero[UNIV_PAGE_SIZE_MAX];
-
-#define PAGE_SIZE_T_SIZE_BITS 17
-
-/** Page size descriptor. Contains the physical and logical page size, as well
-as whether the page is compressed or not. */
-class page_size_t {
-public:
- /** Constructor from (physical, logical, is_compressed).
- @param[in] physical physical (on-disk/zipped) page size
- @param[in] logical logical (in-memory/unzipped) page size
- @param[in] is_compressed whether the page is compressed */
- page_size_t(ulint physical, ulint logical, bool is_compressed)
- {
- if (physical == 0) {
- physical = UNIV_PAGE_SIZE_ORIG;
- }
- if (logical == 0) {
- logical = UNIV_PAGE_SIZE_ORIG;
- }
-
- m_physical = static_cast<unsigned>(physical);
- m_logical = static_cast<unsigned>(logical);
- m_is_compressed = static_cast<unsigned>(is_compressed);
-
- ut_ad(physical <= (1 << PAGE_SIZE_T_SIZE_BITS));
- ut_ad(logical <= (1 << PAGE_SIZE_T_SIZE_BITS));
-
- ut_ad(ut_is_2pow(physical));
- ut_ad(ut_is_2pow(logical));
-
- ut_ad(logical <= UNIV_PAGE_SIZE_MAX);
- ut_ad(logical >= physical);
- ut_ad(!is_compressed || physical <= UNIV_ZIP_SIZE_MAX);
- }
-
- /** Constructor from (fsp_flags).
- @param[in] fsp_flags filespace flags */
- explicit page_size_t(ulint fsp_flags)
- {
- ulint ssize = FSP_FLAGS_GET_PAGE_SSIZE(fsp_flags);
-
- /* If the logical page size is zero in fsp_flags, then use the
- legacy 16k page size. */
- ssize = (0 == ssize) ? UNIV_PAGE_SSIZE_ORIG : ssize;
-
- /* Convert from a 'log2 minus 9' to a page size in bytes. */
- const unsigned size = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
-
- ut_ad(size <= UNIV_PAGE_SIZE_MAX);
- ut_ad(size <= (1 << PAGE_SIZE_T_SIZE_BITS));
-
- m_logical = size;
-
- ssize = FSP_FLAGS_GET_ZIP_SSIZE(fsp_flags);
-
- /* If the fsp_flags have zero in the zip_ssize field, then it means
- that the tablespace does not have compressed pages and the physical
- page size is the same as the logical page size. */
- if (ssize == 0) {
- m_is_compressed = false;
- m_physical = m_logical;
- } else {
- m_is_compressed = true;
-
- /* Convert from a 'log2 minus 9' to a page size
- in bytes. */
- const unsigned phy
- = ((UNIV_ZIP_SIZE_MIN >> 1) << ssize);
-
- ut_ad(phy <= UNIV_ZIP_SIZE_MAX);
- ut_ad(phy <= (1 << PAGE_SIZE_T_SIZE_BITS));
-
- m_physical = phy;
- }
- }
-
- /** Retrieve the physical page size (on-disk).
- @return physical page size in bytes */
- inline ulint physical() const
- {
- ut_ad(m_physical > 0);
-
- return(m_physical);
- }
-
- /** Retrieve the logical page size (in-memory).
- @return logical page size in bytes */
- inline ulint logical() const
- {
- ut_ad(m_logical > 0);
- return(m_logical);
- }
-
- /** Check whether the page is compressed on disk.
- @return true if compressed */
- inline bool is_compressed() const
- {
- return(m_is_compressed);
- }
-
- /** Copy the values from a given page_size_t object.
- @param[in] src page size object whose values to fetch */
- inline void copy_from(const page_size_t& src)
- {
- *this = src;
- }
-
- /** Check if a given page_size_t object is equal to the current one.
- @param[in] a page_size_t object to compare
- @return true if equal */
- inline bool equals_to(const page_size_t& a) const
- {
- return(a.physical() == m_physical
- && a.logical() == m_logical
- && a.is_compressed() == m_is_compressed);
- }
-
-private:
-
- /* For non compressed tablespaces, physical page size is equal to
- the logical page size and the data is stored in buf_page_t::frame
- (and is also always equal to univ_page_size (--innodb-page-size=)).
-
- For compressed tablespaces, physical page size is the compressed
- page size as stored on disk and in buf_page_t::zip::data. The logical
- page size is the uncompressed page size in memory - the size of
- buf_page_t::frame (currently also always equal to univ_page_size
- (--innodb-page-size=)). */
-
- /** Physical page size. */
- unsigned m_physical:PAGE_SIZE_T_SIZE_BITS;
-
- /** Logical page size. */
- unsigned m_logical:PAGE_SIZE_T_SIZE_BITS;
-
- /** Flag designating whether the physical page is compressed, which is
- true IFF the whole tablespace where the page belongs is compressed. */
- unsigned m_is_compressed:1;
-};
-
-/* Overloading the global output operator to conveniently print an object
-of type the page_size_t.
-@param[in,out] out the output stream
-@param[in] obj an object of type page_size_t to be printed
-@retval the output stream */
-inline
-std::ostream&
-operator<<(
- std::ostream& out,
- const page_size_t& obj)
-{
- out << "[page size: physical=" << obj.physical()
- << ", logical=" << obj.logical()
- << ", compressed=" << obj.is_compressed() << "]";
- return(out);
-}
-
-extern page_size_t univ_page_size;
-
-#endif /* page0size_t */
diff --git a/storage/innobase/include/page0types.h b/storage/innobase/include/page0types.h
index 4debd639fa4..dd8d0dbe35d 100644
--- a/storage/innobase/include/page0types.h
+++ b/storage/innobase/include/page0types.h
@@ -84,18 +84,6 @@ enum page_cur_mode_t {
PAGE_CUR_RTREE_GET_FATHER = 14
};
-
-/** The information used for compressing a page when applying
-TRUNCATE log record during recovery */
-struct redo_page_compress_t {
- ulint type; /*!< index type */
- index_id_t index_id; /*!< index id */
- ulint n_fields; /*!< number of index fields */
- ulint field_len; /*!< the length of index field */
- const byte* fields; /*!< index field information */
- ulint trx_id_pos; /*!< position of trx-id column. */
-};
-
/** Compressed page descriptor */
struct page_zip_des_t
{
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
index da682df2e14..2f11a1c77f3 100644
--- a/storage/innobase/include/page0zip.h
+++ b/storage/innobase/include/page0zip.h
@@ -28,28 +28,11 @@ Created June 2005 by Marko Makela
#ifndef page0zip_h
#define page0zip_h
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE
-#endif
-
-#ifdef UNIV_INNOCHECKSUM
-#include "buf0buf.h"
-#include "ut0crc32.h"
-#include "buf0checksum.h"
-#include "mach0data.h"
-#include "zlib.h"
-#endif /* UNIV_INNOCHECKSUM */
+#include "buf0types.h"
#ifndef UNIV_INNOCHECKSUM
#include "mtr0types.h"
#include "page0types.h"
-#endif /* !UNIV_INNOCHECKSUM */
-
-#include "buf0types.h"
-#include "rem0types.h"
-
-#ifndef UNIV_INNOCHECKSUM
#include "dict0types.h"
#include "srv0srv.h"
#include "trx0types.h"
@@ -103,15 +86,10 @@ page_zip_set_size(
@param[in] comp nonzero=compact format
@param[in] n_fields number of fields in the record; ignored if
tablespace is not compressed
-@param[in] page_size page size
-@return FALSE if the entire record can be stored locally on the page */
-UNIV_INLINE
-ibool
-page_zip_rec_needs_ext(
- ulint rec_size,
- ulint comp,
- ulint n_fields,
- const page_size_t& page_size)
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return false if the entire record can be stored locally on the page */
+inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields,
+ ulint zip_size)
MY_ATTRIBUTE((warn_unused_result));
/**********************************************************************//**
@@ -164,10 +142,6 @@ page_zip_compress(
dict_index_t* index, /*!< in: index of the B-tree
node */
ulint level, /*!< in: commpression level */
- const redo_page_compress_t* page_comp_info,
- /*!< in: used for applying
- TRUNCATE log
- record during recovery */
mtr_t* mtr); /*!< in/out: mini-transaction,
or NULL */
@@ -517,12 +491,7 @@ uint32_t
page_zip_calc_checksum(
const void* data,
ulint size,
- srv_checksum_algorithm_t algo
-#ifdef INNODB_BUG_ENDIAN_CRC32
- /** for crc32, use the big-endian bug-compatible crc32 variant */
- , bool use_legacy_big_endian = false
-#endif
-);
+ srv_checksum_algorithm_t algo);
/** Validate the checksum on a ROW_FORMAT=COMPRESSED page.
@param data ROW_FORMAT=COMPRESSED page
@@ -563,11 +532,6 @@ void
page_zip_reset_stat_per_index();
/*===========================*/
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE UNIV_INLINE_ORIGINAL
-#endif
-
#include "page0zip.ic"
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/page0zip.ic b/storage/innobase/include/page0zip.ic
index 90c6ee29657..8bd382e7872 100644
--- a/storage/innobase/include/page0zip.ic
+++ b/storage/innobase/include/page0zip.ic
@@ -2,7 +2,7 @@
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-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
@@ -25,11 +25,6 @@ Compressed page interface
Created June 2005 by Marko Makela
*******************************************************/
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE
-#endif
-
#include "page0zip.h"
#include "mtr0log.h"
#include "page0page.h"
@@ -154,22 +149,17 @@ page_zip_set_size(
@param[in] comp nonzero=compact format
@param[in] n_fields number of fields in the record; ignored if
tablespace is not compressed
-@param[in] page_size page size
-@return FALSE if the entire record can be stored locally on the page */
-UNIV_INLINE
-ibool
-page_zip_rec_needs_ext(
- ulint rec_size,
- ulint comp,
- ulint n_fields,
- const page_size_t& page_size)
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
+@return false if the entire record can be stored locally on the page */
+inline bool page_zip_rec_needs_ext(ulint rec_size, ulint comp, ulint n_fields,
+ ulint zip_size)
{
/* FIXME: row size check is this function seems to be the most correct.
Put it in a separate function and use in more places of InnoDB */
ut_ad(rec_size
> ulint(comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES));
- ut_ad(comp || !page_size.is_compressed());
+ ut_ad(comp || !zip_size);
#if UNIV_PAGE_SIZE_MAX > COMPRESSED_REC_MAX_DATA_SIZE
if (comp ? rec_size >= COMPRESSED_REC_MAX_DATA_SIZE :
@@ -178,7 +168,7 @@ page_zip_rec_needs_ext(
}
#endif
- if (page_size.is_compressed()) {
+ if (zip_size) {
ut_ad(comp);
/* On a compressed page, there is a two-byte entry in
the dense page directory for every record. But there
@@ -187,7 +177,7 @@ page_zip_rec_needs_ext(
the encoded heap number. Check also the available space
on the uncompressed page. */
return(rec_size - (REC_N_NEW_EXTRA_BYTES - 2 - 1)
- >= page_zip_empty_size(n_fields, page_size.physical())
+ >= page_zip_empty_size(n_fields, zip_size)
|| rec_size >= page_get_free_space_of_empty(TRUE) / 2);
}
@@ -417,7 +407,7 @@ page_zip_parse_compress_no_data(
was successful. Crash in this case. */
if (page
- && !page_zip_compress(page_zip, page, index, level, NULL, NULL)) {
+ && !page_zip_compress(page_zip, page, index, level, NULL)) {
ut_error;
}
@@ -440,8 +430,3 @@ page_zip_reset_stat_per_index()
mutex_exit(&page_zip_stat_per_index_mutex);
}
-
-#ifdef UNIV_MATERIALIZE
-# undef UNIV_INLINE
-# define UNIV_INLINE UNIV_INLINE_ORIGINAL
-#endif
diff --git a/storage/innobase/include/que0que.h b/storage/innobase/include/que0que.h
index 66dc00f5d10..4b52e55a047 100644
--- a/storage/innobase/include/que0que.h
+++ b/storage/innobase/include/que0que.h
@@ -297,9 +297,9 @@ que_eval_sql(
/*=========*/
pars_info_t* info, /*!< in: info struct, or NULL */
const char* sql, /*!< in: SQL string */
- ibool reserve_dict_mutex,
- /*!< in: if TRUE, acquire/release
- dict_sys->mutex around call to pars_sql. */
+ bool reserve_dict_mutex,
+ /*!< in: whether to acquire/release
+ dict_sys.mutex around call to pars_sql. */
trx_t* trx); /*!< in: trx */
/**********************************************************************//**
diff --git a/storage/innobase/include/read0types.h b/storage/innobase/include/read0types.h
index c0faf84cfbe..48575feda10 100644
--- a/storage/innobase/include/read0types.h
+++ b/storage/innobase/include/read0types.h
@@ -66,7 +66,14 @@ class ReadView
Close view:
READ_VIEW_STATE_OPEN -> READ_VIEW_STATE_CLOSED
*/
- int32_t m_state;
+ std::atomic<uint32_t> m_state;
+
+
+ /** m_state getter for ReadView owner thread */
+ uint32_t state() const
+ {
+ return m_state.load(std::memory_order_relaxed);
+ }
public:
@@ -134,35 +141,36 @@ loop:
Closes the view.
View becomes not visible to purge thread.
+
+ This method is intended to be called by ReadView owner thread, thus
+ m_state cannot change.
*/
void close()
{
- ut_ad(m_state == READ_VIEW_STATE_CLOSED ||
- m_state == READ_VIEW_STATE_OPEN);
- if (m_state == READ_VIEW_STATE_OPEN)
- my_atomic_store32_explicit(&m_state, READ_VIEW_STATE_CLOSED,
- MY_MEMORY_ORDER_RELAXED);
+ ut_ad(state() == READ_VIEW_STATE_CLOSED ||
+ state() == READ_VIEW_STATE_OPEN);
+ m_state.store(READ_VIEW_STATE_CLOSED, std::memory_order_relaxed);
}
/** m_state getter for trx_sys::clone_oldest_view() trx_sys::size(). */
- int32_t get_state() const
+ uint32_t get_state() const
{
- return my_atomic_load32_explicit(const_cast<int32*>(&m_state),
- MY_MEMORY_ORDER_ACQUIRE);
+ return m_state.load(std::memory_order_acquire);
}
/**
Returns true if view is open.
- Only used by view owner thread, thus we can omit atomic operations.
+ This method is intended to be called by ReadView owner thread, thus
+ m_state cannot change.
*/
bool is_open() const
{
- ut_ad(m_state == READ_VIEW_STATE_OPEN ||
- m_state == READ_VIEW_STATE_CLOSED);
- return m_state == READ_VIEW_STATE_OPEN;
+ ut_ad(state() == READ_VIEW_STATE_OPEN ||
+ state() == READ_VIEW_STATE_CLOSED);
+ return state() == READ_VIEW_STATE_OPEN;
}
diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h
index 4b7812e3bd6..bd6bb563192 100644
--- a/storage/innobase/include/rem0rec.h
+++ b/storage/innobase/include/rem0rec.h
@@ -38,15 +38,6 @@ Created 5/30/1994 Heikki Tuuri
#include <ostream>
#include <sstream>
-/* Info bit denoting the predefined minimum record: this bit is set
-if and only if the record is the first user record on a non-leaf
-B-tree page that is the leftmost page on its level
-(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */
-#define REC_INFO_MIN_REC_FLAG 0x10UL
-/* The deleted flag in info bits */
-#define REC_INFO_DELETED_FLAG 0x20UL /* when bit is set to 1, it means the
- record has been delete marked */
-
/* Number of extra bytes in an old-style record,
in addition to the data and the offsets */
#define REC_N_OLD_EXTRA_BYTES 6
@@ -54,26 +45,6 @@ in addition to the data and the offsets */
in addition to the data and the offsets */
#define REC_N_NEW_EXTRA_BYTES 5
-/** Record status values for ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED */
-enum rec_comp_status_t {
- /** User record (PAGE_LEVEL=0, heap>=PAGE_HEAP_NO_USER_LOW) */
- REC_STATUS_ORDINARY = 0,
- /** Node pointer record (PAGE_LEVEL>=0, heap>=PAGE_HEAP_NO_USER_LOW) */
- REC_STATUS_NODE_PTR = 1,
- /** The page infimum pseudo-record (heap=PAGE_HEAP_NO_INFIMUM) */
- REC_STATUS_INFIMUM = 2,
- /** The page supremum pseudo-record (heap=PAGE_HEAP_NO_SUPREMUM) */
- REC_STATUS_SUPREMUM = 3,
- /** Clustered index record that has been inserted or updated
- after instant ADD COLUMN (more than dict_index_t::n_core_fields) */
- REC_STATUS_COLUMNS_ADDED = 4
-};
-
-/** The dtuple_t::info_bits of the metadata pseudo-record.
-@see rec_is_metadata() */
-static const byte REC_INFO_METADATA
- = REC_INFO_MIN_REC_FLAG | REC_STATUS_COLUMNS_ADDED;
-
#define REC_NEW_STATUS 3 /* This is single byte bit-field */
#define REC_NEW_STATUS_MASK 0x7UL
#define REC_NEW_STATUS_SHIFT 0
@@ -336,7 +307,7 @@ rec_comp_status_t
rec_get_status(const rec_t* rec)
{
byte bits = rec[-REC_NEW_STATUS] & REC_NEW_STATUS_MASK;
- ut_ad(bits <= REC_STATUS_COLUMNS_ADDED);
+ ut_ad(bits <= REC_STATUS_INSTANT);
return static_cast<rec_comp_status_t>(bits);
}
@@ -347,12 +318,12 @@ inline
void
rec_set_status(rec_t* rec, byte bits)
{
- ut_ad(bits <= REC_STATUS_COLUMNS_ADDED);
+ ut_ad(bits <= REC_STATUS_INSTANT);
rec[-REC_NEW_STATUS] = (rec[-REC_NEW_STATUS] & ~REC_NEW_STATUS_MASK)
| bits;
}
-/** Get the length of added field count in a REC_STATUS_COLUMNS_ADDED record.
+/** Get the length of added field count in a REC_STATUS_INSTANT record.
@param[in] n_add_field number of added fields, minus one
@return storage size of the field count, in bytes */
inline unsigned rec_get_n_add_field_len(ulint n_add_field)
@@ -361,8 +332,26 @@ inline unsigned rec_get_n_add_field_len(ulint n_add_field)
return n_add_field < 0x80 ? 1 : 2;
}
-/** Set the added field count in a REC_STATUS_COLUMNS_ADDED record.
-@param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record
+/** Get the added field count in a REC_STATUS_INSTANT record.
+@param[in,out] header variable header of a REC_STATUS_INSTANT record
+@return number of added fields */
+inline unsigned rec_get_n_add_field(const byte*& header)
+{
+ unsigned n_fields_add = *--header;
+ if (n_fields_add < 0x80) {
+ ut_ad(rec_get_n_add_field_len(n_fields_add) == 1);
+ return n_fields_add;
+ }
+
+ n_fields_add &= 0x7f;
+ n_fields_add |= unsigned(*--header) << 7;
+ ut_ad(n_fields_add < REC_MAX_N_FIELDS);
+ ut_ad(rec_get_n_add_field_len(n_fields_add) == 2);
+ return n_fields_add;
+}
+
+/** Set the added field count in a REC_STATUS_INSTANT record.
+@param[in,out] header variable header of a REC_STATUS_INSTANT record
@param[in] n_add number of added fields, minus 1
@return record header before the number of added fields */
inline void rec_set_n_add_field(byte*& header, ulint n_add)
@@ -801,20 +790,89 @@ inline ulint rec_offs_comp(const offset_t *offsets)
}
/** Determine if the record is the metadata pseudo-record
-in the clustered index.
+in the clustered index for instant ADD COLUMN or ALTER TABLE.
+@param[in] rec leaf page record
+@param[in] comp 0 if ROW_FORMAT=REDUNDANT, else nonzero
+@return whether the record is the metadata pseudo-record */
+inline bool rec_is_metadata(const rec_t* rec, ulint comp)
+{
+ bool is = !!(rec_get_info_bits(rec, comp) & REC_INFO_MIN_REC_FLAG);
+ ut_ad(!is || !comp || rec_get_status(rec) == REC_STATUS_INSTANT);
+ return is;
+}
+
+/** Determine if the record is the metadata pseudo-record
+in the clustered index for instant ADD COLUMN or ALTER TABLE.
+@param[in] rec leaf page record
+@param[in] index index of the record
+@return whether the record is the metadata pseudo-record */
+inline bool rec_is_metadata(const rec_t* rec, const dict_index_t& index)
+{
+ bool is = rec_is_metadata(rec, dict_table_is_comp(index.table));
+ ut_ad(!is || index.is_instant());
+ return is;
+}
+
+/** Determine if the record is the metadata pseudo-record
+in the clustered index for instant ADD COLUMN (not other ALTER TABLE).
+@param[in] rec leaf page record
+@param[in] comp 0 if ROW_FORMAT=REDUNDANT, else nonzero
+@return whether the record is the metadata pseudo-record */
+inline bool rec_is_add_metadata(const rec_t* rec, ulint comp)
+{
+ bool is = rec_get_info_bits(rec, comp) == REC_INFO_MIN_REC_FLAG;
+ ut_ad(!is || !comp || rec_get_status(rec) == REC_STATUS_INSTANT);
+ return is;
+}
+
+/** Determine if the record is the metadata pseudo-record
+in the clustered index for instant ADD COLUMN (not other ALTER TABLE).
@param[in] rec leaf page record
@param[in] index index of the record
@return whether the record is the metadata pseudo-record */
-inline bool rec_is_metadata(const rec_t* rec, const dict_index_t* index)
+inline bool rec_is_add_metadata(const rec_t* rec, const dict_index_t& index)
+{
+ bool is = rec_is_add_metadata(rec, dict_table_is_comp(index.table));
+ ut_ad(!is || index.is_instant());
+ return is;
+}
+
+/** Determine if the record is the metadata pseudo-record
+in the clustered index for instant ALTER TABLE (not plain ADD COLUMN).
+@param[in] rec leaf page record
+@param[in] comp 0 if ROW_FORMAT=REDUNDANT, else nonzero
+@return whether the record is the ALTER TABLE metadata pseudo-record */
+inline bool rec_is_alter_metadata(const rec_t* rec, ulint comp)
+{
+ bool is = !(~rec_get_info_bits(rec, comp)
+ & (REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG));
+ ut_ad(!is || rec_is_metadata(rec, comp));
+ return is;
+}
+
+/** Determine if the record is the metadata pseudo-record
+in the clustered index for instant ALTER TABLE (not plain ADD COLUMN).
+@param[in] rec leaf page record
+@param[in] index index of the record
+@return whether the record is the ALTER TABLE metadata pseudo-record */
+inline bool rec_is_alter_metadata(const rec_t* rec, const dict_index_t& index)
{
- bool is = rec_get_info_bits(rec, dict_table_is_comp(index->table))
- & REC_INFO_MIN_REC_FLAG;
- ut_ad(!is || index->is_instant());
- ut_ad(!is || !dict_table_is_comp(index->table)
- || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED);
+ bool is = rec_is_alter_metadata(rec, dict_table_is_comp(index.table));
+ ut_ad(!is || index.is_dummy || index.is_instant());
return is;
}
+/** Determine if a record is delete-marked (not a metadata pseudo-record).
+@param[in] rec record
+@param[in] comp nonzero if ROW_FORMAT!=REDUNDANT
+@return whether the record is a delete-marked user record */
+inline bool rec_is_delete_marked(const rec_t* rec, ulint comp)
+{
+ return (rec_get_info_bits(rec, comp)
+ & (REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG))
+ == REC_INFO_DELETED_FLAG;
+}
+
/** Get the nth field from an index.
@param[in] rec index record
@param[in] index index
@@ -832,6 +890,7 @@ rec_get_nth_cfield(
ulint* len)
{
ut_ad(rec_offs_validate(rec, index, offsets));
+
if (!rec_offs_nth_default(offsets, n)) {
return rec_get_nth_field(rec, offsets, n, len);
}
@@ -978,7 +1037,7 @@ rec_copy(
@param[in] fields data fields
@param[in] n_fields number of data fields
@param[out] extra record header size
-@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED
+@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT
@return total size, in bytes */
ulint
rec_get_converted_size_temp(
@@ -995,7 +1054,7 @@ rec_get_converted_size_temp(
@param[in,out] offsets offsets to the fields; in: rec_offs_n_fields(offsets)
@param[in] n_core number of core fields (index->n_core_fields)
@param[in] def_val default values for non-core fields
-@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED */
+@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */
void
rec_init_offsets_temp(
const rec_t* rec,
@@ -1022,8 +1081,7 @@ rec_init_offsets_temp(
@param[in] index clustered or secondary index
@param[in] fields data fields
@param[in] n_fields number of data fields
-@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED
-*/
+@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */
void
rec_convert_dtuple_to_temp(
rec_t* rec,
@@ -1086,21 +1144,20 @@ rec_get_converted_size_comp_prefix(
ulint n_fields,/*!< in: number of data fields */
ulint* extra) /*!< out: extra size */
MY_ATTRIBUTE((warn_unused_result, nonnull(1,2)));
-/**********************************************************//**
-Determines the size of a data tuple in ROW_FORMAT=COMPACT.
+
+/** Determine the size of a record in ROW_FORMAT=COMPACT.
+@param[in] index record descriptor. dict_table_is_comp()
+ is assumed to hold, even if it doesn't
+@param[in] tuple logical record
+@param[out] extra extra size
@return total size */
ulint
rec_get_converted_size_comp(
-/*========================*/
- const dict_index_t* index, /*!< in: record descriptor;
- dict_table_is_comp() is
- assumed to hold, even if
- it does not */
- rec_comp_status_t status, /*!< in: status bits of the record */
- const dfield_t* fields, /*!< in: array of data fields */
- ulint n_fields,/*!< in: number of data fields */
- ulint* extra) /*!< out: extra size */
- MY_ATTRIBUTE((nonnull(1,3)));
+ const dict_index_t* index,
+ const dtuple_t* tuple,
+ ulint* extra)
+ MY_ATTRIBUTE((nonnull(1,2)));
+
/**********************************************************//**
The following function returns the size of a data tuple when converted to
a physical record.
@@ -1275,7 +1332,7 @@ public:
}
/** Destructor */
- virtual ~rec_printer() {}
+ ~rec_printer() override {}
private:
/** Copy constructor */
diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic
index 1564bdfdcc0..d2f36845e53 100644
--- a/storage/innobase/include/rem0rec.ic
+++ b/storage/innobase/include/rem0rec.ic
@@ -67,7 +67,7 @@ most significant bytes and bits are written below less significant.
001=REC_STATUS_NODE_PTR
010=REC_STATUS_INFIMUM
011=REC_STATUS_SUPREMUM
- 100=REC_STATUS_COLUMNS_ADDED
+ 100=REC_STATUS_INSTANT
1xx=reserved
5 bits heap number
4 8 bits heap number
@@ -451,7 +451,7 @@ rec_get_n_fields(
}
switch (rec_get_status(rec)) {
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
case REC_STATUS_ORDINARY:
return(dict_index_get_n_fields(index));
case REC_STATUS_NODE_PTR:
@@ -547,19 +547,6 @@ rec_set_n_owned_new(
}
}
-#ifdef UNIV_DEBUG
-/** Check if the info bits are valid.
-@param[in] bits info bits to check
-@return true if valid */
-inline
-bool
-rec_info_bits_valid(
- ulint bits)
-{
- return(0 == (bits & ~(REC_INFO_DELETED_FLAG | REC_INFO_MIN_REC_FLAG)));
-}
-#endif /* UNIV_DEBUG */
-
/******************************************************//**
The following function is used to retrieve the info bits of a record.
@return info bits */
@@ -573,7 +560,6 @@ rec_get_info_bits(
const ulint val = rec_get_bit_field_1(
rec, comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
- ut_ad(rec_info_bits_valid(val));
return(val);
}
@@ -586,7 +572,6 @@ rec_set_info_bits_old(
rec_t* rec, /*!< in: old-style physical record */
ulint bits) /*!< in: info bits */
{
- ut_ad(rec_info_bits_valid(bits));
rec_set_bit_field_1(rec, bits, REC_OLD_INFO_BITS,
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
}
@@ -599,7 +584,6 @@ rec_set_info_bits_new(
rec_t* rec, /*!< in/out: new-style physical record */
ulint bits) /*!< in: info bits */
{
- ut_ad(rec_info_bits_valid(bits));
rec_set_bit_field_1(rec, bits, REC_NEW_INFO_BITS,
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
}
@@ -1388,24 +1372,20 @@ rec_get_converted_size(
} else if (index->table->id == DICT_INDEXES_ID) {
/* The column SYS_INDEXES.MERGE_THRESHOLD was
instantly added in MariaDB 10.2.2 (MySQL 5.7). */
+ ut_ad(!index->table->is_temporary());
ut_ad(index->n_fields == DICT_NUM_FIELDS__SYS_INDEXES);
ut_ad(dtuple->n_fields == DICT_NUM_FIELDS__SYS_INDEXES
|| dtuple->n_fields
== DICT_FLD__SYS_INDEXES__MERGE_THRESHOLD);
} else {
ut_ad(dtuple->n_fields >= index->n_core_fields);
- ut_ad(dtuple->n_fields <= index->n_fields);
+ ut_ad(dtuple->n_fields <= index->n_fields
+ || dtuple->is_alter_metadata());
}
#endif
if (dict_table_is_comp(index->table)) {
- return(rec_get_converted_size_comp(
- index,
- static_cast<rec_comp_status_t>(
- dtuple->info_bits
- & REC_NEW_STATUS_MASK),
- dtuple->fields,
- dtuple->n_fields, NULL));
+ return rec_get_converted_size_comp(index, dtuple, NULL);
}
data_size = dtuple_get_data_size(dtuple, 0);
diff --git a/storage/innobase/include/row0ext.h b/storage/innobase/include/row0ext.h
index 11a6bfa4667..251f3125667 100644
--- a/storage/innobase/include/row0ext.h
+++ b/storage/innobase/include/row0ext.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 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
@@ -29,7 +30,7 @@ Created September 2006 Marko Makela
#include "data0types.h"
#include "mem0mem.h"
#include "dict0types.h"
-#include "page0size.h"
+#include "fsp0types.h"
#include "row0types.h"
/********************************************************************//**
@@ -43,7 +44,7 @@ row_ext_create(
in the InnoDB table object, as reported by
dict_col_get_no(); NOT relative to the records
in the clustered index */
- ulint flags, /*!< in: table->flags */
+ const dict_table_t& table, /*!< in: table */
const dtuple_t* tuple, /*!< in: data tuple containing the field
references of the externally stored
columns; must be indexed by col_no;
@@ -91,9 +92,7 @@ struct row_ext_t{
REC_ANTELOPE_MAX_INDEX_COL_LEN or
REC_VERSION_56_MAX_INDEX_COL_LEN depending
on row format */
- page_size_t page_size;
- /*!< page size of the externally stored
- columns */
+ ulint zip_size;/*!< ROW_FORMAT=COMPRESSED page size, or 0 */
ulint len[1]; /*!< prefix lengths; 0 if not cached */
};
diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h
index 9e5360625f4..c8288f58f15 100644
--- a/storage/innobase/include/row0ftsort.h
+++ b/storage/innobase/include/row0ftsort.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 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
@@ -60,8 +60,8 @@ struct fts_psort_t;
struct fts_psort_common_t {
row_merge_dup_t* dup; /*!< descriptor of FTS index */
dict_table_t* new_table; /*!< source table */
- /* Old table page size */
- page_size_t old_page_size;
+ /** Old table page size */
+ ulint old_zip_size;
trx_t* trx; /*!< transaction */
fts_psort_t* all_info; /*!< all parallel sort info */
os_event_t sort_event; /*!< sort event */
@@ -199,19 +199,19 @@ row_merge_create_fts_sort_index(
@param[in] new_table table where indexes are created
@param[in] opt_doc_id_size whether to use 4 bytes instead of 8 bytes
integer to store Doc ID during sort
-@param[in] old_page_size page size of the old table during alter
+@param[in] old_zip_size page size of the old table during alter
@param[out] psort parallel sort info to be instantiated
@param[out] merge parallel merge info to be instantiated
-@return TRUE if all successful */
-ibool
+@return true if all successful */
+bool
row_fts_psort_info_init(
- trx_t* trx,
- row_merge_dup_t* dup,
- const dict_table_t* new_table,
- ibool opt_doc_id_size,
- const page_size_t old_page_size,
- fts_psort_t** psort,
- fts_psort_t** merge)
+ trx_t* trx,
+ row_merge_dup_t*dup,
+ dict_table_t* new_table,
+ bool opt_doc_id_size,
+ ulint old_zip_size,
+ fts_psort_t** psort,
+ fts_psort_t** merge)
MY_ATTRIBUTE((nonnull));
/********************************************************************//**
diff --git a/storage/innobase/include/row0log.h b/storage/innobase/include/row0log.h
index e6f60345703..c4c78b392af 100644
--- a/storage/innobase/include/row0log.h
+++ b/storage/innobase/include/row0log.h
@@ -36,7 +36,7 @@ Created 2011-05-26 Marko Makela
class ut_stage_alter_t;
-extern ulint onlineddl_rowlog_rows;
+extern Atomic_counter<ulint> onlineddl_rowlog_rows;
extern ulint onlineddl_rowlog_pct_used;
extern ulint onlineddl_pct_progress;
diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h
index 8c9b5325c5f..e5798f1f673 100644
--- a/storage/innobase/include/row0mysql.h
+++ b/storage/innobase/include/row0mysql.h
@@ -43,6 +43,7 @@ Created 9/17/2000 Heikki Tuuri
extern ibool row_rollback_on_timeout;
struct row_prebuilt_t;
+class ha_innobase;
/*******************************************************************//**
Frees the blob heap in prebuilt when no longer needed. */
@@ -417,7 +418,7 @@ will remain locked.
@param[in] create_failed true=create table failed
because e.g. foreign key column
@param[in] nonatomic Whether it is permitted to release
- and reacquire dict_operation_lock
+ and reacquire dict_sys.latch
@return error code */
dberr_t
row_drop_table_for_mysql(
@@ -777,10 +778,14 @@ struct row_prebuilt_t {
store it here so that we can return
it to MySQL */
/*----------------------*/
- void* idx_cond; /*!< In ICP, pointer to a ha_innobase,
- passed to innobase_index_cond().
- NULL if index condition pushdown is
- not used. */
+
+ /** Argument of handler_rowid_filter_check(),
+ or NULL if no PRIMARY KEY filter is pushed */
+ ha_innobase* pk_filter;
+
+ /** Argument to handler_index_cond_check(),
+ or NULL if no index condition pushdown (ICP) is used. */
+ ha_innobase* idx_cond;
ulint idx_cond_n_cols;/*!< Number of fields in idx_cond_cols.
0 if and only if idx_cond == NULL. */
/*----------------------*/
diff --git a/storage/innobase/include/row0row.h b/storage/innobase/include/row0row.h
index d4d979cdad5..be451751f56 100644
--- a/storage/innobase/include/row0row.h
+++ b/storage/innobase/include/row0row.h
@@ -74,6 +74,7 @@ row_get_rec_roll_ptr(
#define ROW_BUILD_FOR_PURGE 1 /*!< build row for purge. */
#define ROW_BUILD_FOR_UNDO 2 /*!< build row for undo. */
#define ROW_BUILD_FOR_INSERT 3 /*!< build row for insert. */
+
/*****************************************************************//**
When an insert or purge to a table is performed, this function builds
the entry to be inserted into or purged from an index on the table.
@@ -223,6 +224,24 @@ row_rec_to_index_entry(
mem_heap_t* heap) /*!< in: memory heap from which
the memory needed is allocated */
MY_ATTRIBUTE((warn_unused_result));
+
+/** Convert a metadata record to a data tuple.
+@param[in] rec metadata record
+@param[in] index clustered index after instant ALTER TABLE
+@param[in] offsets rec_get_offsets(rec)
+@param[in,out] heap memory heap for allocations
+@param[in] info_bits the info_bits after an update
+@param[in] pad whether to pad to index->n_fields */
+dtuple_t*
+row_metadata_to_tuple(
+ const rec_t* rec,
+ const dict_index_t* index,
+ const offset_t* offsets,
+ mem_heap_t* heap,
+ ulint info_bits,
+ bool pad)
+ MY_ATTRIBUTE((nonnull,warn_unused_result));
+
/*******************************************************************//**
Builds from a secondary index record a row reference with which we can
search the clustered index record.
diff --git a/storage/innobase/include/row0row.ic b/storage/innobase/include/row0row.ic
index 14f9f47ba7e..c1e9e74ada3 100644
--- a/storage/innobase/include/row0row.ic
+++ b/storage/innobase/include/row0row.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, 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
@@ -39,16 +39,12 @@ row_get_trx_id_offset(
const dict_index_t* index, /*!< in: clustered index */
const offset_t* offsets)/*!< in: record offsets */
{
- ulint pos;
ulint offset;
ulint len;
- ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(NULL, index, offsets));
- pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
-
- offset = rec_get_nth_field_offs(offsets, pos, &len);
+ offset = rec_get_nth_field_offs(offsets, index->db_trx_id(), &len);
ut_ad(len == DATA_TRX_ID_LEN);
diff --git a/storage/innobase/include/row0trunc.h b/storage/innobase/include/row0trunc.h
deleted file mode 100644
index c5f89f7cfdb..00000000000
--- a/storage/innobase/include/row0trunc.h
+++ /dev/null
@@ -1,416 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, 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
-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 Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file include/row0trunc.h
-TRUNCATE implementation
-
-Created 2013-04-25 Krunal Bauskar
-*******************************************************/
-
-#ifndef row0trunc_h
-#define row0trunc_h
-
-#include "row0mysql.h"
-#include "dict0boot.h"
-#include "fil0fil.h"
-#include "srv0start.h"
-
-#include <vector>
-
-/** The information of TRUNCATE log record.
-This class handles the recovery stage of TRUNCATE table. */
-class truncate_t {
-
-public:
- /**
- Constructor
-
- @param old_table_id old table id assigned to table before truncate
- @param new_table_id new table id that will be assigned to table
- after truncate
- @param dir_path directory path */
- truncate_t(
- table_id_t old_table_id,
- table_id_t new_table_id,
- const char* dir_path);
-
- /**
- Constructor
-
- @param log_file_name parse the log file during recovery to populate
- information related to table to truncate */
- truncate_t(const char* log_file_name);
-
- /**
- Consturctor
-
- @param space_id space in which table reisde
- @param name table name
- @param tablespace_flags tablespace flags use for recreating tablespace
- @param log_flags page format flag
- @param recv_lsn lsn of redo log record. */
- truncate_t(
- ulint space_id,
- const char* name,
- ulint tablespace_flags,
- ulint log_flags,
- lsn_t recv_lsn);
-
- /** Destructor */
- ~truncate_t();
-
- /** The index information of MLOG_FILE_TRUNCATE redo record */
- struct index_t {
-
- /* Default copy constructor and destructor should be OK. */
-
- index_t();
-
- /**
- Set the truncate log values for a compressed table.
- @return DB_CORRUPTION or error code */
- dberr_t set(const dict_index_t* index);
-
- typedef std::vector<byte, ut_allocator<byte> > fields_t;
-
- /** Index id */
- index_id_t m_id;
-
- /** Index type */
- ulint m_type;
-
- /** Root Page Number */
- ulint m_root_page_no;
-
- /** New Root Page Number.
- Note: This field is not persisted to TRUNCATE log but used
- during truncate table fix-up for updating SYS_XXXX tables. */
- ulint m_new_root_page_no;
-
- /** Number of index fields */
- ulint m_n_fields;
-
- /** DATA_TRX_ID column position. */
- ulint m_trx_id_pos;
-
- /** Compressed table field meta data, encode by
- page_zip_fields_encode. Empty for non-compressed tables.
- Should be NUL terminated. */
- fields_t m_fields;
- };
-
- /**
- @return the directory path, can be NULL */
- const char* get_dir_path() const
- {
- return(m_dir_path);
- }
-
- /**
- Register index information
-
- @param index index information logged as part of truncate log. */
- void add(index_t& index)
- {
- m_indexes.push_back(index);
- }
-
- /**
- Add table to truncate post recovery.
-
- @param ptr table information need to complete truncate of table. */
- static void add(truncate_t* ptr)
- {
- s_tables.push_back(ptr);
- }
-
- /**
- Clear registered index vector */
- void clear()
- {
- m_indexes.clear();
- }
-
- /**
- @return old table id of the table to truncate */
- table_id_t old_table_id() const
- {
- return(m_old_table_id);
- }
-
- /**
- @return new table id of the table to truncate */
- table_id_t new_table_id() const
- {
- return(m_new_table_id);
- }
-
- /**
- Update root page number in SYS_XXXX tables.
-
- @param trx transaction object
- @param table_id table id for which information needs to
- be updated.
- @param reserve_dict_mutex if TRUE, acquire/release
- dict_sys->mutex around call to pars_sql.
- @param mark_index_corrupted if true, then mark index corrupted
- @return DB_SUCCESS or error code */
- dberr_t update_root_page_no(
- trx_t* trx,
- table_id_t table_id,
- ibool reserve_dict_mutex,
- bool mark_index_corrupted) const;
-
- /** Create an index for a table.
- @param[in] table_name table name, for which to create
- the index
- @param[in,out] space tablespace
- @param[in] index_type type of index to truncate
- @param[in] index_id id of index to truncate
- @param[in] btr_redo_create_info control info for ::btr_create()
- @param[in,out] mtr mini-transaction covering the
- create index
- @return root page no or FIL_NULL on failure */
- inline ulint create_index(
- const char* table_name,
- fil_space_t* space,
- ulint index_type,
- index_id_t index_id,
- const btr_create_t& btr_redo_create_info,
- mtr_t* mtr) const;
-
- /** Create the indexes for a table
- @param[in] table_name table name, for which to create the
- indexes
- @param[in,out] space tablespace
- @param[in] format_flags page format flags
- @return DB_SUCCESS or error code. */
- inline dberr_t create_indexes(
- const char* table_name,
- fil_space_t* space,
- ulint format_flags);
-
- /** Check if index has been modified since TRUNCATE log snapshot
- was recorded.
- @param[in] space tablespace
- @param[in] root_page_no index root page number
- @return true if modified else false */
- inline bool is_index_modified_since_logged(
- const fil_space_t* space,
- ulint root_page_no) const;
-
- /** Drop indexes for a table.
- @param[in,out] space tablespace
- @return DB_SUCCESS or error code. */
- void drop_indexes(fil_space_t* space) const;
-
- /**
- Parses log record during recovery
- @param start_ptr buffer containing log body to parse
- @param end_ptr buffer end
-
- @return DB_SUCCESS or error code */
- dberr_t parse(
- byte* start_ptr,
- const byte* end_ptr);
-
- /** Parse MLOG_TRUNCATE log record from REDO log file during recovery.
- @param[in,out] start_ptr buffer containing log body to parse
- @param[in] end_ptr buffer end
- @param[in] space_id tablespace identifier
- @return parsed upto or NULL. */
- static byte* parse_redo_entry(
- byte* start_ptr,
- const byte* end_ptr,
- ulint space_id);
-
- /**
- Write a log record for truncating a single-table tablespace.
-
- @param start_ptr buffer to write log record
- @param end_ptr buffer end
- @param space_id space id
- @param tablename the table name in the usual
- databasename/tablename format of InnoDB
- @param flags tablespace flags
- @param format_flags page format
- @param lsn lsn while logging */
- dberr_t write(
- byte* start_ptr,
- byte* end_ptr,
- ulint space_id,
- const char* tablename,
- ulint flags,
- ulint format_flags,
- lsn_t lsn) const;
-
- /**
- @return number of indexes parsed from the truncate log record */
- size_t indexes() const;
-
- /**
- Truncate a single-table tablespace. The tablespace must be cached
- in the memory cache.
-
- Note: This is defined in fil0fil.cc because it needs to access some
- types that are local to that file.
-
- @param space_id space id
- @param dir_path directory path
- @param tablename the table name in the usual
- databasename/tablename format of InnoDB
- @param flags tablespace flags
- @param default_size if true, truncate to default size if tablespace
- is being newly re-initialized.
- @return DB_SUCCESS or error */
- static dberr_t truncate(
- ulint space_id,
- const char* dir_path,
- const char* tablename,
- ulint flags,
- bool default_size);
-
- /**
- Fix the table truncate by applying information parsed from TRUNCATE log.
- Fix-up includes re-creating table (drop and re-create indexes)
- @return error code or DB_SUCCESS */
- static dberr_t fixup_tables_in_system_tablespace();
-
- /**
- Fix the table truncate by applying information parsed from TRUNCATE log.
- Fix-up includes re-creating tablespace.
- @return error code or DB_SUCCESS */
- static dberr_t fixup_tables_in_non_system_tablespace();
-
- /**
- Check whether a tablespace was truncated during recovery
- @param space_id tablespace id to check
- @return true if the tablespace was truncated */
- static bool is_tablespace_truncated(ulint space_id);
-
- /** Was tablespace truncated (on crash before checkpoint).
- If the MLOG_TRUNCATE redo-record is still available then tablespace
- was truncated and checkpoint is yet to happen.
- @param[in] space_id tablespace id to check.
- @return true if tablespace was truncated. */
- static bool was_tablespace_truncated(ulint space_id);
-
- /** Get the lsn associated with space.
- @param[in] space_id tablespace id to check.
- @return associated lsn. */
- static lsn_t get_truncated_tablespace_init_lsn(ulint space_id);
-
-private:
- typedef std::vector<index_t, ut_allocator<index_t> > indexes_t;
-
- /** Space ID of tablespace */
- ulint m_space_id;
-
- /** ID of table that is being truncated. */
- table_id_t m_old_table_id;
-
- /** New ID that will be assigned to table on truncation. */
- table_id_t m_new_table_id;
-
- /** Data dir path of tablespace */
- char* m_dir_path;
-
- /** Table name */
- char* m_tablename;
-
- /** Tablespace Flags */
- ulint m_tablespace_flags;
-
- /** Format flags (log flags; stored in page-no field of header) */
- ulint m_format_flags;
-
- /** Index meta-data */
- indexes_t m_indexes;
-
- /** LSN of TRUNCATE log record. */
- lsn_t m_log_lsn;
-
- /** Log file name. */
- char* m_log_file_name;
-
- /** Encryption information of the table */
- fil_encryption_t m_encryption;
- uint32_t m_key_id;
-
- /** Vector of tables to truncate. */
- typedef std::vector<truncate_t*, ut_allocator<truncate_t*> >
- tables_t;
-
- /** Information about tables to truncate post recovery */
- static tables_t s_tables;
-
- /** Information about truncated table
- This is case when truncate is complete but checkpoint hasn't. */
- typedef std::map<ulint, lsn_t> truncated_tables_t;
- static truncated_tables_t s_truncated_tables;
-
-public:
- /** If true then fix-up of table is active and so while creating
- index instead of grabbing information from dict_index_t, grab it
- from parsed truncate log record. */
- static bool s_fix_up_active;
-};
-
-/**
-Parse truncate log file. */
-class TruncateLogParser {
-
-public:
-
- /**
- Scan and Parse truncate log files.
-
- @param dir_path look for log directory in following path
- @return DB_SUCCESS or error code. */
- static dberr_t scan_and_parse(
- const char* dir_path);
-
-private:
- typedef std::vector<char*, ut_allocator<char*> >
- trunc_log_files_t;
-
-private:
- /**
- Scan to find out truncate log file from the given directory path.
-
- @param dir_path look for log directory in following path.
- @param log_files cache to hold truncate log file name found.
- @return DB_SUCCESS or error code. */
- static dberr_t scan(
- const char* dir_path,
- trunc_log_files_t& log_files);
-
- /**
- Parse the log file and populate table to truncate information.
- (Add this table to truncate information to central vector that is then
- used by truncate fix-up routine to fix-up truncate action of the table.)
-
- @param log_file_name log file to parse
- @return DB_SUCCESS or error code. */
- static dberr_t parse(
- const char* log_file_name);
-};
-
-#endif /* row0trunc_h */
diff --git a/storage/innobase/include/row0types.h b/storage/innobase/include/row0types.h
index 5f1e46c6a4d..048b161b884 100644
--- a/storage/innobase/include/row0types.h
+++ b/storage/innobase/include/row0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2018, MariaDB Corporation.
+Copyright (c) 2018, 2020, 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
@@ -24,8 +24,8 @@ Row operation global types
Created 12/27/1996 Heikki Tuuri
*******************************************************/
-#ifndef row0types_h
-#define row0types_h
+#pragma once
+#include "buf0types.h"
struct plan_t;
@@ -146,5 +146,3 @@ public:
return first_use;
}
};
-
-#endif
diff --git a/storage/innobase/include/row0undo.h b/storage/innobase/include/row0undo.h
index a18d154c132..4357a908ca3 100644
--- a/storage/innobase/include/row0undo.h
+++ b/storage/innobase/include/row0undo.h
@@ -82,17 +82,20 @@ that index record. */
enum undo_exec {
UNDO_NODE_FETCH_NEXT = 1, /*!< we should fetch the next
undo log record */
- UNDO_NODE_INSERT, /*!< undo a fresh insert of a
- row to a table */
- UNDO_NODE_MODIFY /*!< undo a modify operation
- (DELETE or UPDATE) on a row
- of a table */
+ /** rollback an insert into persistent table */
+ UNDO_INSERT_PERSISTENT,
+ /** rollback an update (or delete) in a persistent table */
+ UNDO_UPDATE_PERSISTENT,
+ /** rollback an insert into temporary table */
+ UNDO_INSERT_TEMPORARY,
+ /** rollback an update (or delete) in a temporary table */
+ UNDO_UPDATE_TEMPORARY,
};
/** Undo node structure */
struct undo_node_t{
que_common_t common; /*!< node type: QUE_NODE_UNDO */
- enum undo_exec state; /*!< node execution state */
+ undo_exec state; /*!< rollback execution state */
trx_t* trx; /*!< trx for which undo is done */
roll_ptr_t roll_ptr;/*!< roll pointer to undo log record */
trx_undo_rec_t* undo_rec;/*!< undo log record */
diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h
index 51ed7a7f006..a14f8f7b63c 100644
--- a/storage/innobase/include/row0upd.h
+++ b/storage/innobase/include/row0upd.h
@@ -101,19 +101,6 @@ upd_get_field_by_field_no(
bool is_virtual) /*!< in: if it is a virtual column */
MY_ATTRIBUTE((warn_unused_result));
/*********************************************************************//**
-Writes into the redo log the values of trx id and roll ptr and enough info
-to determine their positions within a clustered index record.
-@return new pointer to mlog */
-byte*
-row_upd_write_sys_vals_to_log(
-/*==========================*/
- dict_index_t* index, /*!< in: clustered index */
- trx_id_t trx_id, /*!< in: transaction id */
- roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */
- byte* log_ptr,/*!< pointer to a buffer of size > 20 opened
- in mlog */
- mtr_t* mtr); /*!< in: mtr */
-/*********************************************************************//**
Updates the trx id and roll ptr field in a clustered index record when
a row is updated or marked deleted. */
UNIV_INLINE
@@ -128,18 +115,6 @@ row_upd_rec_sys_fields(
const trx_t* trx, /*!< in: transaction */
roll_ptr_t roll_ptr);/*!< in: DB_ROLL_PTR to the undo log */
/*********************************************************************//**
-Sets the trx id or roll ptr field of a clustered index entry. */
-void
-row_upd_index_entry_sys_field(
-/*==========================*/
- dtuple_t* entry, /*!< in/out: index entry, where the memory
- buffers for sys fields are already allocated:
- the function just copies the new values to
- them */
- dict_index_t* index, /*!< in: clustered index */
- ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
- ib_uint64_t val); /*!< in: value to write */
-/*********************************************************************//**
Creates an update node for a query graph.
@return own: update node */
upd_node_t*
@@ -492,6 +467,14 @@ struct upd_t{
return false;
}
+ /** @return whether this is for a hidden metadata record
+ for instant ALTER TABLE */
+ bool is_metadata() const { return dtuple_t::is_metadata(info_bits); }
+ /** @return whether this is for a hidden metadata record
+ for instant ALTER TABLE (not only ADD COLUMN) */
+ bool is_alter_metadata() const
+ { return dtuple_t::is_alter_metadata(info_bits); }
+
#ifdef UNIV_DEBUG
bool validate() const
{
@@ -505,7 +488,6 @@ struct upd_t{
return(true);
}
#endif // UNIV_DEBUG
-
};
/** Kinds of update operation */
diff --git a/storage/innobase/include/row0upd.ic b/storage/innobase/include/row0upd.ic
index c8e72f45491..85d0322302a 100644
--- a/storage/innobase/include/row0upd.ic
+++ b/storage/innobase/include/row0upd.ic
@@ -167,13 +167,13 @@ row_upd_rec_sys_fields(
const trx_t* trx, /*!< in: transaction */
roll_ptr_t roll_ptr)/*!< in: DB_ROLL_PTR to the undo log */
{
- ut_ad(dict_index_is_clust(index));
+ ut_ad(index->is_primary());
ut_ad(rec_offs_validate(rec, index, offsets));
- if (page_zip) {
- ulint pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
+ if (UNIV_LIKELY_NULL(page_zip)) {
page_zip_write_trx_id_and_roll_ptr(page_zip, rec, offsets,
- pos, trx->id, roll_ptr);
+ index->db_trx_id(),
+ trx->id, roll_ptr);
} else {
ulint offset = index->trx_id_offset;
diff --git a/storage/innobase/include/srv0mon.h b/storage/innobase/include/srv0mon.h
index 049f437fa9b..369892aa287 100644
--- a/storage/innobase/include/srv0mon.h
+++ b/storage/innobase/include/srv0mon.h
@@ -177,7 +177,6 @@ enum monitor_id_t {
MONITOR_OVLD_INDEX_PAGES_WRITTEN,
MONITOR_OVLD_NON_INDEX_PAGES_WRITTEN,
MONITOR_OVLD_PAGES_READ,
- MONITOR_OVLD_PAGES0_READ,
MONITOR_OVLD_INDEX_SEC_REC_CLUSTER_READS,
MONITOR_OVLD_INDEX_SEC_REC_CLUSTER_READS_AVOIDED,
MONITOR_OVLD_BYTE_READ,
@@ -300,7 +299,6 @@ enum monitor_id_t {
MONITOR_TRX_COMMIT_UNDO,
MONITOR_TRX_ROLLBACK,
MONITOR_TRX_ROLLBACK_SAVEPOINT,
- MONITOR_TRX_ROLLBACK_ACTIVE,
MONITOR_TRX_ACTIVE,
MONITOR_RSEG_HISTORY_LEN,
MONITOR_NUM_UNDO_SLOT_USED,
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 4644c1b8a0b..36d50c4a773 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -47,7 +47,6 @@ Created 10/10/1995 Heikki Tuuri
#include "que0types.h"
#include "trx0types.h"
#include "srv0conc.h"
-#include "buf0checksum.h"
#include "fil0fil.h"
#include "mysql/psi/mysql_stage.h"
@@ -144,7 +143,8 @@ struct srv_stats_t
ulint_ctr_1_t n_lock_wait_count;
/** Number of threads currently waiting on database locks */
- simple_atomic_counter<> n_lock_wait_current_count;
+ MY_ALIGNED(CACHE_LINE_SIZE) Atomic_counter<ulint>
+ n_lock_wait_current_count;
/** Number of rows read. */
ulint_ctr_64_t n_rows_read;
@@ -176,9 +176,6 @@ struct srv_stats_t
/** Number of times prefix optimization avoided triggering cluster lookup */
ulint_ctr_64_t n_sec_rec_cluster_reads_avoided;
- /** Number of times page 0 is read from tablespace */
- ulint_ctr_64_t page0_read;
-
/** Number of encryption_get_latest_key_version calls */
ulint_ctr_64_t n_key_requests;
@@ -457,7 +454,7 @@ extern uint srv_fast_shutdown; /*!< If this is 1, do not do a
/** Signal to shut down InnoDB (NULL if shutdown was signaled, or if
running in innodb_read_only mode, srv_read_only_mode) */
-extern st_my_thread_var *srv_running;
+extern std::atomic<st_my_thread_var *> srv_running;
extern ibool srv_innodb_status;
@@ -548,7 +545,6 @@ extern uint srv_sys_space_size_debug;
extern bool srv_log_files_created;
#endif /* UNIV_DEBUG */
-#define SRV_SEMAPHORE_WAIT_EXTENSION 7200
extern ulint srv_dml_needed_delay;
#define SRV_MAX_N_IO_THREADS 130
@@ -912,23 +908,6 @@ srv_purge_wakeup();
/** Shut down the purge threads. */
void srv_purge_shutdown();
-/** Check if tablespace is being truncated.
-(Ignore system-tablespace as we don't re-create the tablespace
-and so some of the action that are suppressed by this function
-for independent tablespace are not applicable to system-tablespace).
-@param space_id space_id to check for truncate action
-@return true if being truncated, false if not being
- truncated or tablespace is system-tablespace. */
-bool
-srv_is_tablespace_truncated(ulint space_id);
-
-/** Check if tablespace was truncated.
-@param[in] space space object to check for truncate action
-@return true if tablespace was truncated and we still have an active
-MLOG_TRUNCATE REDO log record. */
-bool
-srv_was_tablespace_truncated(const fil_space_t* space);
-
#ifdef UNIV_DEBUG
/** Disables master thread. It's used by:
SET GLOBAL innodb_master_thread_disabled_debug = 1 (0).
@@ -983,7 +962,6 @@ struct export_var_t{
ulint innodb_page_size; /*!< srv_page_size */
ulint innodb_pages_created; /*!< buf_pool->stat.n_pages_created */
ulint innodb_pages_read; /*!< buf_pool->stat.n_pages_read*/
- ulint innodb_page0_read; /*!< srv_stats.page0_read */
ulint innodb_pages_written; /*!< buf_pool->stat.n_pages_written */
ulint innodb_row_lock_waits; /*!< srv_n_lock_wait_count */
ulint innodb_row_lock_current_waits; /*!< srv_n_lock_wait_current_count */
diff --git a/storage/innobase/include/sync0arr.ic b/storage/innobase/include/sync0arr.ic
index 9163d5b6614..962226b4934 100644
--- a/storage/innobase/include/sync0arr.ic
+++ b/storage/innobase/include/sync0arr.ic
@@ -44,8 +44,7 @@ sync_array_get()
return(sync_wait_array[0]);
}
- return(sync_wait_array[default_indexer_t<>::get_rnd_index()
- % sync_array_size]);
+ return(sync_wait_array[get_rnd_value() % sync_array_size]);
}
/******************************************************************//**
diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h
index 4e48f1e2720..94f49ff628c 100644
--- a/storage/innobase/include/sync0policy.h
+++ b/storage/innobase/include/sync0policy.h
@@ -30,247 +30,176 @@ Created 2012-08-21 Sunny Bains.
#include "ut0rnd.h"
#include "os0thread.h"
#include "srv0mon.h"
+#include "sync0debug.h"
#ifdef UNIV_DEBUG
-# define MUTEX_MAGIC_N 979585UL
-
-template <typename Mutex>
-class MutexDebug {
-public:
-
- /** For passing context to SyncDebug */
- struct Context : public latch_t {
-
- /** Constructor */
- Context()
- :
- m_mutex(),
- m_filename(),
- m_line(),
- m_thread_id(ULINT_UNDEFINED)
- {
- /* No op */
- }
-
- /** Create the context for SyncDebug
- @param[in] id ID of the latch to track */
- Context(latch_id_t id)
- :
- latch_t(id)
- {
- ut_ad(id != LATCH_ID_NONE);
- }
-
- /** Set to locked state
- @param[in] mutex The mutex to acquire
- @param[in] filename File name from where to acquire
- @param[in] line Line number in filename */
- void locked(
- const Mutex* mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW
- {
- m_mutex = mutex;
-
- my_atomic_storelint(&m_thread_id,
- ulint(os_thread_get_curr_id()));
-
- m_filename = filename;
-
- m_line = line;
- }
-
- /** Reset to unlock state */
- void release()
- UNIV_NOTHROW
- {
- m_mutex = NULL;
-
- my_atomic_storelint(&m_thread_id, ULINT_UNDEFINED);
-
- m_filename = NULL;
-
- m_line = 0;
- }
-
- /** Print information about the latch
- @return the string representation */
- virtual std::string to_string() const
- UNIV_NOTHROW
- {
- std::ostringstream msg;
-
- msg << m_mutex->policy().to_string();
-
- if (m_thread_id != ULINT_UNDEFINED) {
-
- msg << " addr: " << m_mutex
- << " acquired: " << locked_from().c_str();
-
- } else {
- msg << "Not locked";
- }
-
- return(msg.str());
- }
-
- /** @return the name of the file and line number in the file
- from where the mutex was acquired "filename:line" */
- virtual std::string locked_from() const
- {
- std::ostringstream msg;
-
- msg << sync_basename(m_filename) << ":" << m_line;
-
- return(std::string(msg.str()));
- }
-
- /** Mutex to check for lock order violation */
- const Mutex* m_mutex;
-
- /** Filename from where enter was called */
- const char* m_filename;
-
- /** Line mumber in filename */
- unsigned m_line;
-
- /** Thread ID of the thread that own(ed) the mutex */
- ulint m_thread_id;
- };
-
- /** Constructor. */
- MutexDebug()
- :
- m_magic_n(),
- m_context()
- UNIV_NOTHROW
- {
- /* No op */
- }
-
- /* Destructor */
- virtual ~MutexDebug() { }
-
- /** Mutex is being destroyed. */
- void destroy() UNIV_NOTHROW
- {
- ut_ad((ulint)my_atomic_loadlint(&m_context.m_thread_id) == ULINT_UNDEFINED);
-
- m_magic_n = 0;
-
- m_context.m_thread_id = 0;
- }
-
- /** Called when the mutex is "created". Note: Not from the constructor
- but when the mutex is initialised.
- @param[in] id Mutex ID */
- void init(latch_id_t id) UNIV_NOTHROW;
-
- /** Called when an attempt is made to lock the mutex
- @param[in] mutex Mutex instance to be locked
- @param[in] filename Filename from where it was called
- @param[in] line Line number from where it was called */
- void enter(
- const Mutex* mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW;
-
- /** Called when the mutex is locked
- @param[in] mutex Mutex instance that was locked
- @param[in] filename Filename from where it was called
- @param[in] line Line number from where it was called */
- void locked(
- const Mutex* mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW;
-
- /** Called when the mutex is released
- @param[in] mutx Mutex that was released */
- void release(const Mutex* mutex)
- UNIV_NOTHROW;
-
- /** @return true if thread owns the mutex */
- bool is_owned() const UNIV_NOTHROW
- {
- return(os_thread_eq(
- (os_thread_id_t)my_atomic_loadlint(&m_context.m_thread_id),
- os_thread_get_curr_id()));
- }
-
- /** @return the name of the file from the mutex was acquired */
- const char* get_enter_filename() const
- UNIV_NOTHROW
- {
- return(m_context.m_filename);
- }
-
- /** @return the name of the file from the mutex was acquired */
- unsigned get_enter_line() const
- UNIV_NOTHROW
- {
- return(m_context.m_line);
- }
-
- /** @return id of the thread that was trying to acquire the mutex */
- os_thread_id_t get_thread_id() const
- UNIV_NOTHROW
- {
- return((os_thread_id_t)my_atomic_loadlint(&m_context.m_thread_id));
- }
+template <typename Mutex> class MutexDebug: public latch_t
+{
+ /** Mutex to check for lock order violation */
+ const Mutex *m_mutex;
+ /** Filename from where enter was called */
+ const char *m_filename;
+ /** Line mumber in filename */
+ unsigned m_line;
+ /** Thread ID of the thread that owns the mutex */
+ os_thread_id_t m_thread_id;
+ /** Mutex protecting the above members */
+ mutable OSMutex m_debug_mutex;
+
+
+ void set(const Mutex *mutex, const char *filename, unsigned line,
+ os_thread_id_t thread_id)
+ {
+ m_debug_mutex.enter();
+ m_mutex= mutex;
+ m_filename= filename;
+ m_line= line;
+ m_thread_id= thread_id;
+ m_debug_mutex.exit();
+ }
+
+
+ const MutexDebug get() const
+ {
+ MutexDebug ret;
+ m_debug_mutex.enter();
+ ret.m_mutex= m_mutex;
+ ret.m_filename= m_filename;
+ ret.m_line= m_line;
+ ret.m_thread_id= m_thread_id;
+ m_debug_mutex.exit();
+ return ret;
+ }
+
+
+ /**
+ Called either when mutex is locked or destroyed. Thus members are protected
+ from concurrent modification.
+ */
+ void assert_clean_context()
+ {
+ ut_ad(!m_mutex);
+ ut_ad(!m_filename);
+ ut_ad(!m_line);
+ ut_ad(m_thread_id == os_thread_id_t(ULINT_UNDEFINED));
+ }
- /** Magic number to check for memory corruption. */
- ulint m_magic_n;
- /** Latch state of the mutex owner */
- Context m_context;
+public:
+ /**
+ Called when the mutex is "created". Note: Not from the constructor
+ but when the mutex is initialised.
+ @param[in] id Mutex ID
+ */
+ void init(latch_id_t id)
+ {
+ ut_ad(id != LATCH_ID_NONE);
+ m_id= id;
+ m_debug_mutex.init();
+ set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED));
+ }
+
+
+ /** Mutex is being destroyed. */
+ void destroy()
+ {
+ assert_clean_context();
+ m_debug_mutex.destroy();
+ }
+
+
+ /**
+ Called when an attempt is made to lock the mutex
+ @param[in] mutex Mutex instance to be locked
+ @param[in] filename Filename from where it was called
+ @param[in] line Line number from where it was called
+ */
+ void enter(const Mutex &mutex, const char *filename, unsigned line)
+ {
+ MutexDebug context;
+ ut_ad(!is_owned());
+ context.init(m_id);
+ context.set(&mutex, filename, line, os_thread_get_curr_id());
+ /* Check for latch order violation. */
+ sync_check_lock_validate(&context);
+ context.set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED));
+ context.destroy();
+ }
+
+
+ /**
+ Called when the mutex is locked
+ @param[in] mutex Mutex instance that was locked
+ @param[in] filename Filename from where it was called
+ @param[in] line Line number from where it was called
+ */
+ void locked(const Mutex &mutex, const char *filename, unsigned line)
+ {
+ assert_clean_context();
+ set(&mutex, filename, line, os_thread_get_curr_id());
+ sync_check_lock_granted(this);
+ }
+
+
+ /**
+ Called when the mutex is released
+ @param[in] mutex Mutex that was released
+ */
+ void release(const Mutex &mutex)
+ {
+ ut_ad(is_owned());
+ set(0, 0, 0, os_thread_id_t(ULINT_UNDEFINED));
+ sync_check_unlock(this);
+ }
+
+
+ /** @return true if thread owns the mutex */
+ bool is_owned() const
+ {
+ return os_thread_eq(get_thread_id(), os_thread_get_curr_id());
+ }
+
+
+ /** @return the name of the file from the mutex was acquired */
+ const char* get_enter_filename() const { return get().m_filename; }
+
+
+ /** @return the name of the file from the mutex was acquired */
+ unsigned get_enter_line() const { return get().m_line; }
+
+
+ /** @return id of the thread that was trying to acquire the mutex */
+ os_thread_id_t get_thread_id() const { return get().m_thread_id; }
+
+
+ /**
+ Print information about the latch
+ @return the string representation
+ */
+ virtual std::string to_string() const
+ {
+ std::ostringstream msg;
+ const MutexDebug ctx= get();
+
+ msg << m_mutex->policy().to_string();
+ if (ctx.m_mutex)
+ msg << " addr: " << ctx.m_mutex << " acquired: "
+ << sync_basename(ctx.get_enter_filename()) << ":"
+ << ctx.get_enter_line();
+ else
+ msg << "Not locked";
+
+ return(msg.str());
+ }
};
#endif /* UNIV_DEBUG */
-/* Do nothing */
-template <typename Mutex>
-struct NoPolicy {
- /** Default constructor. */
- NoPolicy() { }
-
- void init(const Mutex&, latch_id_t, const char*, uint32_t)
- UNIV_NOTHROW { }
- void destroy() UNIV_NOTHROW { }
- void enter(const Mutex&, const char*, unsigned) UNIV_NOTHROW { }
- void add(uint32_t, uint32_t) UNIV_NOTHROW { }
- void locked(const Mutex&, const char*, ulint) UNIV_NOTHROW { }
- void release(const Mutex&) UNIV_NOTHROW { }
- std::string to_string() const { return(""); };
- latch_id_t get_id() const;
-};
-
/** Collect the metrics per mutex instance, no aggregation. */
template <typename Mutex>
struct GenericPolicy
-#ifdef UNIV_DEBUG
-: public MutexDebug<Mutex>
-#endif /* UNIV_DEBUG */
{
public:
- typedef Mutex MutexType;
-
- /** Constructor. */
- GenericPolicy()
- UNIV_NOTHROW
- :
-#ifdef UNIV_DEBUG
- MutexDebug<MutexType>(),
-#endif /* UNIV_DEBUG */
- m_count(),
- m_id()
- { }
-
- /** Destructor */
- ~GenericPolicy() { }
-
/** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised.
@param[in] id Mutex ID
@@ -292,8 +221,6 @@ public:
meta.get_counter()->single_register(&m_count);
sync_file_created_register(this, filename, uint16_t(line));
-
- ut_d(MutexDebug<MutexType>::init(m_id));
}
/** Called when the mutex is destroyed. */
@@ -305,8 +232,6 @@ public:
meta.get_counter()->single_deregister(&m_count);
sync_file_created_deregister(this);
-
- ut_d(MutexDebug<MutexType>::destroy());
}
/** Called after a successful mutex acquire.
@@ -332,40 +257,6 @@ public:
++m_count.m_calls;
}
- /** Called when an attempt is made to lock the mutex
- @param[in] mutex Mutex instance to be locked
- @param[in] filename Filename from where it was called
- @param[in] line Line number from where it was called */
- void enter(
- const MutexType& mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW
- {
- ut_d(MutexDebug<MutexType>::enter(&mutex, filename, line));
- }
-
- /** Called when the mutex is locked
- @param[in] mutex Mutex instance that is locked
- @param[in] filename Filename from where it was called
- @param[in] line Line number from where it was called */
- void locked(
- const MutexType& mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW
- {
- ut_d(MutexDebug<MutexType>::locked(&mutex, filename, line));
- }
-
- /** Called when the mutex is released
- @param[in] mutex Mutex instance that is released */
- void release(const MutexType& mutex)
- UNIV_NOTHROW
- {
- ut_d(MutexDebug<MutexType>::release(&mutex));
- }
-
/** Print the information about the latch
@return the string representation */
std::string print() const
@@ -378,14 +269,18 @@ public:
return(m_id);
}
- /** @return the string representation */
- std::string to_string() const;
-private:
- typedef latch_meta_t::CounterType Counter;
+ /** @return the string representation */
+ std::string to_string() const
+ { return sync_mutex_to_string(get_id(), sync_file_created_get(this)); }
- /** The user visible counters, registered with the meta-data. */
- Counter::Count m_count;
+#ifdef UNIV_DEBUG
+ MutexDebug<Mutex> context;
+#endif
+
+private:
+ /** The user visible counters, registered with the meta-data. */
+ latch_meta_t::CounterType::Count m_count;
/** Latch meta data ID */
latch_id_t m_id;
@@ -395,29 +290,8 @@ private:
too many of them to count individually. */
template <typename Mutex>
class BlockMutexPolicy
-#ifdef UNIV_DEBUG
-: public MutexDebug<Mutex>
-#endif /* UNIV_DEBUG */
{
public:
- typedef Mutex MutexType;
- typedef typename latch_meta_t::CounterType::Count Count;
-
- /** Default constructor. */
- BlockMutexPolicy()
- :
-#ifdef UNIV_DEBUG
- MutexDebug<MutexType>(),
-#endif /* UNIV_DEBUG */
- m_count(),
- m_id()
- {
- /* Do nothing */
- }
-
- /** Destructor */
- ~BlockMutexPolicy() { }
-
/** Called when the mutex is "created". Note: Not from the constructor
but when the mutex is initialised.
@param[in] id Mutex ID */
@@ -436,8 +310,6 @@ public:
ut_ad(meta.get_id() == id);
m_count = meta.get_counter()->sum_register();
-
- ut_d(MutexDebug<MutexType>::init(m_id));
}
/** Called when the mutex is destroyed. */
@@ -445,7 +317,6 @@ public:
UNIV_NOTHROW
{
m_count = NULL;
- ut_d(MutexDebug<MutexType>::destroy());
}
/** Called after a successful mutex acquire.
@@ -469,40 +340,6 @@ public:
++m_count->m_calls;
}
- /** Called when the mutex is locked
- @param[in] mutex Mutex instance that is locked
- @param[in] filename Filename from where it was called
- @param[in] line Line number from where it was called */
- void locked(
- const MutexType& mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW
- {
- ut_d(MutexDebug<MutexType>::locked(&mutex, filename, line));
- }
-
- /** Called when the mutex is released
- @param[in] mutex Mutex instance that is released */
- void release(const MutexType& mutex)
- UNIV_NOTHROW
- {
- ut_d(MutexDebug<MutexType>::release(&mutex));
- }
-
- /** Called when an attempt is made to lock the mutex
- @param[in] mutex Mutex instance to be locked
- @param[in] filename Filename from where it was called
- @param[in] line Line number from where it was called */
- void enter(
- const MutexType& mutex,
- const char* filename,
- unsigned line)
- UNIV_NOTHROW
- {
- ut_d(MutexDebug<MutexType>::enter(&mutex, filename, line));
- }
-
/** Print the information about the latch
@return the string representation */
std::string print() const
@@ -514,19 +351,26 @@ public:
return(m_id);
}
- /** @return the string representation */
- std::string to_string() const;
-private:
- typedef latch_meta_t::CounterType Counter;
+ /**
+ I don't think it makes sense to keep track of the file name
+ and line number for each block mutex. Too much of overhead. Use the
+ latch id to figure out the location from the source.
+
+ @return the string representation
+ */
+ std::string to_string() const
+ { return(sync_mutex_to_string(get_id(), "buf0buf.cc:0")); }
+
+#ifdef UNIV_DEBUG
+ MutexDebug<Mutex> context;
+#endif
- /** The user visible counters, registered with the meta-data. */
- Counter::Count* m_count;
+private:
+ /** The user visible counters, registered with the meta-data. */
+ latch_meta_t::CounterType::Count *m_count;
/** Latch meta data ID */
latch_id_t m_id;
};
-
-#include "sync0policy.ic"
-
#endif /* sync0policy_h */
diff --git a/storage/innobase/include/sync0policy.ic b/storage/innobase/include/sync0policy.ic
deleted file mode 100644
index e7aeb2e16bb..00000000000
--- a/storage/innobase/include/sync0policy.ic
+++ /dev/null
@@ -1,101 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2013, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 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
-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 Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/******************************************************************//**
-@file include/sync0policy.ic
-Policy for mutexes.
-
-Created 2012-08-21 Sunny Bains.
-***********************************************************************/
-
-#include "sync0debug.h"
-
-template <typename Mutex>
-std::string GenericPolicy<Mutex>::to_string() const
-{
- return(sync_mutex_to_string(get_id(), sync_file_created_get(this)));
-}
-
-template <typename Mutex>
-std::string BlockMutexPolicy<Mutex>::to_string() const
-{
- /* I don't think it makes sense to keep track of the file name
- and line number for each block mutex. Too much of overhead. Use the
- latch id to figure out the location from the source. */
- return(sync_mutex_to_string(get_id(), "buf0buf.cc:0"));
-}
-
-#ifdef UNIV_DEBUG
-
-template <typename Mutex>
-void MutexDebug<Mutex>::init(latch_id_t id)
- UNIV_NOTHROW
-{
- m_context.m_id = id;
-
- m_context.release();
-
- m_magic_n = MUTEX_MAGIC_N;
-}
-
-template <typename Mutex>
-void MutexDebug<Mutex>::enter(
- const Mutex* mutex,
- const char* name,
- unsigned line)
- UNIV_NOTHROW
-{
- ut_ad(!is_owned());
-
- Context context(m_context.get_id());
-
- context.locked(mutex, name, line);
-
- /* Check for latch order violation. */
-
- sync_check_lock_validate(&context);
-}
-
-template <typename Mutex>
-void MutexDebug<Mutex>::locked(
- const Mutex* mutex,
- const char* name,
- unsigned line)
- UNIV_NOTHROW
-{
- ut_ad(!is_owned());
- ut_ad(m_context.m_thread_id == ULINT_UNDEFINED);
-
- m_context.locked(mutex, name, line);
-
- sync_check_lock_granted(&m_context);
-}
-
-template <typename Mutex>
-void MutexDebug<Mutex>::release(const Mutex*)
- UNIV_NOTHROW
-{
- ut_ad(is_owned());
-
- m_context.release();
-
- sync_check_unlock(&m_context);
-}
-
-#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h
index 5de22c74fa1..bf47cb8fe88 100644
--- a/storage/innobase/include/sync0rw.h
+++ b/storage/innobase/include/sync0rw.h
@@ -569,10 +569,10 @@ struct rw_lock_t
#endif /* UNIV_DEBUG */
{
/** Holds the state of the lock. */
- int32_t lock_word;
+ std::atomic<int32_t> lock_word;
/** 1: there are waiters */
- int32_t waiters;
+ std::atomic<int32_t> waiters;
/** number of granted SX locks. */
volatile ulint sx_recursive;
@@ -625,8 +625,7 @@ struct rw_lock_t
#endif /* UNIV_PFS_RWLOCK */
#ifdef UNIV_DEBUG
- virtual std::string to_string() const;
- virtual std::string locked_from() const;
+ std::string to_string() const override;
/** In the debug version: pointer to the debug info list of the lock */
UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
@@ -634,7 +633,6 @@ struct rw_lock_t
/** Level in the global latching order. */
latch_level_t level;
#endif /* UNIV_DEBUG */
-
};
#ifdef UNIV_DEBUG
/** The structure for storing debug info of an rw-lock. All access to this
diff --git a/storage/innobase/include/sync0rw.ic b/storage/innobase/include/sync0rw.ic
index 15f8ff3fe62..a1bbf719b7d 100644
--- a/storage/innobase/include/sync0rw.ic
+++ b/storage/innobase/include/sync0rw.ic
@@ -77,8 +77,7 @@ rw_lock_get_writer(
/*===============*/
const rw_lock_t* lock) /*!< in: rw-lock */
{
- int32_t lock_word = my_atomic_load32_explicit(const_cast<int32_t*>(&lock->lock_word),
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_word = lock->lock_word.load(std::memory_order_relaxed);
ut_ad(lock_word <= X_LOCK_DECR);
if (lock_word > X_LOCK_HALF_DECR) {
@@ -110,8 +109,7 @@ rw_lock_get_reader_count(
/*=====================*/
const rw_lock_t* lock) /*!< in: rw-lock */
{
- int32_t lock_word = my_atomic_load32_explicit(const_cast<int32_t*>(&lock->lock_word),
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_word = lock->lock_word.load(std::memory_order_relaxed);
ut_ad(lock_word <= X_LOCK_DECR);
if (lock_word > X_LOCK_HALF_DECR) {
@@ -147,8 +145,7 @@ rw_lock_get_x_lock_count(
/*=====================*/
const rw_lock_t* lock) /*!< in: rw-lock */
{
- int32_t lock_copy = my_atomic_load32_explicit(const_cast<int32_t*>(&lock->lock_word),
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_copy = lock->lock_word.load(std::memory_order_relaxed);
ut_ad(lock_copy <= X_LOCK_DECR);
if (lock_copy == 0 || lock_copy == -X_LOCK_HALF_DECR) {
@@ -181,8 +178,7 @@ rw_lock_get_sx_lock_count(
const rw_lock_t* lock) /*!< in: rw-lock */
{
#ifdef UNIV_DEBUG
- int32_t lock_copy = my_atomic_load32_explicit(const_cast<int32_t*>(&lock->lock_word),
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_copy = lock->lock_word.load(std::memory_order_relaxed);
ut_ad(lock_copy <= X_LOCK_DECR);
@@ -213,14 +209,15 @@ rw_lock_lock_word_decr(
int32_t amount, /*!< in: amount to decrement */
int32_t threshold) /*!< in: threshold of judgement */
{
- int32_t lock_copy = my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_copy = lock->lock_word.load(std::memory_order_relaxed);
+
while (lock_copy > threshold) {
- if (my_atomic_cas32_strong_explicit(&lock->lock_word,
- &lock_copy,
- lock_copy - amount,
- MY_MEMORY_ORDER_ACQUIRE,
- MY_MEMORY_ORDER_RELAXED)) {
+ if (lock->lock_word.compare_exchange_strong(
+ lock_copy,
+ lock_copy - amount,
+ std::memory_order_acquire,
+ std::memory_order_relaxed)) {
+
return(true);
}
}
@@ -304,9 +301,9 @@ rw_lock_x_lock_func_nowait(
{
int32_t oldval = X_LOCK_DECR;
- if (my_atomic_cas32_strong_explicit(&lock->lock_word, &oldval, 0,
- MY_MEMORY_ORDER_ACQUIRE,
- MY_MEMORY_ORDER_RELAXED)) {
+ if (lock->lock_word.compare_exchange_strong(oldval, 0,
+ std::memory_order_acquire,
+ std::memory_order_relaxed)) {
lock->writer_thread = os_thread_get_curr_id();
} else if (os_thread_eq(lock->writer_thread, os_thread_get_curr_id())) {
@@ -316,12 +313,12 @@ rw_lock_x_lock_func_nowait(
observe consistent values. */
if (oldval == 0 || oldval == -X_LOCK_HALF_DECR) {
/* There are 1 x-locks */
- my_atomic_add32_explicit(&lock->lock_word, -X_LOCK_DECR,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_sub(X_LOCK_DECR,
+ std::memory_order_relaxed);
} else if (oldval <= -X_LOCK_DECR) {
/* There are 2 or more x-locks */
- my_atomic_add32_explicit(&lock->lock_word, -1,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_sub(1,
+ std::memory_order_relaxed);
/* Watch for too many recursive locks */
ut_ad(oldval < 1);
} else {
@@ -356,8 +353,7 @@ rw_lock_s_unlock_func(
rw_lock_t* lock) /*!< in/out: rw-lock */
{
#ifdef UNIV_DEBUG
- int32_t dbg_lock_word = my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED);
+ auto dbg_lock_word = lock->lock_word.load(std::memory_order_relaxed);
ut_ad(dbg_lock_word > -X_LOCK_DECR);
ut_ad(dbg_lock_word != 0);
ut_ad(dbg_lock_word < X_LOCK_DECR);
@@ -366,8 +362,8 @@ rw_lock_s_unlock_func(
ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_S));
/* Increment lock_word to indicate 1 less reader */
- int32_t lock_word = my_atomic_add32_explicit(&lock->lock_word, 1,
- MY_MEMORY_ORDER_RELEASE) + 1;
+ auto lock_word = lock->lock_word.fetch_add(
+ 1, std::memory_order_release) + 1;
if (lock_word == 0 || lock_word == -X_LOCK_HALF_DECR) {
/* wait_ex waiter exists. It may not be asleep, but we signal
@@ -393,8 +389,7 @@ rw_lock_x_unlock_func(
#endif /* UNIV_DEBUG */
rw_lock_t* lock) /*!< in/out: rw-lock */
{
- int32_t lock_word = my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_word = lock->lock_word.load(std::memory_order_relaxed);
ut_ad(lock_word == 0 || lock_word == -X_LOCK_HALF_DECR
|| lock_word <= -X_LOCK_DECR);
@@ -411,31 +406,29 @@ rw_lock_x_unlock_func(
ACQ_REL due to...
RELEASE: we release rw-lock
ACQUIRE: we want waiters to be loaded after lock_word is stored */
- my_atomic_add32_explicit(&lock->lock_word, X_LOCK_DECR,
- MY_MEMORY_ORDER_ACQ_REL);
+ lock->lock_word.fetch_add(X_LOCK_DECR,
+ std::memory_order_acq_rel);
/* This no longer has an X-lock but it may still have
an SX-lock. So it is now free for S-locks by other threads.
We need to signal read/write waiters.
We do not need to signal wait_ex waiters, since they cannot
exist when there is a writer. */
- if (my_atomic_load32_explicit(&lock->waiters,
- MY_MEMORY_ORDER_RELAXED)) {
- my_atomic_store32_explicit(&lock->waiters, 0,
- MY_MEMORY_ORDER_RELAXED);
+ if (lock->waiters.load(std::memory_order_relaxed)) {
+ lock->waiters.store(0, std::memory_order_relaxed);
os_event_set(lock->event);
sync_array_object_signalled();
}
} else if (lock_word == -X_LOCK_DECR
|| lock_word == -(X_LOCK_DECR + X_LOCK_HALF_DECR)) {
/* There are 2 x-locks */
- my_atomic_add32_explicit(&lock->lock_word, X_LOCK_DECR,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_add(X_LOCK_DECR,
+ std::memory_order_relaxed);
} else {
/* There are more than 2 x-locks. */
ut_ad(lock_word < -X_LOCK_DECR);
- my_atomic_add32_explicit(&lock->lock_word, 1,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_add(1,
+ std::memory_order_relaxed);
}
ut_ad(rw_lock_validate(lock));
@@ -461,8 +454,8 @@ rw_lock_sx_unlock_func(
ut_d(rw_lock_remove_debug_info(lock, pass, RW_LOCK_SX));
if (lock->sx_recursive == 0) {
- int32_t lock_word = my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_word =
+ lock->lock_word.load(std::memory_order_relaxed);
/* Last caller in a possible recursive chain. */
if (lock_word > 0) {
lock->writer_thread = 0;
@@ -472,17 +465,15 @@ rw_lock_sx_unlock_func(
ACQ_REL due to...
RELEASE: we release rw-lock
ACQUIRE: we want waiters to be loaded after lock_word is stored */
- my_atomic_add32_explicit(&lock->lock_word, X_LOCK_HALF_DECR,
- MY_MEMORY_ORDER_ACQ_REL);
+ lock->lock_word.fetch_add(X_LOCK_HALF_DECR,
+ std::memory_order_acq_rel);
/* Lock is now free. May have to signal read/write
waiters. We do not need to signal wait_ex waiters,
since they cannot exist when there is an sx-lock
holder. */
- if (my_atomic_load32_explicit(&lock->waiters,
- MY_MEMORY_ORDER_RELAXED)) {
- my_atomic_store32_explicit(&lock->waiters, 0,
- MY_MEMORY_ORDER_RELAXED);
+ if (lock->waiters.load(std::memory_order_relaxed)) {
+ lock->waiters.store(0, std::memory_order_relaxed);
os_event_set(lock->event);
sync_array_object_signalled();
}
@@ -490,8 +481,8 @@ rw_lock_sx_unlock_func(
/* still has x-lock */
ut_ad(lock_word == -X_LOCK_HALF_DECR ||
lock_word <= -(X_LOCK_DECR + X_LOCK_HALF_DECR));
- my_atomic_add32_explicit(&lock->lock_word, X_LOCK_HALF_DECR,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_add(X_LOCK_HALF_DECR,
+ std::memory_order_relaxed);
}
}
diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h
index 12936c04b70..e2b5354d2de 100644
--- a/storage/innobase/include/sync0types.h
+++ b/storage/innobase/include/sync0types.h
@@ -28,7 +28,6 @@ Created 9/5/1995 Heikki Tuuri
#define sync0types_h
#include <vector>
-#include <my_atomic.h>
#include "ut0new.h"
@@ -999,9 +998,6 @@ struct latch_t {
@return the string representation */
virtual std::string to_string() const = 0;
- /** @return "filename:line" from where the latch was last locked */
- virtual std::string locked_from() const = 0;
-
/** @return the latch level */
latch_level_t get_level() const
UNIV_NOTHROW
@@ -1042,7 +1038,7 @@ struct sync_checker : public sync_check_functor_t
/** Check the latching constraints
@param[in] level The level held by the thread
@return whether a latch violation was detected */
- bool operator()(const latch_level_t level) const
+ bool operator()(const latch_level_t level) const override
{
if (some_allowed) {
switch (level) {
@@ -1086,7 +1082,7 @@ struct sync_allowed_latches : public sync_check_functor_t {
@param[in] latch The latch level to check
@return true if there is a latch violation */
- bool operator()(const latch_level_t level) const
+ bool operator()(const latch_level_t level) const override
{
return(std::find(begin, end, level) == end);
}
@@ -1117,51 +1113,6 @@ enum rw_lock_flag_t {
#endif /* UNIV_INNOCHECKSUM */
-static inline ulint my_atomic_addlint(ulint *A, ulint B)
-{
-#ifdef _WIN64
- return ulint(my_atomic_add64((volatile int64*)A, B));
-#else
- return ulint(my_atomic_addlong(A, B));
-#endif
-}
-
-static inline ulint my_atomic_loadlint(const ulint *A)
-{
-#ifdef _WIN64
- return ulint(my_atomic_load64((volatile int64*)A));
-#else
- return ulint(my_atomic_loadlong(A));
-#endif
-}
-
-static inline lint my_atomic_addlint(volatile lint *A, lint B)
-{
-#ifdef _WIN64
- return my_atomic_add64((volatile int64*)A, B);
-#else
- return my_atomic_addlong(A, B);
-#endif
-}
-
-static inline lint my_atomic_loadlint(const lint *A)
-{
-#ifdef _WIN64
- return lint(my_atomic_load64((volatile int64*)A));
-#else
- return my_atomic_loadlong(A);
-#endif
-}
-
-static inline void my_atomic_storelint(ulint *A, ulint B)
-{
-#ifdef _WIN64
- my_atomic_store64((volatile int64*)A, B);
-#else
- my_atomic_storelong(A, B);
-#endif
-}
-
/** Simple non-atomic counter aligned to CACHE_LINE_SIZE
@tparam Type the integer type of the counter */
template <typename Type>
@@ -1184,28 +1135,4 @@ private:
/** The counter */
Type m_counter;
};
-
-/** Simple atomic counter aligned to CACHE_LINE_SIZE
-@tparam Type lint or ulint */
-template <typename Type = ulint>
-struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) simple_atomic_counter
-{
- /** Increment the counter */
- Type inc() { return add(1); }
- /** Decrement the counter */
- Type dec() { return add(Type(~0)); }
-
- /** Add to the counter
- @param[in] i amount to be added
- @return the value of the counter before adding */
- Type add(Type i) { return my_atomic_addlint(&m_counter, i); }
-
- /** @return the value of the counter (non-atomic access)! */
- operator Type() const { return m_counter; }
-
-private:
- /** The counter */
- Type m_counter;
-};
-
#endif /* sync0types_h */
diff --git a/storage/innobase/include/trx0purge.h b/storage/innobase/include/trx0purge.h
index 4bc5aded341..7c3343ce7d2 100644
--- a/storage/innobase/include/trx0purge.h
+++ b/storage/innobase/include/trx0purge.h
@@ -140,202 +140,6 @@ private:
TrxUndoRsegs::const_iterator m_iter;
};
-/* Namespace to hold all the related functions and variables need for truncate
-of undo tablespace. */
-namespace undo {
-
- typedef std::vector<ulint> undo_spaces_t;
- typedef std::vector<trx_rseg_t*> rseg_for_trunc_t;
-
- /** Mark completion of undo truncate action by writing magic number to
- the log file and then removing it from the disk.
- If we are going to remove it from disk then why write magic number ?
- This is to safeguard from unlink (file-system) anomalies that will keep
- the link to the file even after unlink action is successfull and
- ref-count = 0.
- @param[in] space_id id of the undo tablespace to truncate.*/
- void done(ulint space_id);
-
- /** Check if TRUNCATE_DDL_LOG file exist.
- @param[in] space_id id of the undo tablespace.
- @return true if exist else false. */
- bool is_log_present(ulint space_id);
-
- /** Track UNDO tablespace mark for truncate. */
- class Truncate {
- public:
- void create()
- {
- m_undo_for_trunc = ULINT_UNDEFINED;
- m_scan_start = 1;
- m_purge_rseg_truncate_frequency =
- ulint(srv_purge_rseg_truncate_frequency);
- }
-
- /** Clear the cached rollback segment. Normally done
- when purge is about to shutdown. */
- void clear()
- {
- reset();
- rseg_for_trunc_t temp;
- m_rseg_for_trunc.swap(temp);
- }
-
- /** Is tablespace selected for truncate.
- @return true if undo tablespace is marked for truncate */
- bool is_marked() const
- {
- return(!(m_undo_for_trunc == ULINT_UNDEFINED));
- }
-
- /** Mark the tablespace for truncate.
- @param[in] undo_id tablespace for truncate. */
- void mark(ulint undo_id)
- {
- m_undo_for_trunc = undo_id;
-
- m_scan_start = (undo_id + 1)
- % (srv_undo_tablespaces_active + 1);
- if (m_scan_start == 0) {
- /* Note: UNDO tablespace ids starts from 1. */
- m_scan_start = 1;
- }
-
- /* We found an UNDO-tablespace to truncate so set the
- local purge rseg truncate frequency to 1. This will help
- accelerate the purge action and in turn truncate. */
- m_purge_rseg_truncate_frequency = 1;
- }
-
- /** Get the tablespace marked for truncate.
- @return tablespace id marked for truncate. */
- ulint get_marked_space_id() const
- {
- return(m_undo_for_trunc);
- }
-
- /** Add rseg to truncate vector.
- @param[in,out] rseg rseg for truncate */
- void add_rseg_to_trunc(trx_rseg_t* rseg)
- {
- m_rseg_for_trunc.push_back(rseg);
- }
-
- /** Get number of rsegs registered for truncate.
- @return return number of rseg that belongs to tablespace mark
- for truncate. */
- ulint rsegs_size() const
- {
- return(m_rseg_for_trunc.size());
- }
-
- /** Get ith registered rseg.
- @param[in] id index of rseg to get.
- @return reference to registered rseg. */
- trx_rseg_t* get_ith_rseg(ulint id)
- {
- ut_ad(id < m_rseg_for_trunc.size());
- return(m_rseg_for_trunc.at(id));
- }
-
- /** Reset for next rseg truncate. */
- void reset()
- {
- m_undo_for_trunc = ULINT_UNDEFINED;
- m_rseg_for_trunc.clear();
-
- /* Sync with global value as we are done with
- truncate now. */
- m_purge_rseg_truncate_frequency = static_cast<ulint>(
- srv_purge_rseg_truncate_frequency);
- }
-
- /** Get the tablespace id to start scanning from.
- @return id of UNDO tablespace to start scanning from. */
- ulint get_scan_start() const
- {
- return(m_scan_start);
- }
-
- /** Check if the tablespace needs fix-up (based on presence of
- DDL truncate log)
- @param space_id space id of the undo tablespace to check
- @return true if fix up is needed else false */
- bool needs_fix_up(ulint space_id) const
- {
- return(is_log_present(space_id));
- }
-
- /** Add undo tablespace to truncate vector.
- @param[in] space_id space id of tablespace to
- truncate */
- static void add_space_to_trunc_list(ulint space_id)
- {
- s_spaces_to_truncate.push_back(space_id);
- }
-
- /** Clear the truncate vector. */
- static void clear_trunc_list()
- {
- s_spaces_to_truncate.clear();
- }
-
- /** Is tablespace marked for truncate.
- @param[in] space_id space id to check
- @return true if marked for truncate, else false. */
- static bool is_tablespace_truncated(ulint space_id)
- {
- return(std::find(s_spaces_to_truncate.begin(),
- s_spaces_to_truncate.end(), space_id)
- != s_spaces_to_truncate.end());
- }
-
- /** Was a tablespace truncated at startup
- @param[in] space_id space id to check
- @return whether space_id was truncated at startup */
- static bool was_tablespace_truncated(ulint space_id)
- {
- return(std::find(s_fix_up_spaces.begin(),
- s_fix_up_spaces.end(),
- space_id)
- != s_fix_up_spaces.end());
- }
-
- /** Get local rseg purge truncate frequency
- @return rseg purge truncate frequency. */
- ulint get_rseg_truncate_frequency() const
- {
- return(m_purge_rseg_truncate_frequency);
- }
-
- private:
- /** UNDO tablespace is mark for truncate. */
- ulint m_undo_for_trunc;
-
- /** rseg that resides in UNDO tablespace is marked for
- truncate. */
- rseg_for_trunc_t m_rseg_for_trunc;
-
- /** Start scanning for UNDO tablespace from this space_id.
- This is to avoid bias selection of one tablespace always. */
- ulint m_scan_start;
-
- /** Rollback segment(s) purge frequency. This is local
- value maintained along with global value. It is set to global
- value on start but when tablespace is marked for truncate it
- is updated to 1 and then minimum value among 2 is used by
- purge action. */
- ulint m_purge_rseg_truncate_frequency;
-
- /** List of UNDO tablespace(s) to truncate. */
- static undo_spaces_t s_spaces_to_truncate;
- public:
- /** Undo tablespaces that were truncated at startup */
- static undo_spaces_t s_fix_up_spaces;
- }; /* class Truncate */
-
-}; /* namespace undo */
-
/** The control structure used in the purge operation */
class purge_sys_t
{
@@ -348,22 +152,19 @@ public:
MY_ALIGNED(CACHE_LINE_SIZE)
rw_lock_t latch;
private:
- /** whether purge is enabled; protected by latch and my_atomic */
- int32_t m_enabled;
+ /** whether purge is enabled; protected by latch and std::atomic */
+ std::atomic<bool> m_enabled;
/** number of pending stop() calls without resume() */
- int32_t m_paused;
+ Atomic_counter<int32_t> m_paused;
public:
que_t* query; /*!< The query graph which will do the
parallelized purge operation */
MY_ALIGNED(CACHE_LINE_SIZE)
ReadView view; /*!< The purge will not remove undo logs
which are >= this view (purge view) */
- /** Total number of tasks submitted by srv_purge_coordinator_thread.
- Not accessed by other threads. */
- ulint n_submitted;
- /** Number of completed tasks. Accessed by srv_purge_coordinator
- and srv_worker_thread by my_atomic. */
- ulint n_completed;
+ /** Number of not completed tasks. Accessed by srv_purge_coordinator
+ and srv_worker_thread by std::atomic. */
+ std::atomic<ulint> n_tasks;
/** Iterator to the undo log records of committed transactions */
struct iterator
@@ -417,9 +218,14 @@ public:
by the pq_mutex */
PQMutex pq_mutex; /*!< Mutex protecting purge_queue */
- undo::Truncate undo_trunc; /*!< Track UNDO tablespace marked
- for truncate. */
-
+ /** Undo tablespace file truncation (only accessed by the
+ srv_purge_coordinator_thread) */
+ struct {
+ /** The undo tablespace that is currently being truncated */
+ fil_space_t* current;
+ /** The undo tablespace that was last truncated */
+ fil_space_t* last;
+ } truncate;
/**
Constructor.
@@ -428,7 +234,7 @@ public:
uninitialised. Real initialisation happens in create().
*/
- purge_sys_t() : event(NULL), m_enabled(false) {}
+ purge_sys_t() : event(NULL), m_enabled(false), n_tasks(0) {}
/** Create the instance */
@@ -438,39 +244,24 @@ public:
void close();
/** @return whether purge is enabled */
- bool enabled()
- {
- return my_atomic_load32_explicit(&m_enabled, MY_MEMORY_ORDER_RELAXED);
- }
- /** @return whether purge is enabled */
- bool enabled_latched()
- {
- ut_ad(rw_lock_own_flagged(&latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
- return bool(m_enabled);
- }
+ bool enabled() { return m_enabled.load(std::memory_order_relaxed); }
/** @return whether the purge coordinator is paused */
bool paused()
- { return my_atomic_load32_explicit(&m_paused, MY_MEMORY_ORDER_RELAXED); }
- /** @return whether the purge coordinator is paused */
- bool paused_latched()
- {
- ut_ad(rw_lock_own_flagged(&latch, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
- return m_paused != 0;
- }
+ { return m_paused != 0; }
/** Enable purge at startup. Not protected by latch; the main thread
will wait for purge_sys.enabled() in srv_start() */
void coordinator_startup()
{
ut_ad(!enabled());
- my_atomic_store32_explicit(&m_enabled, true, MY_MEMORY_ORDER_RELAXED);
+ m_enabled.store(true, std::memory_order_relaxed);
}
/** Disable purge at shutdown */
void coordinator_shutdown()
{
ut_ad(enabled());
- my_atomic_store32_explicit(&m_enabled, false, MY_MEMORY_ORDER_RELAXED);
+ m_enabled.store(false, std::memory_order_relaxed);
}
/** @return whether the purge coordinator thread is active */
diff --git a/storage/innobase/include/trx0roll.h b/storage/innobase/include/trx0roll.h
index d2b873c5647..7f27a054866 100644
--- a/storage/innobase/include/trx0roll.h
+++ b/storage/innobase/include/trx0roll.h
@@ -51,16 +51,6 @@ trx_savept_take(
/*============*/
trx_t* trx); /*!< in: transaction */
-/** Get the last undo log record of a transaction (for rollback).
-@param[in,out] trx transaction
-@param[out] roll_ptr DB_ROLL_PTR to the undo record
-@param[in,out] heap memory heap for allocation
-@return undo log record copied to heap
-@retval NULL if none left or the roll_limit (savepoint) was reached */
-trx_undo_rec_t*
-trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap)
- MY_ATTRIBUTE((nonnull, warn_unused_result));
-
/** Report progress when rolling back a row of a recovered transaction. */
void trx_roll_report_progress();
/*******************************************************************//**
diff --git a/storage/innobase/include/trx0rseg.ic b/storage/innobase/include/trx0rseg.ic
index 687a1d5b8d8..0cff8fa1f5c 100644
--- a/storage/innobase/include/trx0rseg.ic
+++ b/storage/innobase/include/trx0rseg.ic
@@ -41,7 +41,7 @@ trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr)
|| !srv_was_started);
buf_block_t* block = buf_page_get(page_id_t(space->id, page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER);
@@ -67,8 +67,7 @@ trx_rsegf_get_new(
|| !srv_was_started);
ut_ad(space <= TRX_SYS_MAX_UNDO_SPACES || space == SRV_TMP_SPACE_ID);
- block = buf_page_get(
- page_id_t(space, page_no), univ_page_size, RW_X_LATCH, mtr);
+ block = buf_page_get(page_id_t(space, page_no), 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
index 913e2d25172..73f05eb5d48 100644
--- a/storage/innobase/include/trx0sys.h
+++ b/storage/innobase/include/trx0sys.h
@@ -68,17 +68,12 @@ trx_sys_rseg_find_free(const buf_block_t* sys_header);
@param[in] rw whether to lock the page for writing
@return the TRX_SYS page
@retval NULL if the page cannot be read */
-inline
-buf_block_t*
-trx_sysf_get(mtr_t* mtr, bool rw = true)
+inline buf_block_t *trx_sysf_get(mtr_t* mtr, bool rw= true)
{
- buf_block_t* block = buf_page_get(
- page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- univ_page_size, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
- if (block) {
- buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
- }
- return block;
+ buf_block_t* block = buf_page_get(page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
+ 0, rw ? RW_X_LATCH : RW_S_LATCH, mtr);
+ ut_d(if (block) buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);)
+ return block;
}
#ifdef UNIV_DEBUG
@@ -200,14 +195,13 @@ trx_sysf_rseg_get_space(const buf_block_t* sys_header, ulint rseg_id)
@param[in] sys_header TRX_SYS page
@param[in] rseg_id rollback segment identifier
@return undo page number */
-inline
-uint32_t
-trx_sysf_rseg_get_page_no(const buf_block_t* sys_header, ulint rseg_id)
+inline uint32_t
+trx_sysf_rseg_get_page_no(const buf_block_t *sys_header, ulint rseg_id)
{
- ut_ad(rseg_id < TRX_SYS_N_RSEGS);
- return mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO
- + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
- + sys_header->frame);
+ ut_ad(rseg_id < TRX_SYS_N_RSEGS);
+ return mach_read_from_4(TRX_SYS + TRX_SYS_RSEGS + TRX_SYS_RSEG_PAGE_NO +
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE +
+ sys_header->frame);
}
/** Maximum length of MySQL binlog file name, in bytes.
@@ -344,9 +338,9 @@ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID. */
/*-------------------------------------------------------------*/
/** Contents of TRX_SYS_DOUBLEWRITE_MAGIC */
-#define TRX_SYS_DOUBLEWRITE_MAGIC_N 536853855
+constexpr uint32_t TRX_SYS_DOUBLEWRITE_MAGIC_N= 536853855;
/** Contents of TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED */
-#define TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N 1783657386
+constexpr uint32_t TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N= 1783657386;
/** Size of the doublewrite block in pages */
#define TRX_SYS_DOUBLEWRITE_BLOCK_SIZE FSP_EXTENT_SIZE
@@ -369,7 +363,7 @@ struct rw_trx_hash_element_t
trx_id_t id; /* lf_hash_init() relies on this to be first in the struct */
- trx_id_t no;
+ Atomic_counter<trx_id_t> no;
trx_t *trx;
ib_mutex_t mutex;
};
@@ -716,11 +710,7 @@ public:
because it may change even before this method returns.
*/
- uint32_t size()
- {
- return uint32_t(my_atomic_load32_explicit(&hash.count,
- MY_MEMORY_ORDER_RELAXED));
- }
+ uint32_t size() { return uint32_t(lf_hash_size(&hash)); }
/**
@@ -802,7 +792,7 @@ class trx_sys_t
The smallest number not yet assigned as a transaction id or transaction
number. Accessed and updated with atomic operations.
*/
- MY_ALIGNED(CACHE_LINE_SIZE) trx_id_t m_max_trx_id;
+ MY_ALIGNED(CACHE_LINE_SIZE) Atomic_counter<trx_id_t> m_max_trx_id;
/**
@@ -813,17 +803,17 @@ class trx_sys_t
@sa assign_new_trx_no()
@sa snapshot_ids()
*/
- MY_ALIGNED(CACHE_LINE_SIZE) trx_id_t m_rw_trx_hash_version;
+ MY_ALIGNED(CACHE_LINE_SIZE) std::atomic<trx_id_t> m_rw_trx_hash_version;
+ bool m_initialised;
+
+public:
/**
TRX_RSEG_HISTORY list length (number of committed transactions to purge)
*/
- MY_ALIGNED(CACHE_LINE_SIZE) int32 rseg_history_len;
-
- bool m_initialised;
+ MY_ALIGNED(CACHE_LINE_SIZE) Atomic_counter<uint32_t> rseg_history_len;
-public:
/** Mutex protecting trx_list. */
MY_ALIGNED(CACHE_LINE_SIZE) mutable TrxSysMutex mutex;
@@ -899,9 +889,7 @@ public:
trx_id_t get_max_trx_id()
{
- return static_cast<trx_id_t>
- (my_atomic_load64_explicit(reinterpret_cast<int64*>(&m_max_trx_id),
- MY_MEMORY_ORDER_RELAXED));
+ return m_max_trx_id;
}
@@ -943,9 +931,7 @@ public:
void assign_new_trx_no(trx_t *trx)
{
trx->no= get_new_trx_id_no_refresh();
- my_atomic_store64_explicit(reinterpret_cast<int64*>
- (&trx->rw_trx_hash_element->no),
- trx->no, MY_MEMORY_ORDER_RELAXED);
+ trx->rw_trx_hash_element->no= trx->no;
refresh_rw_trx_hash_version();
}
@@ -996,7 +982,8 @@ public:
/** Initialiser for m_max_trx_id and m_rw_trx_hash_version. */
void init_max_trx_id(trx_id_t value)
{
- m_max_trx_id= m_rw_trx_hash_version= value;
+ m_max_trx_id= value;
+ m_rw_trx_hash_version.store(value, std::memory_order_relaxed);
}
@@ -1118,22 +1105,6 @@ public:
return count;
}
- /** @return number of committed transactions waiting for purge */
- ulint history_size() const
- {
- return uint32(my_atomic_load32(&const_cast<trx_sys_t*>(this)
- ->rseg_history_len));
- }
- /** Add to the TRX_RSEG_HISTORY length (on database startup). */
- void history_add(int32 len)
- {
- my_atomic_add32(&rseg_history_len, len);
- }
- /** Register a committed transaction. */
- void history_insert() { history_add(1); }
- /** Note that a committed transaction was purged. */
- void history_remove() { history_add(-1); }
-
private:
static my_bool get_min_trx_id_callback(rw_trx_hash_element_t *element,
trx_id_t *id)
@@ -1164,8 +1135,7 @@ private:
{
if (element->id < arg->m_id)
{
- trx_id_t no= static_cast<trx_id_t>(my_atomic_load64_explicit(
- reinterpret_cast<int64*>(&element->no), MY_MEMORY_ORDER_RELAXED));
+ trx_id_t no= element->no;
arg->m_ids->push_back(element->id);
if (no < arg->m_no)
arg->m_no= no;
@@ -1177,18 +1147,14 @@ private:
/** Getter for m_rw_trx_hash_version, must issue ACQUIRE memory barrier. */
trx_id_t get_rw_trx_hash_version()
{
- return static_cast<trx_id_t>
- (my_atomic_load64_explicit(reinterpret_cast<int64*>
- (&m_rw_trx_hash_version),
- MY_MEMORY_ORDER_ACQUIRE));
+ return m_rw_trx_hash_version.load(std::memory_order_acquire);
}
/** Increments m_rw_trx_hash_version, must issue RELEASE memory barrier. */
void refresh_rw_trx_hash_version()
{
- my_atomic_add64_explicit(reinterpret_cast<int64*>(&m_rw_trx_hash_version),
- 1, MY_MEMORY_ORDER_RELEASE);
+ m_rw_trx_hash_version.fetch_add(1, std::memory_order_release);
}
@@ -1207,8 +1173,7 @@ private:
trx_id_t get_new_trx_id_no_refresh()
{
- return static_cast<trx_id_t>(my_atomic_add64_explicit(
- reinterpret_cast<int64*>(&m_max_trx_id), 1, MY_MEMORY_ORDER_RELAXED));
+ return m_max_trx_id++;
}
};
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 8cd4d2018c6..738f725c60d 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -460,6 +460,7 @@ Check transaction state */
ut_ad((t)->lock.table_locks.empty()); \
ut_ad(!(t)->autoinc_locks \
|| ib_vector_is_empty((t)->autoinc_locks)); \
+ ut_ad(UT_LIST_GET_LEN((t)->lock.evicted_tables) == 0); \
ut_ad((t)->dict_operation == TRX_DICT_OP_NONE); \
} while(0)
@@ -558,6 +559,11 @@ struct trx_lock_t {
lock_sys.mutex. Otherwise, this may
only be modified by the thread that is
serving the running transaction. */
+#ifdef WITH_WSREP
+ bool was_chosen_as_wsrep_victim;
+ /*!< high priority wsrep thread has
+ marked this trx to abort */
+#endif /* WITH_WSREP */
/** Pre-allocated record locks */
struct {
@@ -584,6 +590,9 @@ struct trx_lock_t {
lock_list table_locks; /*!< All table locks requested by this
transaction, including AUTOINC locks */
+ /** List of pending trx_t::evict_table() */
+ UT_LIST_BASE_NODE_T(dict_table_t) evicted_tables;
+
bool cancel; /*!< true if the transaction is being
rolled back either via deadlock
detection or due to lock timeout. The
@@ -674,7 +683,7 @@ with exactly one user transaction. There are some exceptions to this:
* For DDL operations, a subtransaction is allocated that modifies the
data dictionary tables. Lock waits and deadlocks are prevented by
-acquiring the dict_operation_lock before starting the subtransaction
+acquiring the dict_sys.latch before starting the subtransaction
and releasing it after committing the subtransaction.
* The purge system uses a special transaction that is not associated
@@ -750,7 +759,7 @@ private:
that it is no longer "active".
*/
- int32_t n_ref;
+ Atomic_counter<int32_t> n_ref;
public:
@@ -905,8 +914,8 @@ public:
ib_uint32_t dict_operation_lock_mode;
/*!< 0, RW_S_LATCH, or RW_X_LATCH:
the latch mode trx currently holds
- on dict_operation_lock. Protected
- by dict_operation_lock. */
+ on dict_sys.latch. Protected
+ by dict_sys.latch. */
/** wall-clock time of the latest transition to TRX_STATE_ACTIVE;
used for diagnostic purposes only */
@@ -1112,19 +1121,23 @@ public:
/** Release any explicit locks of a committing transaction. */
inline void release_locks();
+ /** Evict a table definition due to the rollback of ALTER TABLE.
+ @param[in] table_id table identifier */
+ void evict_table(table_id_t table_id);
+
bool is_referenced()
{
- return my_atomic_load32_explicit(&n_ref, MY_MEMORY_ORDER_RELAXED) > 0;
+ return n_ref > 0;
}
void reference()
{
#ifdef UNIV_DEBUG
- int32_t old_n_ref=
+ auto old_n_ref=
#endif
- my_atomic_add32_explicit(&n_ref, 1, MY_MEMORY_ORDER_RELAXED);
+ n_ref++;
ut_ad(old_n_ref >= 0);
}
@@ -1132,9 +1145,9 @@ public:
void release_reference()
{
#ifdef UNIV_DEBUG
- int32_t old_n_ref=
+ auto old_n_ref=
#endif
- my_atomic_add32_explicit(&n_ref, -1, MY_MEMORY_ORDER_RELAXED);
+ n_ref--;
ut_ad(old_n_ref > 0);
}
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index 7be4314ecbc..ce92e5de5e1 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.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
@@ -79,27 +79,22 @@ trx_undo_trx_id_is_insert(
/*======================*/
const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */
MY_ATTRIBUTE((warn_unused_result));
-/*****************************************************************//**
-Writes a roll ptr to an index page. In case that the size changes in
-some future version, this function should be used instead of
-mach_write_... */
-UNIV_INLINE
-void
-trx_write_roll_ptr(
-/*===============*/
- byte* ptr, /*!< in: pointer to memory where
- written */
- roll_ptr_t roll_ptr); /*!< in: roll ptr */
-/*****************************************************************//**
-Reads a roll ptr from an index page. In case that the roll ptr size
-changes in some future version, this function should be used instead of
-mach_read_...
+/** Write DB_ROLL_PTR.
+@param[out] ptr buffer
+@param[in] roll_ptr DB_ROLL_PTR value */
+inline void trx_write_roll_ptr(byte* ptr, roll_ptr_t roll_ptr)
+{
+ compile_time_assert(DATA_ROLL_PTR_LEN == 7);
+ mach_write_to_7(ptr, roll_ptr);
+}
+/** Read DB_ROLL_PTR.
+@param[in] ptr buffer
@return roll ptr */
-UNIV_INLINE
-roll_ptr_t
-trx_read_roll_ptr(
-/*==============*/
- const byte* ptr); /*!< in: pointer to memory from where to read */
+inline roll_ptr_t trx_read_roll_ptr(const byte* ptr)
+{
+ compile_time_assert(DATA_ROLL_PTR_LEN == 7);
+ return mach_read_from_7(ptr);
+}
/** Gets an undo log page and x-latches it.
@param[in] page_id page id
@@ -185,9 +180,7 @@ trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr)
@param[in,out] undo undo log
@param[in] limit all undo logs after this limit will be discarded
@param[in] is_temp whether this is temporary undo log */
-void
-trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp)
- MY_ATTRIBUTE((nonnull));
+void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp);
/** Truncate the head of an undo log.
NOTE that only whole pages are freed; the header page is not
@@ -315,16 +308,17 @@ trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
and delete markings: in short,
modifys (the name 'UPDATE' is a
historical relic) */
-/* States of an undo log segment */
-#define TRX_UNDO_ACTIVE 1 /* contains an undo log of an active
- transaction */
-#define TRX_UNDO_CACHED 2 /* cached for quick reuse */
-#define TRX_UNDO_TO_FREE 3 /* insert undo segment can be freed */
-#define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be
- reused: it can be freed in purge when
- all undo data in it is removed */
-#define TRX_UNDO_PREPARED 5 /* contains an undo log of an
- prepared transaction */
+/* TRX_UNDO_STATE values of an undo log segment */
+/** contains an undo log of an active transaction */
+constexpr uint16_t TRX_UNDO_ACTIVE = 1;
+/** cached for quick reuse */
+constexpr uint16_t TRX_UNDO_CACHED = 2;
+/** old_insert undo segment that can be freed */
+constexpr uint16_t TRX_UNDO_TO_FREE = 3;
+/** can be freed in purge when all undo data in it is removed */
+constexpr uint16_t TRX_UNDO_TO_PURGE = 4;
+/** contains an undo log of a prepared transaction */
+constexpr uint16_t TRX_UNDO_PREPARED = 5;
#ifndef UNIV_INNOCHECKSUM
diff --git a/storage/innobase/include/trx0undo.ic b/storage/innobase/include/trx0undo.ic
index 19697c6054c..6d1ec16869e 100644
--- a/storage/innobase/include/trx0undo.ic
+++ b/storage/innobase/include/trx0undo.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2013, 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
@@ -103,37 +103,6 @@ trx_undo_trx_id_is_insert(
return bool(trx_id[DATA_TRX_ID_LEN] >> 7);
}
-/*****************************************************************//**
-Writes a roll ptr to an index page. In case that the size changes in
-some future version, this function should be used instead of
-mach_write_... */
-UNIV_INLINE
-void
-trx_write_roll_ptr(
-/*===============*/
- byte* ptr, /*!< in: pointer to memory where
- written */
- roll_ptr_t roll_ptr) /*!< in: roll ptr */
-{
- compile_time_assert(DATA_ROLL_PTR_LEN == 7);
- mach_write_to_7(ptr, roll_ptr);
-}
-
-/*****************************************************************//**
-Reads a roll ptr from an index page. In case that the roll ptr size
-changes in some future version, this function should be used instead of
-mach_read_...
-@return roll ptr */
-UNIV_INLINE
-roll_ptr_t
-trx_read_roll_ptr(
-/*==============*/
- const byte* ptr) /*!< in: pointer to memory from where to read */
-{
- compile_time_assert(DATA_ROLL_PTR_LEN == 7);
- return(mach_read_from_7(ptr));
-}
-
/** Gets an undo log page and x-latches it.
@param[in] page_id page id
@param[in,out] mtr mini-transaction
@@ -142,8 +111,7 @@ UNIV_INLINE
page_t*
trx_undo_page_get(const page_id_t page_id, mtr_t* mtr)
{
- buf_block_t* block = buf_page_get(page_id, univ_page_size,
- RW_X_LATCH, mtr);
+ buf_block_t* block = buf_page_get(page_id, 0, RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
@@ -158,8 +126,7 @@ UNIV_INLINE
page_t*
trx_undo_page_get_s_latched(const page_id_t page_id, mtr_t* mtr)
{
- buf_block_t* block = buf_page_get(page_id, univ_page_size,
- RW_S_LATCH, mtr);
+ buf_block_t* block = buf_page_get(page_id, 0, RW_S_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i
index ab30024116e..e9d427e04c0 100644
--- a/storage/innobase/include/univ.i
+++ b/storage/innobase/include/univ.i
@@ -77,6 +77,7 @@ used throughout InnoDB but do not include too much themselves. They
support cross-platform development and expose comonly used SQL names. */
#include <my_global.h>
+#include "my_counter.h"
/* JAN: TODO: missing 5.7 header */
#ifdef HAVE_MY_THREAD_H
diff --git a/storage/innobase/include/ut0counter.h b/storage/innobase/include/ut0counter.h
index a04a674751c..646a5f367c2 100644
--- a/storage/innobase/include/ut0counter.h
+++ b/storage/innobase/include/ut0counter.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 2015, 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
@@ -30,7 +30,6 @@ Created 2012/04/12 by Sunny Bains
#include "os0thread.h"
#include "my_rdtsc.h"
-#include "my_atomic.h"
/** CPU cache line size */
#ifdef CPU_LEVEL1_DCACHE_LINESIZE
@@ -42,120 +41,85 @@ Created 2012/04/12 by Sunny Bains
/** Default number of slots to use in ib_counter_t */
#define IB_N_SLOTS 64
-/** Get the offset into the counter array. */
-template <typename Type, int N>
-struct generic_indexer_t {
- /** @return offset within m_counter */
- static size_t offset(size_t index) UNIV_NOTHROW
- {
- return(((index % N) + 1) * (CACHE_LINE_SIZE / sizeof(Type)));
- }
-};
+/** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles
+as a random value. See the comments for my_timer_cycles() */
+/** @return result from RDTSC or similar functions. */
+static inline size_t
+get_rnd_value()
+{
+ size_t c = static_cast<size_t>(my_timer_cycles());
+
+ if (c != 0) {
+ return c;
+ }
-/** Use the result of my_timer_cycles(), which mainly uses RDTSC for cycles,
-to index into the counter array. See the comments for my_timer_cycles() */
-template <typename Type=ulint, int N=1>
-struct counter_indexer_t : public generic_indexer_t<Type, N> {
- /** @return result from RDTSC or similar functions. */
- static size_t get_rnd_index() UNIV_NOTHROW
- {
- size_t c = static_cast<size_t>(my_timer_cycles());
-
- if (c != 0) {
- return(c);
- } else {
- /* We may go here if my_timer_cycles() returns 0,
- so we have to have the plan B for the counter. */
+ /* We may go here if my_timer_cycles() returns 0,
+ so we have to have the plan B for the counter. */
#if !defined(_WIN32)
- return(size_t(os_thread_get_curr_id()));
+ return (size_t)os_thread_get_curr_id();
#else
- LARGE_INTEGER cnt;
- QueryPerformanceCounter(&cnt);
+ LARGE_INTEGER cnt;
+ QueryPerformanceCounter(&cnt);
- return(static_cast<size_t>(cnt.QuadPart));
+ return static_cast<size_t>(cnt.QuadPart);
#endif /* !_WIN32 */
- }
- }
+}
- /** @return a random offset to the array */
- static size_t get_rnd_offset() UNIV_NOTHROW
- {
- return(generic_indexer_t<Type, N>::offset(get_rnd_index()));
- }
-};
-
-#define default_indexer_t counter_indexer_t
-
-/** Class for using fuzzy counters. The counter is relaxed atomic
+/** Class for using fuzzy counters. The counter is multi-instance relaxed atomic
so the results are not guaranteed to be 100% accurate but close
enough. Creates an array of counters and separates each element by the
CACHE_LINE_SIZE bytes */
-template <
- typename Type,
- int N = IB_N_SLOTS,
- template<typename, int> class Indexer = default_indexer_t>
-struct MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_t
-{
+template <typename Type, int N = IB_N_SLOTS>
+struct ib_counter_t {
/** Increment the counter by 1. */
- void inc() UNIV_NOTHROW { add(1); }
+ void inc() { add(1); }
/** Increment the counter by 1.
@param[in] index a reasonably thread-unique identifier */
- void inc(size_t index) UNIV_NOTHROW { add(index, 1); }
+ void inc(size_t index) { add(index, 1); }
/** Add to the counter.
@param[in] n amount to be added */
- void add(Type n) UNIV_NOTHROW { add(m_policy.get_rnd_offset(), n); }
+ void add(Type n) { add(get_rnd_value(), n); }
/** Add to the counter.
@param[in] index a reasonably thread-unique identifier
@param[in] n amount to be added */
- void add(size_t index, Type n) UNIV_NOTHROW {
- size_t i = m_policy.offset(index);
-
- ut_ad(i < UT_ARR_SIZE(m_counter));
-
- if (sizeof(Type) == 8) {
- my_atomic_add64_explicit(
- reinterpret_cast<int64*>(&m_counter[i]),
- static_cast<int64>(n), MY_MEMORY_ORDER_RELAXED);
- } else if (sizeof(Type) == 4) {
- my_atomic_add32_explicit(
- reinterpret_cast<int32*>(&m_counter[i]),
- static_cast<int32>(n), MY_MEMORY_ORDER_RELAXED);
- }
- compile_time_assert(sizeof(Type) == 8 || sizeof(Type) == 4);
+ void add(size_t index, Type n) {
+ index = index % N;
+
+ ut_ad(index < UT_ARR_SIZE(m_counter));
+
+ m_counter[index].value.fetch_add(n, std::memory_order_relaxed);
}
- /* @return total value - not 100% accurate, since it is relaxed atomic. */
- operator Type() const UNIV_NOTHROW {
+ /* @return total value - not 100% accurate, since it is relaxed atomic*/
+ operator Type() const {
Type total = 0;
- for (size_t i = 0; i < N; ++i) {
- if (sizeof(Type) == 8) {
- total += static_cast<
- Type>(my_atomic_load64_explicit(
- reinterpret_cast<int64*>(const_cast<Type*>(
- &m_counter[m_policy.offset(i)])),
- MY_MEMORY_ORDER_RELAXED));
- } else if (sizeof(Type) == 4) {
- total += static_cast<
- Type>(my_atomic_load32_explicit(
- reinterpret_cast<int32*>(const_cast<Type*>(
- &m_counter[m_policy.offset(i)])),
- MY_MEMORY_ORDER_RELAXED));
- }
+ for (const auto &counter : m_counter) {
+ total += counter.value.load(std::memory_order_relaxed);
}
return(total);
}
private:
- /** Indexer into the array */
- Indexer<Type, N>m_policy;
-
- /** Slot 0 is unused. */
- Type m_counter[(N + 1) * (CACHE_LINE_SIZE / sizeof(Type))];
+ /** Atomic which occupies whole CPU cache line.
+ Note: We rely on the default constructor of std::atomic and
+ do not explicitly initialize the contents. This works for us,
+ because ib_counter_t is only intended for usage with global
+ memory that is allocated from the .bss and thus guaranteed to
+ be zero-initialized by the run-time environment.
+ @see srv_stats
+ @see rw_lock_stats */
+ struct ib_counter_element_t {
+ MY_ALIGNED(CACHE_LINE_SIZE) std::atomic<Type> value;
+ };
+ static_assert(sizeof(ib_counter_element_t) == CACHE_LINE_SIZE, "");
+
+ /** Array of counter elements */
+ MY_ALIGNED(CACHE_LINE_SIZE) ib_counter_element_t m_counter[N];
};
#endif /* ut0counter_h */
diff --git a/storage/innobase/include/ut0crc32.h b/storage/innobase/include/ut0crc32.h
index 68af6882155..f2c1b7e82b6 100644
--- a/storage/innobase/include/ut0crc32.h
+++ b/storage/innobase/include/ut0crc32.h
@@ -47,12 +47,6 @@ typedef uint32_t (*ut_crc32_func_t)(const byte* ptr, ulint len);
/** Pointer to CRC32 calculation function. */
extern ut_crc32_func_t ut_crc32;
-#ifdef INNODB_BUG_ENDIAN_CRC32
-/** Pointer to CRC32 calculation function, which uses big-endian byte order
-when converting byte strings to integers internally. */
-extern uint32_t ut_crc32_legacy_big_endian(const byte* buf, ulint len);
-#endif /* INNODB_BUG_ENDIAN_CRC32 */
-
/** Text description of CRC32 implementation */
extern const char* ut_crc32_implementation;
diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h
index 1f99ee17a24..d7d48cd1f28 100644
--- a/storage/innobase/include/ut0mutex.h
+++ b/storage/innobase/include/ut0mutex.h
@@ -38,8 +38,6 @@ Created 2012-03-24 Sunny Bains.
@param[in] T The resulting typedef alias */
#define UT_MUTEX_TYPE(M, P, T) typedef PolicyMutex<M<P> > T;
-typedef OSMutex EventMutex;
-
# ifdef HAVE_IB_LINUX_FUTEX
UT_MUTEX_TYPE(TTASFutexMutex, GenericPolicy, FutexMutex);
UT_MUTEX_TYPE(TTASFutexMutex, BlockMutexPolicy, BlockFutexMutex);
diff --git a/storage/innobase/include/ut0rnd.h b/storage/innobase/include/ut0rnd.h
index 9af8687bfd0..5b1ae5bc0da 100644
--- a/storage/innobase/include/ut0rnd.h
+++ b/storage/innobase/include/ut0rnd.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2019, MariaDB Corporation.
+Copyright (c) 2019, 2020, 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
@@ -32,7 +32,7 @@ Created 1/20/1994 Heikki Tuuri
#ifndef UNIV_INNOCHECKSUM
/** Seed value of ut_rnd_gen() */
-extern int32 ut_rnd_current;
+extern std::atomic<uint32_t> ut_rnd_current;
/** @return a pseudo-random 32-bit number */
inline uint32_t ut_rnd_gen()
@@ -45,8 +45,7 @@ inline uint32_t ut_rnd_gen()
x^19+x^18+x^14+x^13+x^11+x^10+x^9+x^8+x^6+1 */
const uint32_t crc32c= 0x1edc6f41;
- uint32_t rnd= my_atomic_load32_explicit(&ut_rnd_current,
- MY_MEMORY_ORDER_RELAXED);
+ uint32_t rnd= ut_rnd_current.load(std::memory_order_relaxed);
if (UNIV_UNLIKELY(rnd == 0))
{
@@ -61,7 +60,7 @@ inline uint32_t ut_rnd_gen()
rnd^= crc32c;
}
- my_atomic_store32_explicit(&ut_rnd_current, rnd, MY_MEMORY_ORDER_RELAXED);
+ ut_rnd_current.store(rnd, std::memory_order_relaxed);
return rnd;
}
diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h
index 4b285cf718c..410d2ead738 100644
--- a/storage/innobase/include/ut0ut.h
+++ b/storage/innobase/include/ut0ut.h
@@ -46,7 +46,6 @@ Created 1/20/1994 Heikki Tuuri
#include <stdarg.h>
#include <string>
-#include <my_atomic.h>
/** Index name prefix in fast index creation, as a string constant */
#define TEMP_INDEX_PREFIX_STR "\377"
@@ -146,12 +145,6 @@ ut_2_power_up(
ulint n) /*!< in: number != 0 */
MY_ATTRIBUTE((const));
-/** Determine how many bytes (groups of 8 bits) are needed to
-store the given number of bits.
-@param b in: bits
-@return number of bytes (octets) needed to represent b */
-#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8)
-
/**********************************************************//**
Returns the number of milliseconds since some epoch. The
value may wrap around. It should only be used for heuristic
@@ -162,6 +155,12 @@ ut_time_ms(void);
/*============*/
#endif /* !UNIV_INNOCHECKSUM */
+/** Determine how many bytes (groups of 8 bits) are needed to
+store the given number of bits.
+@param b in: bits
+@return number of bytes (octets) needed to represent b */
+#define UT_BITS_IN_BYTES(b) (((b) + 7) / 8)
+
/** Determines if a number is zero or a power of two.
@param[in] n number
@return nonzero if n is zero or a power of two; zero otherwise */
diff --git a/storage/innobase/innodb.cmake b/storage/innobase/innodb.cmake
index 8bfca3a614b..07ed7ed67ab 100644
--- a/storage/innobase/innodb.cmake
+++ b/storage/innobase/innodb.cmake
@@ -33,7 +33,6 @@ MYSQL_CHECK_LZMA()
MYSQL_CHECK_BZIP2()
MYSQL_CHECK_SNAPPY()
MYSQL_CHECK_NUMA()
-TEST_BIG_ENDIAN(IS_BIG_ENDIAN)
INCLUDE(${MYSQL_CMAKE_SCRIPT_DIR}/compile_flags.cmake)
@@ -122,11 +121,6 @@ ELSEIF(WITH_INNODB_ROOT_GUESS)
ADD_DEFINITIONS(-DBTR_CUR_ADAPT)
ENDIF()
-OPTION(WITH_INNODB_BUG_ENDIAN_CRC32 "Weaken innodb_checksum_algorithm=crc32 by supporting upgrade from big-endian systems running 5.6/10.0/10.1" ${IS_BIG_ENDIAN})
-IF(WITH_INNODB_BUG_ENDIAN_CRC32)
- ADD_DEFINITIONS(-DINNODB_BUG_ENDIAN_CRC32)
-ENDIF()
-
OPTION(WITH_INNODB_EXTRA_DEBUG "Enable extra InnoDB debug checks" OFF)
IF(WITH_INNODB_EXTRA_DEBUG)
ADD_DEFINITIONS(-DUNIV_ZIP_DEBUG)
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index 9ff787282c2..60b8fdb0070 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -328,7 +328,7 @@ lock_report_trx_id_insanity(
trx_id_t max_trx_id) /*!< in: trx_sys.get_max_trx_id() */
{
ut_ad(rec_offs_validate(rec, index, offsets));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
ib::error()
<< "Transaction id " << trx_id
@@ -351,7 +351,7 @@ lock_check_trx_id_sanity(
const offset_t* offsets) /*!< in: rec_get_offsets(rec, index) */
{
ut_ad(rec_offs_validate(rec, index, offsets));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
trx_id_t max_trx_id = trx_sys.get_max_trx_id();
ut_ad(max_trx_id || srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN);
@@ -380,7 +380,7 @@ lock_clust_rec_cons_read_sees(
ut_ad(dict_index_is_clust(index));
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
/* Temp-tables are not shared across connections and multiple
transactions from different connections cannot simultaneously
@@ -419,7 +419,7 @@ lock_sec_rec_cons_read_sees(
{
ut_ad(page_rec_is_user_rec(rec));
ut_ad(!index->is_primary());
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
/* NOTE that we might call this function while holding the search
system latch. */
@@ -758,9 +758,7 @@ lock_rec_has_to_wait(
<< wsrep_thd_query(lock2->trx->mysql_thd);
}
- if (wsrep_trx_order_before(trx->mysql_thd,
- lock2->trx->mysql_thd)
- && (type_mode & LOCK_MODE_MASK) == LOCK_X
+ if ((type_mode & LOCK_MODE_MASK) == LOCK_X
&& (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) {
if (for_locking || wsrep_debug) {
/* exclusive lock conflicts are not
@@ -770,12 +768,11 @@ lock_rec_has_to_wait(
<< type_mode
<< " supremum: " << lock_is_on_supremum
<< "conflicts states: my "
- << wsrep_thd_conflict_state(
- trx->mysql_thd, FALSE)
+ << wsrep_thd_transaction_state_str(
+ trx->mysql_thd)
<< " locked "
- << wsrep_thd_conflict_state(
- lock2->trx->mysql_thd,
- FALSE);
+ << wsrep_thd_transaction_state_str(
+ lock2->trx->mysql_thd);
lock_rec_print(stderr, lock2, mtr);
ib::info() << " SQL1: "
<< wsrep_thd_query(trx->mysql_thd)
@@ -1094,12 +1091,15 @@ wsrep_kill_victim(
return;
}
- my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
+ if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
+ return;
+ }
+
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
mtr_t mtr;
- if ((bf_this && !bf_other) ||
- (bf_this && bf_other && wsrep_trx_order_before(
+ if ((!bf_other) ||
+ (wsrep_thd_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
@@ -1110,11 +1110,7 @@ wsrep_kill_victim(
is in the queue*/
} else if (lock->trx != trx) {
if (wsrep_log_conflicts) {
- if (bf_this) {
- ib::info() << "*** Priority TRANSACTION:";
- } else {
- ib::info() << "*** Victim TRANSACTION:";
- }
+ ib::info() << "*** Priority TRANSACTION:";
trx_print_latched(stderr, trx, 3000);
@@ -1215,7 +1211,7 @@ lock_sec_rec_some_has_impl(
ut_ad(!dict_index_is_clust(index));
ut_ad(page_rec_is_user_rec(rec));
ut_ad(rec_offs_validate(rec, index, offsets));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
max_trx_id = page_get_max_trx_id(page);
@@ -1423,7 +1419,7 @@ lock_rec_create_low(
lock_t *prev = NULL;
while (hash && wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE)
- && wsrep_trx_order_before(hash->trx->mysql_thd,
+ && wsrep_thd_order_before(hash->trx->mysql_thd,
trx->mysql_thd)) {
prev = hash;
hash = (lock_t *)hash->hash;
@@ -1830,15 +1826,15 @@ lock_rec_add_to_queue(
ib::info() << "WSREP BF lock conflict for my lock:\n BF:" <<
((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(trx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(trx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(trx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(trx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " <<
wsrep_thd_query(trx->mysql_thd);
trx_t* otrx = other_lock->trx;
ib::info() << "WSREP other lock:\n BF:" <<
((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " <<
wsrep_thd_query(otrx->mysql_thd);
}
@@ -4244,6 +4240,7 @@ lock_check_dict_lock(
const lock_t* lock) /*!< in: lock to check */
{
if (lock_get_type_low(lock) == LOCK_REC) {
+ ut_ad(!lock->index->table->is_temporary());
/* Check if the transcation locked a record
in a system table in X mode. It should have set
@@ -4257,9 +4254,8 @@ lock_check_dict_lock(
} else {
ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
- const dict_table_t* table;
-
- table = lock->un_member.tab_lock.table;
+ const dict_table_t* table = lock->un_member.tab_lock.table;
+ ut_ad(!table->is_temporary());
/* Check if the transcation locked a system table
in IX mode. It should have set the dict_op code
@@ -4591,14 +4587,14 @@ lock_print_info_summary(
fprintf(file,
"Purge done for trx's n:o < " TRX_ID_FMT
" undo n:o < " TRX_ID_FMT " state: %s\n"
- "History list length " ULINTPF "\n",
+ "History list length %u\n",
purge_sys.tail.trx_no(),
purge_sys.tail.undo_no,
purge_sys.enabled()
? (purge_sys.running() ? "running"
: purge_sys.paused() ? "stopped" : "running but idle")
: "disabled",
- trx_sys.history_size());
+ uint32_t{trx_sys.rseg_history_len});
#ifdef PRINT_NUM_OF_LOCK_STRUCTS
fprintf(file,
@@ -4896,8 +4892,8 @@ func_exit:
if (!lock_get_wait(other_lock) ) {
ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" <<
((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(impl_trx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(impl_trx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(impl_trx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " <<
wsrep_thd_query(impl_trx->mysql_thd);
@@ -4905,8 +4901,8 @@ func_exit:
ib::info() << "WSREP other lock:\n BF:" <<
((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " <<
- wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " <<
- wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " <<
+ wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " <<
+ wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " <<
wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " <<
wsrep_thd_query(otrx->mysql_thd);
}
@@ -5124,7 +5120,7 @@ lock_rec_block_validate(
block = buf_page_get_gen(
page_id_t(space_id, page_no),
- page_size_t(space->flags),
+ space->zip_size(),
RW_X_LATCH, NULL,
BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr, &err);
@@ -5264,7 +5260,7 @@ lock_rec_insert_check_and_lock(
trx_t* trx = thr_get_trx(thr);
const rec_t* next_rec = page_rec_get_next_const(rec);
ulint heap_no = page_rec_get_heap_no(next_rec);
- ut_ad(!rec_is_metadata(next_rec, index));
+ ut_ad(!rec_is_metadata(next_rec, *index));
lock_mutex_enter();
/* Because this code is invoked for a running transaction by
@@ -5392,7 +5388,7 @@ lock_rec_convert_impl_to_expl_for_trx(
{
ut_ad(trx->is_referenced());
ut_ad(page_rec_is_leaf(rec));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx");
lock_mutex_enter();
@@ -5525,7 +5521,7 @@ lock_rec_convert_impl_to_expl(
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
ut_ad(page_rec_is_leaf(rec));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
if (dict_index_is_clust(index)) {
trx_id_t trx_id;
@@ -5602,7 +5598,7 @@ lock_clust_rec_modify_check_and_lock(
return(DB_SUCCESS);
}
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
ut_ad(!index->table->is_temporary());
heap_no = rec_offs_comp(offsets)
@@ -5658,7 +5654,7 @@ lock_sec_rec_modify_check_and_lock(
ut_ad(block->frame == page_align(rec));
ut_ad(mtr->is_named_space(index->table->space));
ut_ad(page_rec_is_leaf(rec));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
if (flags & BTR_NO_LOCKING_FLAG) {
@@ -5752,7 +5748,7 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS);
}
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
heap_no = page_rec_get_heap_no(rec);
/* Some transaction may have an implicit x-lock on the record only
@@ -5814,7 +5810,7 @@ lock_clust_rec_read_check_and_lock(
|| gap_mode == LOCK_REC_NOT_GAP);
ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(page_rec_is_leaf(rec));
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
if ((flags & BTR_NO_LOCKING_FLAG)
|| srv_read_only_mode
@@ -6085,10 +6081,8 @@ lock_get_table_id(
/*==============*/
const lock_t* lock) /*!< in: lock */
{
- dict_table_t* table;
-
- table = lock_get_table(lock);
-
+ dict_table_t* table = lock_get_table(lock);
+ ut_ad(!table->is_temporary());
return(table->id);
}
@@ -6264,6 +6258,12 @@ lock_trx_handle_wait(
/*=================*/
trx_t* trx) /*!< in/out: trx lock state */
{
+#ifdef WITH_WSREP
+ /* We already own mutexes */
+ if (trx->lock.was_chosen_as_wsrep_victim) {
+ return lock_trx_handle_wait_low(trx);
+ }
+#endif /* WITH_WSREP */
lock_mutex_enter();
trx_mutex_enter(trx);
dberr_t err = lock_trx_handle_wait_low(trx);
@@ -6867,6 +6867,11 @@ DeadlockChecker::trx_rollback()
trx_t* trx = m_wait_lock->trx;
print("*** WE ROLL BACK TRANSACTION (1)\n");
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd) && wsrep_thd_is_SR(trx->mysql_thd)) {
+ wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd);
+ }
+#endif
trx_mutex_enter(trx);
@@ -6953,6 +6958,13 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx)
if (victim_trx != NULL) {
print("*** WE ROLL BACK TRANSACTION (2)\n");
+#ifdef WITH_WSREP
+ if (wsrep_on(trx->mysql_thd)
+ && wsrep_thd_is_SR(trx->mysql_thd)) {
+ wsrep_handle_SR_rollback(trx->mysql_thd,
+ victim_trx->mysql_thd);
+ }
+#endif
lock_deadlock_found = true;
}
diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc
index 75e93aed561..94104172577 100644
--- a/storage/innobase/lock/lock0wait.cc
+++ b/storage/innobase/lock/lock0wait.cc
@@ -282,7 +282,7 @@ lock_wait_suspend_thread(
if (thr->lock_state == QUE_THR_LOCK_ROW) {
srv_stats.n_lock_wait_count.inc();
- srv_stats.n_lock_wait_current_count.inc();
+ srv_stats.n_lock_wait_current_count++;
start_time = my_interval_timer();
}
@@ -385,7 +385,7 @@ lock_wait_suspend_thread(
thd_storage_lock_wait(trx->mysql_thd, diff_time);
}
- srv_stats.n_lock_wait_current_count.dec();
+ srv_stats.n_lock_wait_current_count--;
DBUG_EXECUTE_IF("lock_instrument_slow_query_log",
os_thread_sleep(1000););
diff --git a/storage/innobase/log/log0crypt.cc b/storage/innobase/log/log0crypt.cc
index a2e4ac1dd40..ff055131a6f 100644
--- a/storage/innobase/log/log0crypt.cc
+++ b/storage/innobase/log/log0crypt.cc
@@ -39,10 +39,9 @@ my_bool srv_encrypt_log;
/** Redo log encryption key ID */
#define LOG_DEFAULT_ENCRYPTION_KEY 1
-typedef union {
- uint32_t words[MY_AES_BLOCK_SIZE / sizeof(uint32_t)];
+struct aes_block_t {
byte bytes[MY_AES_BLOCK_SIZE];
-} aes_block_t;
+};
struct crypt_info_t {
ulint checkpoint_no; /*!< checkpoint no; 32 bits */
@@ -85,19 +84,63 @@ log_block_get_start_lsn(
return start_lsn;
}
+/** Generate crypt key from crypt msg.
+@param[in,out] info encryption key
+@param[in] upgrade whether to use the key in MariaDB 10.1 format
+@return whether the operation was successful */
+static bool init_crypt_key(crypt_info_t* info, bool upgrade = false)
+{
+ byte mysqld_key[MY_AES_MAX_KEY_LENGTH];
+ uint keylen = sizeof mysqld_key;
+
+ compile_time_assert(16 == sizeof info->crypt_key.bytes);
+ compile_time_assert(16 == MY_AES_BLOCK_SIZE);
+
+ if (uint rc = encryption_key_get(LOG_DEFAULT_ENCRYPTION_KEY,
+ info->key_version, mysqld_key,
+ &keylen)) {
+ ib::error()
+ << "Obtaining redo log encryption key version "
+ << info->key_version << " failed (" << rc
+ << "). Maybe the key or the required encryption "
+ "key management plugin was not found.";
+ return false;
+ }
+
+ if (upgrade) {
+ while (keylen < sizeof mysqld_key) {
+ mysqld_key[keylen++] = 0;
+ }
+ }
+
+ uint dst_len;
+ int err= my_aes_crypt(MY_AES_ECB,
+ ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT,
+ info->crypt_msg.bytes, MY_AES_BLOCK_SIZE,
+ info->crypt_key.bytes, &dst_len,
+ mysqld_key, keylen, NULL, 0);
+
+ if (err != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
+ ib::error() << "Getting redo log crypto key failed: err = "
+ << err << ", len = " << dst_len;
+ return false;
+ }
+
+ return true;
+}
+
/** Encrypt or decrypt log blocks.
@param[in,out] buf log blocks to encrypt or decrypt
@param[in] lsn log sequence number of the start of the buffer
@param[in] size size of the buffer, in bytes
-@param[in] decrypt whether to decrypt instead of encrypting */
-UNIV_INTERN
-void
-log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt)
+@param[in] op whether to decrypt, encrypt, or rotate key and encrypt
+@return whether the operation succeeded (encrypt always does) */
+bool log_crypt(byte* buf, lsn_t lsn, ulint size, log_crypt_t op)
{
ut_ad(size % OS_FILE_LOG_BLOCK_SIZE == 0);
+ ut_ad(ulint(buf) % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_a(info.key_version);
- uint dst_len;
uint32_t aes_ctr_iv[MY_AES_BLOCK_SIZE / sizeof(uint32_t)];
compile_time_assert(sizeof(uint32_t) == 4);
@@ -106,7 +149,8 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt)
for (const byte* const end = buf + size; buf != end;
buf += OS_FILE_LOG_BLOCK_SIZE, lsn += OS_FILE_LOG_BLOCK_SIZE) {
- uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE)
+ uint32_t dst[(OS_FILE_LOG_BLOCK_SIZE - LOG_CRYPT_HDR_SIZE
+ - LOG_BLOCK_CHECKSUM)
/ sizeof(uint32_t)];
/* The log block number is not encrypted. */
@@ -126,64 +170,61 @@ log_crypt(byte* buf, lsn_t lsn, ulint size, bool decrypt)
ut_ad(log_block_get_start_lsn(lsn,
log_block_get_hdr_no(buf))
== lsn);
+ byte* key_ver = &buf[OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_KEY
+ - LOG_BLOCK_CHECKSUM];
+ const uint dst_size
+ = log_sys.log.format == log_t::FORMAT_ENC_10_4
+ ? sizeof dst - LOG_BLOCK_KEY
+ : sizeof dst;
+ if (log_sys.log.format == log_t::FORMAT_ENC_10_4) {
+ const uint key_version = info.key_version;
+ switch (op) {
+ case LOG_ENCRYPT_ROTATE_KEY:
+ info.key_version
+ = encryption_key_get_latest_version(
+ LOG_DEFAULT_ENCRYPTION_KEY);
+ if (key_version != info.key_version
+ && !init_crypt_key(&info)) {
+ info.key_version = key_version;
+ }
+ /* fall through */
+ case LOG_ENCRYPT:
+ mach_write_to_4(key_ver, info.key_version);
+ break;
+ case LOG_DECRYPT:
+ info.key_version = mach_read_from_4(key_ver);
+ if (key_version != info.key_version
+ && !init_crypt_key(&info)) {
+ return false;
+ }
+ }
+#ifndef DBUG_OFF
+ if (key_version != info.key_version) {
+ DBUG_PRINT("ib_log", ("key_version: %x -> %x",
+ key_version,
+ info.key_version));
+ }
+#endif /* !DBUG_OFF */
+ }
+ ut_ad(LOG_CRYPT_HDR_SIZE + dst_size
+ == log_sys.trailer_offset());
+
+ uint dst_len;
int rc = encryption_crypt(
- buf + LOG_CRYPT_HDR_SIZE, sizeof dst,
+ buf + LOG_CRYPT_HDR_SIZE, dst_size,
reinterpret_cast<byte*>(dst), &dst_len,
const_cast<byte*>(info.crypt_key.bytes),
- sizeof info.crypt_key,
+ MY_AES_BLOCK_SIZE,
reinterpret_cast<byte*>(aes_ctr_iv), sizeof aes_ctr_iv,
- decrypt
+ op == LOG_DECRYPT
? ENCRYPTION_FLAG_DECRYPT | ENCRYPTION_FLAG_NOPAD
: ENCRYPTION_FLAG_ENCRYPT | ENCRYPTION_FLAG_NOPAD,
LOG_DEFAULT_ENCRYPTION_KEY,
info.key_version);
-
ut_a(rc == MY_AES_OK);
- ut_a(dst_len == sizeof dst);
- memcpy(buf + LOG_CRYPT_HDR_SIZE, dst, sizeof dst);
- }
-}
-
-/** Generate crypt key from crypt msg.
-@param[in,out] info encryption key
-@param[in] upgrade whether to use the key in MariaDB 10.1 format
-@return whether the operation was successful */
-static bool init_crypt_key(crypt_info_t* info, bool upgrade = false)
-{
- byte mysqld_key[MY_AES_MAX_KEY_LENGTH];
- uint keylen = sizeof mysqld_key;
-
- compile_time_assert(16 == sizeof info->crypt_key);
-
- if (uint rc = encryption_key_get(LOG_DEFAULT_ENCRYPTION_KEY,
- info->key_version, mysqld_key,
- &keylen)) {
- ib::error()
- << "Obtaining redo log encryption key version "
- << info->key_version << " failed (" << rc
- << "). Maybe the key or the required encryption "
- "key management plugin was not found.";
- return false;
- }
-
- if (upgrade) {
- while (keylen < sizeof mysqld_key) {
- mysqld_key[keylen++] = 0;
- }
- }
-
- uint dst_len;
- int err= my_aes_crypt(MY_AES_ECB,
- ENCRYPTION_FLAG_NOPAD | ENCRYPTION_FLAG_ENCRYPT,
- info->crypt_msg.bytes, sizeof info->crypt_msg,
- info->crypt_key.bytes, &dst_len,
- mysqld_key, keylen, NULL, 0);
-
- if (err != MY_AES_OK || dst_len != MY_AES_BLOCK_SIZE) {
- ib::error() << "Getting redo log crypto key failed: err = "
- << err << ", len = " << dst_len;
- return false;
+ ut_a(dst_len == dst_size);
+ memcpy(buf + LOG_CRYPT_HDR_SIZE, dst, dst_size);
}
return true;
@@ -247,7 +288,7 @@ log_crypt_101_read_checkpoint(const byte* buf)
infos_used++;
info.checkpoint_no = checkpoint_no;
info.key_version = mach_read_from_4(buf + 4);
- memcpy(info.crypt_msg.bytes, buf + 8, sizeof info.crypt_msg);
+ memcpy(info.crypt_msg.bytes, buf + 8, MY_AES_BLOCK_SIZE);
memcpy(info.crypt_nonce.bytes, buf + 24,
sizeof info.crypt_nonce);
@@ -331,13 +372,14 @@ void
log_crypt_write_checkpoint_buf(byte* buf)
{
ut_ad(info.key_version);
- compile_time_assert(16 == sizeof info.crypt_msg);
+ compile_time_assert(16 == sizeof info.crypt_msg.bytes);
+ compile_time_assert(16 == MY_AES_BLOCK_SIZE);
compile_time_assert(LOG_CHECKPOINT_CRYPT_MESSAGE
- LOG_CHECKPOINT_CRYPT_NONCE
== sizeof info.crypt_nonce);
memcpy(buf + LOG_CHECKPOINT_CRYPT_MESSAGE, info.crypt_msg.bytes,
- sizeof info.crypt_msg);
+ MY_AES_BLOCK_SIZE);
memcpy(buf + LOG_CHECKPOINT_CRYPT_NONCE, info.crypt_nonce.bytes,
sizeof info.crypt_nonce);
mach_write_to_4(buf + LOG_CHECKPOINT_CRYPT_KEY, info.key_version);
@@ -356,13 +398,14 @@ log_crypt_read_checkpoint_buf(const byte* buf)
#if MY_AES_BLOCK_SIZE != 16
# error "MY_AES_BLOCK_SIZE != 16; redo log checkpoint format affected"
#endif
- compile_time_assert(16 == sizeof info.crypt_msg);
+ compile_time_assert(16 == sizeof info.crypt_msg.bytes);
+ compile_time_assert(16 == MY_AES_BLOCK_SIZE);
compile_time_assert(LOG_CHECKPOINT_CRYPT_MESSAGE
- LOG_CHECKPOINT_CRYPT_NONCE
== sizeof info.crypt_nonce);
memcpy(info.crypt_msg.bytes, buf + LOG_CHECKPOINT_CRYPT_MESSAGE,
- sizeof info.crypt_msg);
+ MY_AES_BLOCK_SIZE);
memcpy(info.crypt_nonce.bytes, buf + LOG_CHECKPOINT_CRYPT_NONCE,
sizeof info.crypt_nonce);
@@ -392,8 +435,7 @@ log_tmp_block_encrypt(
int rc = encryption_crypt(
src, uint(size), dst, &dst_len,
- const_cast<byte*>(info.crypt_key.bytes),
- uint(sizeof info.crypt_key),
+ const_cast<byte*>(info.crypt_key.bytes), MY_AES_BLOCK_SIZE,
reinterpret_cast<byte*>(iv), uint(sizeof iv),
encrypt
? ENCRYPTION_FLAG_ENCRYPT|ENCRYPTION_FLAG_NOPAD
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 6d0b3baa5a3..e8881ee05a8 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -210,9 +210,9 @@ log_calculate_actual_len(
{
ut_ad(log_mutex_own());
+ const ulint framing_size = log_sys.framing_size();
/* actual length stored per block */
- const ulint len_per_blk = OS_FILE_LOG_BLOCK_SIZE
- - (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE);
+ const ulint len_per_blk = OS_FILE_LOG_BLOCK_SIZE - framing_size;
/* actual data length in last block already written */
ulint extra_len = (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE);
@@ -221,8 +221,7 @@ log_calculate_actual_len(
extra_len -= LOG_BLOCK_HDR_SIZE;
/* total extra length for block header and trailer */
- extra_len = ((len + extra_len) / len_per_blk)
- * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE);
+ extra_len = ((len + extra_len) / len_per_blk) * framing_size;
return(len + extra_len);
}
@@ -340,26 +339,24 @@ log_write_low(
ulint str_len) /*!< in: string length */
{
ulint len;
- ulint data_len;
- byte* log_block;
ut_ad(log_mutex_own());
+ const ulint trailer_offset = log_sys.trailer_offset();
part_loop:
/* Calculate a part length */
- data_len = (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len;
+ ulint data_len = (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE) + str_len;
- if (data_len <= OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
+ if (data_len <= trailer_offset) {
/* The string fits within the current log block */
len = str_len;
} else {
- data_len = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE;
+ data_len = trailer_offset;
- len = OS_FILE_LOG_BLOCK_SIZE
- - (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE)
- - LOG_BLOCK_TRL_SIZE;
+ len = trailer_offset
+ - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE;
}
memcpy(log_sys.buf + log_sys.buf_free, str, len);
@@ -367,18 +364,18 @@ part_loop:
str_len -= len;
str = str + len;
- log_block = static_cast<byte*>(
+ byte* log_block = static_cast<byte*>(
ut_align_down(log_sys.buf + log_sys.buf_free,
OS_FILE_LOG_BLOCK_SIZE));
log_block_set_data_len(log_block, data_len);
- if (data_len == OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
+ if (data_len == trailer_offset) {
/* This block became full */
log_block_set_data_len(log_block, OS_FILE_LOG_BLOCK_SIZE);
log_block_set_checkpoint_no(log_block,
log_sys.next_checkpoint_no);
- len += LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE;
+ len += log_sys.framing_size();
log_sys.lsn += len;
@@ -604,9 +601,7 @@ void log_t::files::create(ulint n_files)
ut_ad(log_sys.is_initialised());
this->n_files= n_files;
- format= srv_encrypt_log
- ? LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED
- : LOG_HEADER_FORMAT_CURRENT;
+ format= srv_encrypt_log ? log_t::FORMAT_ENC_10_4 : log_t::FORMAT_10_4;
subformat= 2;
file_size= srv_log_file_size;
lsn= LOG_START_LSN;
@@ -628,8 +623,8 @@ log_file_header_flush(
ut_ad(log_write_mutex_own());
ut_ad(!recv_no_log_write);
ut_a(nth_file < log_sys.log.n_files);
- ut_ad((log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
- == LOG_HEADER_FORMAT_CURRENT);
+ ut_ad(log_sys.log.format == log_t::FORMAT_10_4
+ || log_sys.log.format == log_t::FORMAT_ENC_10_4);
// man 2 open suggests this buffer to be aligned by 512 for O_DIRECT
MY_ALIGNED(OS_FILE_LOG_BLOCK_SIZE)
@@ -658,7 +653,7 @@ log_file_header_flush(
fil_io(IORequestLogWrite, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint(dest_offset & (srv_page_size - 1)),
OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
@@ -778,7 +773,7 @@ loop:
fil_io(IORequestLogWrite, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint(next_offset & (srv_page_size - 1)), write_len, buf, NULL);
srv_stats.os_log_pending_writes.dec();
@@ -865,11 +860,9 @@ wait and check if an already running write is covering the request.
@param[in] lsn log sequence number that should be
included in the redo log file write
@param[in] flush_to_disk whether the written log should also
-be flushed to the file system */
-void
-log_write_up_to(
- lsn_t lsn,
- bool flush_to_disk)
+be flushed to the file system
+@param[in] rotate_key whether to rotate the encryption key */
+void log_write_up_to(lsn_t lsn, bool flush_to_disk, bool rotate_key)
{
#ifdef UNIV_DEBUG
ulint loop_count = 0;
@@ -878,6 +871,7 @@ log_write_up_to(
lsn_t write_lsn;
ut_ad(!srv_read_only_mode);
+ ut_ad(!rotate_key || flush_to_disk);
if (recv_no_ibuf_operations) {
/* Recovery is running and no operations on the log files are
@@ -1022,7 +1016,8 @@ loop:
if (log_sys.is_encrypted()) {
log_crypt(write_buf + area_start, log_sys.write_lsn,
- area_end - area_start);
+ area_end - area_start,
+ rotate_key ? LOG_ENCRYPT_ROTATE_KEY : LOG_ENCRYPT);
}
/* Do the write to the log files */
@@ -1277,7 +1272,7 @@ log_group_checkpoint(lsn_t end_lsn)
fil_io(IORequestLogWrite, false,
page_id_t(SRV_LOG_SPACE_FIRST_ID, 0),
- univ_page_size,
+ 0,
(log_sys.next_checkpoint_no & 1)
? LOG_CHECKPOINT_2 : LOG_CHECKPOINT_1,
OS_FILE_LOG_BLOCK_SIZE,
@@ -1297,7 +1292,7 @@ void log_header_read(ulint header)
fil_io(IORequestLogRead, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID,
header >> srv_page_size_shift),
- univ_page_size, header & (srv_page_size - 1),
+ 0, header & (srv_page_size - 1),
OS_FILE_LOG_BLOCK_SIZE, log_sys.checkpoint_buf, NULL);
}
@@ -1428,7 +1423,7 @@ bool log_checkpoint(bool sync)
log_mutex_exit();
- log_write_up_to(flush_lsn, true);
+ log_write_up_to(flush_lsn, true, true);
log_mutex_enter();
@@ -1614,11 +1609,11 @@ loop:
} else {
ut_ad(!srv_dict_stats_thread_active);
}
- if (recv_sys && recv_sys->flush_start) {
+ if (recv_sys.flush_start) {
/* This is in case recv_writer_thread was never
started, or buf_flush_page_cleaner_coordinator
failed to notice its termination. */
- os_event_set(recv_sys->flush_start);
+ os_event_set(recv_sys.flush_start);
}
}
#define COUNT_INTERVAL 600U
@@ -1956,7 +1951,7 @@ void log_t::close()
if (!srv_read_only_mode && srv_scrub_log)
os_event_destroy(log_scrub_event);
- recv_sys_close();
+ recv_sys.close();
}
/******************************************************//**
@@ -1976,13 +1971,9 @@ log_pad_current_log_block(void)
/* We retrieve lsn only because otherwise gcc crashed on HP-UX */
lsn = log_reserve_and_open(OS_FILE_LOG_BLOCK_SIZE);
- pad_length = OS_FILE_LOG_BLOCK_SIZE
- - (log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE)
- - LOG_BLOCK_TRL_SIZE;
- if (pad_length
- == (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
- - LOG_BLOCK_TRL_SIZE)) {
-
+ pad_length = log_sys.trailer_offset()
+ - log_sys.buf_free % OS_FILE_LOG_BLOCK_SIZE;
+ if (pad_length == log_sys.payload_size()) {
pad_length = 0;
}
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index ad2fc4e22d3..1c96a43715b 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -51,7 +51,6 @@ Created 9/20/1997 Heikki Tuuri
#include "trx0undo.h"
#include "trx0rec.h"
#include "fil0fil.h"
-#include "row0trunc.h"
#include "buf0rea.h"
#include "srv0srv.h"
#include "srv0start.h"
@@ -66,7 +65,7 @@ this must be less than srv_page_size as it is stored in the buffer pool */
#define RECV_READ_AHEAD_AREA 32
/** The recovery system */
-recv_sys_t* recv_sys;
+recv_sys_t recv_sys;
/** TRUE when applying redo log records during crash recovery; FALSE
otherwise. Note that this is FALSE while a background thread is
rolling back incomplete transactions. */
@@ -151,8 +150,9 @@ struct file_name_t {
lsn_t enable_lsn;
/** Constructor */
- file_name_t(std::string name_, bool deleted) :
- name(name_), space(NULL), status(deleted ? DELETED: NORMAL),
+ file_name_t(std::string name_, bool deleted)
+ : name(std::move(name_)), space(NULL),
+ status(deleted ? DELETED: NORMAL),
size(0), enable_lsn(0) {}
/** Report a MLOG_INDEX_LOAD operation, meaning that
@@ -210,10 +210,6 @@ corresponding to MLOG_INDEX_LOAD.
*/
void (*log_optimized_ddl_op)(ulint space_id);
-/** Report backup-unfriendly TRUNCATE operation (with separate log file),
-corresponding to MLOG_TRUNCATE. */
-void (*log_truncate)();
-
/** Report an operation to create, delete, or rename a file during backup.
@param[in] space_id tablespace identifier
@param[in] flags tablespace flags (NULL if not create)
@@ -249,7 +245,7 @@ private:
ut_allocator<std::pair<const page_id_t, init> > >
map;
/** Map of page initialization operations.
- FIXME: Merge this to recv_sys->addr_hash! */
+ FIXME: Merge this to recv_sys.addr_hash! */
map inits;
public:
/** Record that a page will be initialized by the redo log.
@@ -258,7 +254,7 @@ public:
@param[in] lsn log sequence number */
void add(ulint space, ulint page_no, lsn_t lsn)
{
- ut_ad(mutex_own(&recv_sys->mutex));
+ ut_ad(mutex_own(&recv_sys.mutex));
const init init = { lsn, false };
std::pair<map::iterator, bool> p = inits.insert(
map::value_type(page_id_t(space, page_no), init));
@@ -273,20 +269,20 @@ public:
@param[in] page_id page id
@param[in,out] init initialize log or load log
@return the latest page initialization;
- not valid after releasing recv_sys->mutex. */
+ not valid after releasing recv_sys.mutex. */
init& last(page_id_t page_id)
{
- ut_ad(mutex_own(&recv_sys->mutex));
+ ut_ad(mutex_own(&recv_sys.mutex));
return inits.find(page_id)->second;
}
/** At the end of each recovery batch, reset the 'created' flags. */
void reset()
{
- ut_ad(mutex_own(&recv_sys->mutex));
+ ut_ad(mutex_own(&recv_sys.mutex));
ut_ad(recv_no_ibuf_operations);
- for (map::iterator i= inits.begin(); i != inits.end(); i++) {
- i->second.created = false;
+ for (map::value_type& i : inits) {
+ i.second.created = false;
}
}
@@ -304,26 +300,25 @@ public:
@param[in,out] mtr dummy mini-transaction */
void ibuf_merge(mtr_t& mtr)
{
- ut_ad(mutex_own(&recv_sys->mutex));
+ ut_ad(mutex_own(&recv_sys.mutex));
ut_ad(!recv_no_ibuf_operations);
mtr.start();
- for (map::const_iterator i= inits.begin(); i != inits.end();
- i++) {
- if (!i->second.created) {
+ for (const map::value_type& i : inits) {
+ if (!i.second.created) {
continue;
}
if (buf_block_t* block = buf_page_get_low(
- i->first, univ_page_size, RW_X_LATCH, NULL,
+ i.first, 0, RW_X_LATCH, NULL,
BUF_GET_IF_IN_POOL, __FILE__, __LINE__,
&mtr, NULL)) {
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
ibuf_merge_or_delete_for_page(
- block, i->first,
- &block->page.size, true);
+ block, i.first,
+ block->zip_size(), true);
mtr.commit();
mtr.start();
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
}
}
@@ -347,10 +342,10 @@ static void recv_addr_trim(ulint space_id, unsigned pages, lsn_t lsn)
DBUG_LOG("ib_log",
"discarding log beyond end of tablespace "
<< page_id_t(space_id, pages) << " before LSN " << lsn);
- ut_ad(mutex_own(&recv_sys->mutex));
- for (ulint i = recv_sys->addr_hash->n_cells; i--; ) {
+ ut_ad(mutex_own(&recv_sys.mutex));
+ for (ulint i = recv_sys.addr_hash->n_cells; i--; ) {
hash_cell_t* const cell = hash_get_nth_cell(
- recv_sys->addr_hash, i);
+ recv_sys.addr_hash, i);
for (recv_addr_t* addr = static_cast<recv_addr_t*>(cell->node),
*next;
addr; addr = next) {
@@ -459,7 +454,7 @@ fil_name_process(
<< " has been found in two places: '"
<< f.name << "' and '" << name << "'."
" You must delete one of them.";
- recv_sys->found_corrupt_fs = true;
+ recv_sys.found_corrupt_fs = true;
}
break;
@@ -482,7 +477,7 @@ fil_name_process(
forcing recovery. */
ib::info()
- << "At LSN: " << recv_sys->recovered_lsn
+ << "At LSN: " << recv_sys.recovered_lsn
<< ": unable to open file " << name
<< " for tablespace " << space_id;
}
@@ -511,7 +506,7 @@ fil_name_process(
" disk is broken, and you cannot"
" remove the .ibd file, you can set"
" --innodb_force_recovery.";
- recv_sys->found_corrupt_fs = true;
+ recv_sys.found_corrupt_fs = true;
break;
}
@@ -527,8 +522,7 @@ fil_name_process(
/** Parse or process a MLOG_FILE_* record.
@param[in] ptr redo log record
@param[in] end end of the redo log buffer
-@param[in] space_id the tablespace ID
-@param[in] first_page_no first page number in the file
+@param[in] page_id first page number in the file
@param[in] type MLOG_FILE_NAME or MLOG_FILE_DELETE
or MLOG_FILE_CREATE2 or MLOG_FILE_RENAME2
@param[in] apply whether to apply the record
@@ -539,8 +533,7 @@ byte*
fil_name_parse(
byte* ptr,
const byte* end,
- ulint space_id,
- ulint first_page_no,
+ const page_id_t page_id,
mlog_id_t type,
bool apply)
{
@@ -564,9 +557,9 @@ fil_name_parse(
/* MLOG_FILE_* records should only be written for
user-created tablespaces. The name must be long enough
and end in .ibd. */
- bool corrupt = is_predefined_tablespace(space_id)
+ bool corrupt = is_predefined_tablespace(page_id.space())
|| len < sizeof "/a.ibd\0"
- || (!first_page_no != !memcmp(ptr + len - 5, DOT_IBD, 5));
+ || (!page_id.page_no() != !memcmp(ptr + len - 5, DOT_IBD, 5));
if (!corrupt && !memchr(ptr, OS_PATH_SEPARATOR, len)) {
if (byte* c = static_cast<byte*>
@@ -592,37 +585,38 @@ fil_name_parse(
case MLOG_FILE_NAME:
if (corrupt) {
ib::error() << "MLOG_FILE_NAME incorrect:" << ptr;
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
break;
}
fil_name_process(
- reinterpret_cast<char*>(ptr), len, space_id, false);
+ reinterpret_cast<char*>(ptr), len, page_id.space(),
+ false);
break;
case MLOG_FILE_DELETE:
if (corrupt) {
ib::error() << "MLOG_FILE_DELETE incorrect:" << ptr;
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
break;
}
- fil_name_process(
- reinterpret_cast<char*>(ptr), len, space_id, true);
+ fil_name_process(reinterpret_cast<char*>(ptr), len,
+ page_id.space(), true);
/* fall through */
case MLOG_FILE_CREATE2:
- if (first_page_no) {
- ut_ad(first_page_no
+ if (page_id.page_no()) {
+ ut_ad(page_id.page_no()
== SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
- ut_a(srv_is_undo_tablespace(space_id));
+ ut_a(srv_is_undo_tablespace(page_id.space()));
compile_time_assert(
- UT_ARR_SIZE(recv_sys->truncated_undo_spaces)
+ UT_ARR_SIZE(recv_sys.truncated_undo_spaces)
== TRX_SYS_MAX_UNDO_SPACES);
- recv_sys_t::trunc& t = recv_sys->truncated_undo_spaces[
- space_id - srv_undo_space_id_start];
- t.lsn = recv_sys->recovered_lsn;
- t.pages = uint32_t(first_page_no);
+ recv_sys_t::trunc& t = recv_sys.truncated_undo_spaces[
+ page_id.space() - srv_undo_space_id_start];
+ t.lsn = recv_sys.recovered_lsn;
+ t.pages = uint32_t(page_id.page_no());
} else if (log_file_op) {
- log_file_op(space_id,
+ log_file_op(page_id.space(),
type == MLOG_FILE_CREATE2 ? ptr - 4 : NULL,
ptr, len, NULL, 0);
}
@@ -630,7 +624,7 @@ fil_name_parse(
case MLOG_FILE_RENAME2:
if (corrupt) {
ib::error() << "MLOG_FILE_RENAME2 incorrect:" << ptr;
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
}
/* The new name follows the old name. */
@@ -672,19 +666,19 @@ fil_name_parse(
if (corrupt) {
ib::error() << "MLOG_FILE_RENAME2 new_name incorrect:" << ptr
<< " new_name: " << new_name;
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
break;
}
fil_name_process(
reinterpret_cast<char*>(ptr), len,
- space_id, false);
+ page_id.space(), false);
fil_name_process(
reinterpret_cast<char*>(new_name), new_len,
- space_id, false);
+ page_id.space(), false);
if (log_file_op) {
- log_file_op(space_id, NULL,
+ log_file_op(page_id.space(), NULL,
ptr, len, new_name, new_len);
}
@@ -692,50 +686,51 @@ fil_name_parse(
break;
}
if (!fil_op_replay_rename(
- space_id, first_page_no,
+ page_id.space(), page_id.page_no(),
reinterpret_cast<const char*>(ptr),
reinterpret_cast<const char*>(new_name))) {
- recv_sys->found_corrupt_fs = true;
+ recv_sys.found_corrupt_fs = true;
}
}
return(end_ptr);
}
-/** Clean up after recv_sys_init() */
-void
-recv_sys_close()
+/** Clean up after recv_sys_t::create() */
+void recv_sys_t::close()
{
- if (recv_sys != NULL) {
- recv_sys->dblwr.pages.clear();
+ ut_ad(this == &recv_sys);
+ ut_ad(!recv_writer_thread_active);
- if (recv_sys->addr_hash != NULL) {
- hash_table_free(recv_sys->addr_hash);
- }
+ if (is_initialised()) {
+ dblwr.pages.clear();
- if (recv_sys->heap != NULL) {
- mem_heap_free(recv_sys->heap);
+ if (addr_hash) {
+ hash_table_free(addr_hash);
+ addr_hash = NULL;
}
- if (recv_sys->flush_start != NULL) {
- os_event_destroy(recv_sys->flush_start);
+ if (heap) {
+ mem_heap_free(heap);
+ heap = NULL;
}
- if (recv_sys->flush_end != NULL) {
- os_event_destroy(recv_sys->flush_end);
+ if (flush_start) {
+ os_event_destroy(flush_start);
}
- if (recv_sys->buf != NULL) {
- ut_free_dodump(recv_sys->buf, recv_sys->buf_size);
+ if (flush_end) {
+ os_event_destroy(flush_end);
}
- ut_ad(!recv_writer_thread_active);
- mutex_free(&recv_sys->writer_mutex);
-
- mutex_free(&recv_sys->mutex);
+ if (buf) {
+ ut_free_dodump(buf, buf_size);
+ buf = NULL;
+ }
- ut_free(recv_sys);
- recv_sys = NULL;
+ buf_size = 0;
+ mutex_free(&writer_mutex);
+ mutex_free(&mutex);
}
recv_spaces.clear();
@@ -789,20 +784,20 @@ DECLARE_THREAD(recv_writer_thread)(
int64_t sig_count = os_event_reset(buf_flush_event);
os_event_wait_time_low(buf_flush_event, 100000, sig_count);
- mutex_enter(&recv_sys->writer_mutex);
+ mutex_enter(&recv_sys.writer_mutex);
if (!recv_recovery_is_on()) {
- mutex_exit(&recv_sys->writer_mutex);
+ mutex_exit(&recv_sys.writer_mutex);
break;
}
/* Flush pages from end of LRU if required */
- os_event_reset(recv_sys->flush_end);
- recv_sys->flush_type = BUF_FLUSH_LRU;
- os_event_set(recv_sys->flush_start);
- os_event_wait(recv_sys->flush_end);
+ os_event_reset(recv_sys.flush_end);
+ recv_sys.flush_type = BUF_FLUSH_LRU;
+ os_event_set(recv_sys.flush_start);
+ os_event_wait(recv_sys.flush_end);
- mutex_exit(&recv_sys->writer_mutex);
+ mutex_exit(&recv_sys.writer_mutex);
}
recv_writer_thread_active = false;
@@ -817,75 +812,83 @@ DECLARE_THREAD(recv_writer_thread)(
}
/** Initialize the redo log recovery subsystem. */
-void
-recv_sys_init()
+void recv_sys_t::create()
{
- ut_ad(recv_sys == NULL);
-
- recv_sys = static_cast<recv_sys_t*>(ut_zalloc_nokey(sizeof(*recv_sys)));
+ ut_ad(this == &recv_sys);
+ ut_ad(!is_initialised());
+ ut_ad(!flush_start);
+ ut_ad(!flush_end);
+ mutex_create(LATCH_ID_RECV_SYS, &mutex);
+ mutex_create(LATCH_ID_RECV_WRITER, &writer_mutex);
- mutex_create(LATCH_ID_RECV_SYS, &recv_sys->mutex);
- mutex_create(LATCH_ID_RECV_WRITER, &recv_sys->writer_mutex);
-
- recv_sys->heap = mem_heap_create_typed(256, MEM_HEAP_FOR_RECV_SYS);
+ heap = mem_heap_create_typed(256, MEM_HEAP_FOR_RECV_SYS);
if (!srv_read_only_mode) {
- recv_sys->flush_start = os_event_create(0);
- recv_sys->flush_end = os_event_create(0);
+ flush_start = os_event_create(0);
+ flush_end = os_event_create(0);
}
- recv_sys->buf = static_cast<byte*>(
- ut_malloc_dontdump(RECV_PARSING_BUF_SIZE));
- recv_sys->buf_size = RECV_PARSING_BUF_SIZE;
-
- recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512);
- recv_sys->progress_time = time(NULL);
+ flush_type = BUF_FLUSH_LRU;
+ apply_log_recs = false;
+ apply_batch_on = false;
+
+ buf = static_cast<byte*>(ut_malloc_dontdump(RECV_PARSING_BUF_SIZE));
+ buf_size = RECV_PARSING_BUF_SIZE;
+ len = 0;
+ parse_start_lsn = 0;
+ scanned_lsn = 0;
+ scanned_checkpoint_no = 0;
+ recovered_offset = 0;
+ recovered_lsn = 0;
+ found_corrupt_log = false;
+ found_corrupt_fs = false;
+ mlog_checkpoint_lsn = 0;
+
+ addr_hash = hash_create(buf_pool_get_curr_size() / 512);
+ n_addrs = 0;
+ progress_time = time(NULL);
recv_max_page_lsn = 0;
- /* Call the constructor for recv_sys_t::dblwr member */
- new (&recv_sys->dblwr) recv_dblwr_t();
+ memset(truncated_undo_spaces, 0, sizeof truncated_undo_spaces);
+ last_stored_lsn = 0;
}
-/** Empty a fully processed hash table. */
-static
-void
-recv_sys_empty_hash()
+/** Empty a fully processed set of stored redo log records. */
+inline void recv_sys_t::empty()
{
- ut_ad(mutex_own(&(recv_sys->mutex)));
- ut_a(recv_sys->n_addrs == 0);
+ ut_ad(mutex_own(&mutex));
+ ut_a(n_addrs == 0);
- hash_table_free(recv_sys->addr_hash);
- mem_heap_empty(recv_sys->heap);
+ hash_table_free(addr_hash);
+ mem_heap_empty(heap);
- recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512);
+ addr_hash = hash_create(buf_pool_get_curr_size() / 512);
}
-/********************************************************//**
-Frees the recovery system. */
-void
-recv_sys_debug_free(void)
-/*=====================*/
+/** Free most recovery data structures. */
+void recv_sys_t::debug_free()
{
- mutex_enter(&(recv_sys->mutex));
+ ut_ad(this == &recv_sys);
+ ut_ad(is_initialised());
+ mutex_enter(&mutex);
- hash_table_free(recv_sys->addr_hash);
- mem_heap_free(recv_sys->heap);
- ut_free_dodump(recv_sys->buf, recv_sys->buf_size);
+ hash_table_free(addr_hash);
+ mem_heap_free(heap);
+ ut_free_dodump(buf, buf_size);
- recv_sys->buf_size = 0;
- recv_sys->buf = NULL;
- recv_sys->heap = NULL;
- recv_sys->addr_hash = NULL;
+ buf = NULL;
+ heap = NULL;
+ addr_hash = NULL;
/* wake page cleaner up to progress */
if (!srv_read_only_mode) {
ut_ad(!recv_recovery_is_on());
ut_ad(!recv_writer_thread_active);
os_event_reset(buf_flush_event);
- os_event_set(recv_sys->flush_start);
+ os_event_set(flush_start);
}
- mutex_exit(&(recv_sys->mutex));
+ mutex_exit(&mutex);
}
/** Read a log segment to log_sys.buf.
@@ -926,7 +929,7 @@ loop:
fil_io(IORequestLogRead, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint(source_offset & (srv_page_size - 1)),
len, buf, NULL);
@@ -968,22 +971,24 @@ fail:
goto fail;
}
- if (is_encrypted()) {
- log_crypt(buf, *start_lsn,
- OS_FILE_LOG_BLOCK_SIZE, true);
+ if (is_encrypted()
+ && !log_crypt(buf, *start_lsn,
+ OS_FILE_LOG_BLOCK_SIZE,
+ LOG_DECRYPT)) {
+ goto fail;
}
}
ulint dl = log_block_get_data_len(buf);
if (dl < LOG_BLOCK_HDR_SIZE
- || (dl > OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE
- && dl != OS_FILE_LOG_BLOCK_SIZE)) {
- recv_sys->found_corrupt_log = true;
+ || (dl != OS_FILE_LOG_BLOCK_SIZE
+ && dl > log_sys.trailer_offset())) {
+ recv_sys.found_corrupt_log = true;
goto fail;
}
}
- if (recv_sys->report(time(NULL))) {
+ if (recv_sys.report(time(NULL))) {
ib::info() << "Read redo log up to LSN=" << *start_lsn;
service_manager_extend_timeout(INNODB_EXTEND_TIMEOUT_INTERVAL,
"Read redo log up to LSN=" LSN_PF,
@@ -1008,7 +1013,7 @@ static
void
recv_synchronize_groups()
{
- const lsn_t recovered_lsn = recv_sys->recovered_lsn;
+ const lsn_t recovered_lsn = recv_sys.recovered_lsn;
/* Read the last recovered log block to the recovery system buffer:
the block is always incomplete */
@@ -1140,7 +1145,7 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt)
fil_io(IORequestLogRead, true,
page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
+ 0,
ulint((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1))
& (srv_page_size - 1)),
OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
@@ -1167,9 +1172,9 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt)
/* Mark the redo log for upgrading. */
srv_log_file_size = 0;
- recv_sys->parse_start_lsn = recv_sys->recovered_lsn
- = recv_sys->scanned_lsn
- = recv_sys->mlog_checkpoint_lsn = lsn;
+ recv_sys.parse_start_lsn = recv_sys.recovered_lsn
+ = recv_sys.scanned_lsn
+ = recv_sys.mlog_checkpoint_lsn = lsn;
log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn
= log_sys.lsn = log_sys.write_lsn
= log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn
@@ -1178,52 +1183,6 @@ static dberr_t recv_log_format_0_recover(lsn_t lsn, bool crypt)
return(DB_SUCCESS);
}
-/** Determine if a redo log from MariaDB 10.4 is clean.
-@return error code
-@retval DB_SUCCESS if the redo log is clean
-@retval DB_CORRUPTION if the redo log is corrupted
-@retval DB_ERROR if the redo log is not empty */
-static dberr_t recv_log_recover_10_4()
-{
- ut_ad(!log_sys.is_encrypted());
- const lsn_t lsn = log_sys.log.get_lsn();
- const lsn_t source_offset = log_sys.log.calc_lsn_offset(lsn);
- const ulint page_no
- = (ulint) (source_offset / univ_page_size.physical());
- byte* buf = log_sys.buf;
-
- fil_io(IORequestLogRead, true,
- page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
- (ulint) ((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1))
- % univ_page_size.physical()),
- OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
-
- if (log_block_calc_checksum(buf) != log_block_get_checksum(buf)) {
- return DB_CORRUPTION;
- }
-
- /* On a clean shutdown, the redo log will be logically empty
- after the checkpoint lsn. */
-
- if (log_block_get_data_len(buf)
- != (source_offset & (OS_FILE_LOG_BLOCK_SIZE - 1))) {
- return DB_ERROR;
- }
-
- /* Mark the redo log for downgrading. */
- srv_log_file_size = 0;
- recv_sys->parse_start_lsn = recv_sys->recovered_lsn
- = recv_sys->scanned_lsn
- = recv_sys->mlog_checkpoint_lsn = lsn;
- log_sys.last_checkpoint_lsn = log_sys.next_checkpoint_lsn
- = log_sys.lsn = log_sys.write_lsn
- = log_sys.current_flush_lsn = log_sys.flushed_to_disk_lsn
- = lsn;
- log_sys.next_checkpoint_no = 0;
- return DB_SUCCESS;
-}
-
/** Find the latest checkpoint in the log header.
@param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2
@return error code or DB_SUCCESS */
@@ -1244,10 +1203,10 @@ recv_find_max_checkpoint(ulint* max_field)
/* Check the header page checksum. There was no
checksum in the first redo log format (version 0). */
log_sys.log.format = mach_read_from_4(buf + LOG_HEADER_FORMAT);
- log_sys.log.subformat = log_sys.log.format != LOG_HEADER_FORMAT_3_23
+ log_sys.log.subformat = log_sys.log.format != log_t::FORMAT_3_23
? mach_read_from_4(buf + LOG_HEADER_SUBFORMAT)
: 0;
- if (log_sys.log.format != LOG_HEADER_FORMAT_3_23
+ if (log_sys.log.format != log_t::FORMAT_3_23
&& !recv_check_log_header_checksum(buf)) {
ib::error() << "Invalid redo log header checksum.";
return(DB_CORRUPTION);
@@ -1260,15 +1219,14 @@ recv_find_max_checkpoint(ulint* max_field)
creator[LOG_HEADER_CREATOR_END - LOG_HEADER_CREATOR] = 0;
switch (log_sys.log.format) {
- case LOG_HEADER_FORMAT_3_23:
+ case log_t::FORMAT_3_23:
return(recv_find_max_checkpoint_0(max_field));
- case LOG_HEADER_FORMAT_10_2:
- case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED:
- case LOG_HEADER_FORMAT_CURRENT:
- case LOG_HEADER_FORMAT_CURRENT | LOG_HEADER_FORMAT_ENCRYPTED:
- case LOG_HEADER_FORMAT_10_4:
- /* We can only parse the unencrypted LOG_HEADER_FORMAT_10_4.
- The encrypted format uses a larger redo log block trailer. */
+ case log_t::FORMAT_10_2:
+ case log_t::FORMAT_10_2 | log_t::FORMAT_ENCRYPTED:
+ case log_t::FORMAT_10_3:
+ case log_t::FORMAT_10_3 | log_t::FORMAT_ENCRYPTED:
+ case log_t::FORMAT_10_4:
+ case log_t::FORMAT_10_4 | log_t::FORMAT_ENCRYPTED:
break;
default:
ib::error() << "Unsupported redo log format."
@@ -1333,19 +1291,7 @@ recv_find_max_checkpoint(ulint* max_field)
return(DB_ERROR);
}
- if (log_sys.log.format == LOG_HEADER_FORMAT_10_4) {
- dberr_t err = recv_log_recover_10_4();
- if (err != DB_SUCCESS) {
- ib::error()
- << "Downgrade after a crash is not supported."
- " The redo log was created with " << creator
- << (err == DB_ERROR
- ? "." : ", and it appears corrupted.");
- }
- return err;
- }
-
- return DB_SUCCESS;
+ return(DB_SUCCESS);
}
/** Try to parse a single log record body and also applies it if
@@ -1353,8 +1299,7 @@ specified.
@param[in] type redo log entry type
@param[in] ptr redo log record body
@param[in] end_ptr end of buffer
-@param[in] space_id tablespace identifier
-@param[in] page_no page number
+@param[in] page_id page identifier
@param[in] apply whether to apply the record
@param[in,out] block buffer block, or NULL if
a page log record should not be applied
@@ -1368,14 +1313,13 @@ recv_parse_or_apply_log_rec_body(
mlog_id_t type,
byte* ptr,
byte* end_ptr,
- ulint space_id,
- ulint page_no,
+ const page_id_t page_id,
bool apply,
buf_block_t* block,
mtr_t* mtr)
{
ut_ad(!block == !mtr);
- ut_ad(!apply || recv_sys->mlog_checkpoint_lsn != 0);
+ ut_ad(!apply || recv_sys.mlog_checkpoint_lsn);
switch (type) {
case MLOG_FILE_NAME:
@@ -1385,22 +1329,17 @@ recv_parse_or_apply_log_rec_body(
ut_ad(block == NULL);
/* Collect the file names when parsing the log,
before applying any log records. */
- return(fil_name_parse(ptr, end_ptr, space_id, page_no, type,
- apply));
+ return fil_name_parse(ptr, end_ptr, page_id, type, apply);
case MLOG_INDEX_LOAD:
if (end_ptr < ptr + 8) {
return(NULL);
}
return(ptr + 8);
case MLOG_TRUNCATE:
- if (log_truncate) {
- ut_ad(srv_operation != SRV_OPERATION_NORMAL);
- log_truncate();
- recv_sys->found_corrupt_fs = true;
- return NULL;
- }
- return(truncate_t::parse_redo_entry(ptr, end_ptr, space_id));
-
+ ib::error() << "Cannot crash-upgrade from "
+ "old-style TRUNCATE TABLE";
+ recv_sys.found_corrupt_log = true;
+ return NULL;
default:
break;
}
@@ -1419,23 +1358,22 @@ recv_parse_or_apply_log_rec_body(
page_zip = buf_block_get_page_zip(block);
ut_d(page_type = fil_page_get_type(page));
} else if (apply
- && !is_predefined_tablespace(space_id)
- && recv_spaces.find(space_id) == recv_spaces.end()) {
- if (recv_sys->recovered_lsn < recv_sys->mlog_checkpoint_lsn) {
+ && !is_predefined_tablespace(page_id.space())
+ && recv_spaces.find(page_id.space()) == recv_spaces.end()) {
+ if (recv_sys.recovered_lsn < recv_sys.mlog_checkpoint_lsn) {
/* We have not seen all records between the
checkpoint and MLOG_CHECKPOINT. There should be
a MLOG_FILE_DELETE for this tablespace later. */
recv_spaces.insert(
- std::make_pair(space_id,
+ std::make_pair(page_id.space(),
file_name_t("", false)));
goto parse_log;
}
ib::error() << "Missing MLOG_FILE_NAME or MLOG_FILE_DELETE"
- " for redo log record " << type << " (page "
- << space_id << ":" << page_no << ") at "
- << recv_sys->recovered_lsn << ".";
- recv_sys->found_corrupt_log = true;
+ " for redo log record " << type << page_id << " at "
+ << recv_sys.recovered_lsn << ".";
+ recv_sys.found_corrupt_log = true;
return(NULL);
} else {
parse_log:
@@ -1454,6 +1392,7 @@ parse_log:
break;
#endif /* UNIV_LOG_LSN_DEBUG */
case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
+ case MLOG_MEMSET:
#ifdef UNIV_DEBUG
if (page && page_type == FIL_PAGE_TYPE_ALLOCATED
&& end_ptr >= ptr + 2) {
@@ -1476,7 +1415,8 @@ parse_log:
redo log been written with something
older than InnoDB Plugin 1.0.4. */
ut_ad(offs == FIL_PAGE_TYPE
- || srv_is_undo_tablespace(space_id)
+ || srv_is_undo_tablespace(
+ page_id.space())
|| offs == IBUF_TREE_SEG_HEADER
+ IBUF_HEADER + FSEG_HDR_OFFSET
|| offs == PAGE_BTR_IBUF_FREE_LIST
@@ -1502,7 +1442,8 @@ parse_log:
ut_ad(0
/* fil_crypt_rotate_page() writes this */
|| offs == FIL_PAGE_SPACE_ID
- || srv_is_undo_tablespace(space_id)
+ || srv_is_undo_tablespace(
+ page_id.space())
|| offs == IBUF_TREE_SEG_HEADER
+ IBUF_HEADER + FSEG_HDR_SPACE
|| offs == IBUF_TREE_SEG_HEADER
@@ -1534,7 +1475,7 @@ parse_log:
#endif /* UNIV_DEBUG */
ptr = mlog_parse_nbytes(type, ptr, end_ptr, page, page_zip);
if (ptr != NULL && page != NULL
- && page_no == 0 && type == MLOG_4BYTES) {
+ && page_id.page_no() == 0 && type == MLOG_4BYTES) {
ulint offs = mach_read_from_2(old_ptr);
switch (offs) {
fil_space_t* space;
@@ -1545,7 +1486,7 @@ parse_log:
case FSP_HEADER_OFFSET + FSP_SIZE:
case FSP_HEADER_OFFSET + FSP_FREE_LIMIT:
case FSP_HEADER_OFFSET + FSP_FREE + FLST_LEN:
- space = fil_space_get(space_id);
+ space = fil_space_get(page_id.space());
ut_a(space != NULL);
val = mach_read_from_4(page + offs);
@@ -1721,12 +1662,17 @@ parse_log:
break;
case MLOG_IBUF_BITMAP_INIT:
/* Allow anything in page_type when creating a page. */
- ptr = ibuf_parse_bitmap_init(ptr, end_ptr, block, mtr);
+ if (block) ibuf_bitmap_init_apply(block);
break;
case MLOG_INIT_FILE_PAGE2:
/* Allow anything in page_type when creating a page. */
if (block) fsp_apply_init_file_page(block);
break;
+ case MLOG_INIT_FREE_PAGE:
+ /* The page can be zero-filled and its previous
+ contents can be ignored. We do not write or apply
+ this record yet. */
+ break;
case MLOG_WRITE_STRING:
ptr = mlog_parse_string(ptr, end_ptr, page, page_zip);
break;
@@ -1770,7 +1716,7 @@ parse_log:
ptr = const_cast<byte*>(fil_parse_write_crypt_data(ptr, end_ptr, &err));
if (err != DB_SUCCESS) {
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
}
break;
default:
@@ -1778,7 +1724,7 @@ parse_log:
ib::error() << "Incorrect log record type "
<< ib::hex(unsigned(type));
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
}
if (index) {
@@ -1816,7 +1762,7 @@ recv_hash(
ulint space, /*!< in: space */
ulint page_no)/*!< in: page number */
{
- return(hash_calc_hash(recv_fold(space, page_no), recv_sys->addr_hash));
+ return(hash_calc_hash(recv_fold(space, page_no), recv_sys.addr_hash));
}
/*********************************************************************//**
@@ -1829,12 +1775,12 @@ recv_get_fil_addr_struct(
ulint space, /*!< in: space id */
ulint page_no)/*!< in: page number */
{
- ut_ad(mutex_own(&recv_sys->mutex));
+ ut_ad(mutex_own(&recv_sys.mutex));
recv_addr_t* recv_addr;
for (recv_addr = static_cast<recv_addr_t*>(
- HASH_GET_FIRST(recv_sys->addr_hash,
+ HASH_GET_FIRST(recv_sys.addr_hash,
recv_hash(space, page_no)));
recv_addr != 0;
recv_addr = static_cast<recv_addr_t*>(
@@ -1850,26 +1796,18 @@ recv_get_fil_addr_struct(
return(NULL);
}
-/*******************************************************************//**
-Adds a new log record to the hash table of log records. */
-static
-void
-recv_add_to_hash_table(
-/*===================*/
- mlog_id_t type, /*!< in: log record type */
- ulint space, /*!< in: space id */
- ulint page_no, /*!< in: page number */
- byte* body, /*!< in: log record body */
- byte* rec_end, /*!< in: log record end */
- lsn_t start_lsn, /*!< in: start lsn of the mtr */
- lsn_t end_lsn) /*!< in: end lsn of the mtr */
+/** Store a redo log record for applying.
+@param type record type
+@param space tablespace identifier
+@param page_no page number
+@param body record body
+@param rec_end end of record
+@param lsn start LSN of the mini-transaction
+@param end_lsn end LSN of the mini-transaction */
+inline void recv_sys_t::add(mlog_id_t type, ulint space, ulint page_no,
+ byte* body, byte* rec_end, lsn_t lsn,
+ lsn_t end_lsn)
{
- recv_t* recv;
- ulint len;
- recv_data_t* recv_data;
- recv_data_t** prev_field;
- recv_addr_t* recv_addr;
-
ut_ad(type != MLOG_FILE_DELETE);
ut_ad(type != MLOG_FILE_CREATE2);
ut_ad(type != MLOG_FILE_RENAME2);
@@ -1879,21 +1817,18 @@ recv_add_to_hash_table(
ut_ad(type != MLOG_INDEX_LOAD);
ut_ad(type != MLOG_TRUNCATE);
- len = ulint(rec_end - body);
-
- recv = static_cast<recv_t*>(
- mem_heap_alloc(recv_sys->heap, sizeof(recv_t)));
+ recv_t* recv= static_cast<recv_t*>(mem_heap_alloc(heap, sizeof *recv));
recv->type = type;
recv->len = ulint(rec_end - body);
- recv->start_lsn = start_lsn;
+ recv->start_lsn = lsn;
recv->end_lsn = end_lsn;
- recv_addr = recv_get_fil_addr_struct(space, page_no);
+ recv_addr_t* recv_addr = recv_get_fil_addr_struct(space, page_no);
if (recv_addr == NULL) {
recv_addr = static_cast<recv_addr_t*>(
- mem_heap_alloc(recv_sys->heap, sizeof(recv_addr_t)));
+ mem_heap_alloc(heap, sizeof(recv_addr_t)));
recv_addr->space = space;
recv_addr->page_no = page_no;
@@ -1901,50 +1836,49 @@ recv_add_to_hash_table(
UT_LIST_INIT(recv_addr->rec_list, &recv_t::rec_list);
- HASH_INSERT(recv_addr_t, addr_hash, recv_sys->addr_hash,
+ HASH_INSERT(recv_addr_t, addr_hash, addr_hash,
recv_fold(space, page_no), recv_addr);
- recv_sys->n_addrs++;
+ n_addrs++;
}
switch (type) {
case MLOG_INIT_FILE_PAGE2:
case MLOG_ZIP_PAGE_COMPRESS:
+ case MLOG_INIT_FREE_PAGE:
/* Ignore any earlier redo log records for this page. */
ut_ad(recv_addr->state == RECV_NOT_PROCESSED
|| recv_addr->state == RECV_WILL_NOT_READ);
recv_addr->state = RECV_WILL_NOT_READ;
- mlog_init.add(space, page_no, start_lsn);
+ mlog_init.add(space, page_no, lsn);
default:
break;
}
UT_LIST_ADD_LAST(recv_addr->rec_list, recv);
- prev_field = &(recv->data);
+ recv_data_t** prev_field = &recv->data;
/* Store the log record body in chunks of less than srv_page_size:
- recv_sys->heap grows into the buffer pool, and bigger chunks could not
+ heap grows into the buffer pool, and bigger chunks could not
be allocated */
while (rec_end > body) {
+ ulint rec_len = ulint(rec_end - body);
- len = ulint(rec_end - body);
-
- if (len > RECV_DATA_BLOCK_SIZE) {
- len = RECV_DATA_BLOCK_SIZE;
+ if (rec_len > RECV_DATA_BLOCK_SIZE) {
+ rec_len = RECV_DATA_BLOCK_SIZE;
}
- recv_data = static_cast<recv_data_t*>(
- mem_heap_alloc(recv_sys->heap,
- sizeof(recv_data_t) + len));
+ recv_data_t* recv_data = static_cast<recv_data_t*>(
+ mem_heap_alloc(heap, sizeof(recv_data_t) + rec_len));
*prev_field = recv_data;
- memcpy(recv_data + 1, body, len);
+ memcpy(recv_data + 1, body, rec_len);
- prev_field = &(recv_data->next);
+ prev_field = &recv_data->next;
- body += len;
+ body += rec_len;
}
*prev_field = NULL;
@@ -1987,18 +1921,21 @@ lsn of a log record.
@param[in,out] block buffer pool page
@param[in,out] mtr mini-transaction
@param[in,out] recv_addr recovery address
-@param[in] init_lsn the initial LSN where to start recovery */
+@param[in,out] init page initialization operation, or NULL */
static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
- recv_addr_t* recv_addr, lsn_t init_lsn = 0)
+ recv_addr_t* recv_addr,
+ mlog_init_t::init* init = NULL)
{
page_t* page;
page_zip_des_t* page_zip;
- ut_ad(mutex_own(&recv_sys->mutex));
- ut_ad(recv_sys->apply_log_recs);
+ ut_ad(mutex_own(&recv_sys.mutex));
+ ut_ad(recv_sys.apply_log_recs);
ut_ad(recv_needed_recovery);
ut_ad(recv_addr->state != RECV_BEING_PROCESSED);
ut_ad(recv_addr->state != RECV_PROCESSED);
+ ut_ad(!init || init->created);
+ ut_ad(!init || init->lsn);
if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) {
fprintf(stderr, "Applying log to page %u:%u\n",
@@ -2008,7 +1945,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
DBUG_LOG("ib_log", "Applying log to page " << block->page.id);
recv_addr->state = RECV_BEING_PROCESSED;
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
page = block->frame;
page_zip = buf_block_get_page_zip(block);
@@ -2020,19 +1957,9 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
}
+ bool free_page = false;
lsn_t start_lsn = 0, end_lsn = 0;
- fil_space_t* space;
-
- if (srv_is_tablespace_truncated(recv_addr->space)) {
- /* The table will be truncated after applying
- normal redo log records. */
- goto skip_log;
- }
-
- space = fil_space_acquire(recv_addr->space);
- if (!space) {
- goto skip_log;
- }
+ const lsn_t init_lsn = init ? init->lsn : 0;
for (recv_t* recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
recv; recv = UT_LIST_GET_NEXT(rec_list, recv)) {
@@ -2052,18 +1979,11 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
<< get_mlog_string(recv->type)
<< " LSN " << recv->start_lsn << " < "
<< init_lsn);
- } else if (srv_was_tablespace_truncated(space)
- && recv->start_lsn
- < truncate_t::get_truncated_tablespace_init_lsn(
- recv_addr->space)) {
- /* If per-table tablespace was truncated and
- there exist REDO records before truncate that
- are to be applied as part of recovery
- (checkpoint didn't happen since truncate was
- done) skip such records using lsn check as
- they may not stand valid post truncate. */
} else {
- if (!start_lsn) {
+ if (recv->type == MLOG_INIT_FREE_PAGE) {
+ /* This does not really modify the page. */
+ free_page = true;
+ } else if (!start_lsn) {
start_lsn = recv->start_lsn;
}
@@ -2094,8 +2014,7 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
recv_parse_or_apply_log_rec_body(
recv->type, buf, buf + recv->len,
- block->page.id.space(),
- block->page.id.page_no(), true, block, &mtr);
+ block->page.id, true, block, &mtr);
end_lsn = recv->start_lsn + recv->len;
mach_write_to_8(FIL_PAGE_LSN + page, end_lsn);
@@ -2114,9 +2033,6 @@ static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
}
}
- space->release();
-
-skip_log:
#ifdef UNIV_ZIP_DEBUG
ut_ad(!fil_page_index_page_check(page)
|| !page_zip
@@ -2125,8 +2041,15 @@ skip_log:
if (start_lsn) {
log_flush_order_mutex_enter();
- buf_flush_recv_note_modification(block, start_lsn, end_lsn);
+ buf_flush_note_modification(block, start_lsn, end_lsn, NULL);
log_flush_order_mutex_exit();
+ } else if (free_page && init) {
+ /* There have been no operations than MLOG_INIT_FREE_PAGE.
+ Any buffered changes must not be merged. A subsequent
+ buf_page_create() from a user thread should discard
+ any buffered changes. */
+ init->created = false;
+ ut_ad(!mtr.has_modifications());
}
/* Make sure that committing mtr does not change the modification
@@ -2137,7 +2060,7 @@ skip_log:
time_t now = time(NULL);
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
if (recv_max_page_lsn < page_lsn) {
recv_max_page_lsn = page_lsn;
@@ -2146,9 +2069,9 @@ skip_log:
ut_ad(recv_addr->state == RECV_BEING_PROCESSED);
recv_addr->state = RECV_PROCESSED;
- ut_a(recv_sys->n_addrs > 0);
- if (ulint n = --recv_sys->n_addrs) {
- if (recv_sys->report(now)) {
+ ut_a(recv_sys.n_addrs > 0);
+ if (ulint n = --recv_sys.n_addrs) {
+ if (recv_sys.report(now)) {
ib::info() << "To recover: " << n << " pages from log";
service_manager_extend_timeout(
INNODB_EXTEND_TIMEOUT_INTERVAL, "To recover: " ULINTPF " pages from log", n);
@@ -2156,15 +2079,15 @@ skip_log:
}
}
-/** Reduces recv_sys->n_addrs for the corrupted page.
+/** Reduces recv_sys.n_addrs for the corrupted page.
This function should called when srv_force_recovery > 0.
@param[in] page_id page id of the corrupted page */
void recv_recover_corrupt_page(page_id_t page_id)
{
ut_ad(srv_force_recovery);
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
- if (!recv_sys->apply_log_recs) {
+ if (!recv_sys.apply_log_recs) {
} else if (recv_addr_t* recv_addr = recv_get_fil_addr_struct(
page_id.space(), page_id.page_no())) {
switch (recv_addr->state) {
@@ -2176,12 +2099,12 @@ void recv_recover_corrupt_page(page_id_t page_id)
break;
default:
recv_addr->state = RECV_PROCESSED;
- ut_ad(recv_sys->n_addrs);
- recv_sys->n_addrs--;
+ ut_ad(recv_sys.n_addrs);
+ recv_sys.n_addrs--;
}
}
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
}
/** Apply any buffered redo log to a page that was just read from a data file.
@@ -2206,8 +2129,8 @@ void recv_recover_page(buf_page_t* bpage)
__FILE__, __LINE__, &mtr);
ut_a(success);
- mutex_enter(&recv_sys->mutex);
- if (!recv_sys->apply_log_recs) {
+ mutex_enter(&recv_sys.mutex);
+ if (!recv_sys.apply_log_recs) {
} else if (recv_addr_t* recv_addr = recv_get_fil_addr_struct(
bpage->id.space(), bpage->id.page_no())) {
switch (recv_addr->state) {
@@ -2222,7 +2145,7 @@ void recv_recover_page(buf_page_t* bpage)
mtr.commit();
func_exit:
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
ut_ad(mtr.has_committed());
}
@@ -2248,10 +2171,10 @@ static void recv_read_in_area(const page_id_t page_id)
}
}
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
buf_read_recv_pages(FALSE, page_id.space(), page_nos,
ulint(p - page_nos));
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
}
/** This is another low level function for the recovery system
@@ -2274,12 +2197,12 @@ static buf_block_t* recv_recovery_create_page_low(const page_id_t page_id,
<< " < " << i.lsn);
recv_addr->state= RECV_PROCESSED;
ignore:
- ut_a(recv_sys->n_addrs);
- recv_sys->n_addrs--;
+ ut_a(recv_sys.n_addrs);
+ recv_sys.n_addrs--;
return NULL;
}
- fil_space_t *space= fil_space_acquire(recv_addr->space);
+ fil_space_t *space= fil_space_acquire_for_io(recv_addr->space);
if (!space)
{
recv_addr->state= RECV_PROCESSED;
@@ -2289,7 +2212,7 @@ ignore:
if (space->enable_lsn)
{
init_fail:
- space->release();
+ space->release_for_io();
recv_addr->state= RECV_NOT_PROCESSED;
return NULL;
}
@@ -2309,8 +2232,7 @@ init_fail:
mtr.start();
mtr.set_log_mode(MTR_LOG_NONE);
- buf_block_t *block= buf_page_create(page_id, page_size_t(space->flags),
- &mtr);
+ buf_block_t *block= buf_page_create(page_id, space->zip_size(), &mtr);
if (recv_addr->state == RECV_PROCESSED)
/* The page happened to exist in the buffer pool, or it was
just being read in. Before buf_page_get_with_no_latch() returned,
@@ -2321,11 +2243,11 @@ init_fail:
i.created= true;
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
mtr.x_latch_at_savepoint(0, block);
- recv_recover_page(block, mtr, recv_addr, i.lsn);
+ recv_recover_page(block, mtr, recv_addr, &i);
ut_ad(mtr.has_committed());
}
- space->release();
+ space->release_for_io();
return block;
}
@@ -2335,15 +2257,13 @@ to create a page which has buffered intialized redo log records.
@return whether the page creation successfully */
buf_block_t* recv_recovery_create_page_low(const page_id_t page_id)
{
- buf_block_t* block= NULL;
- mutex_enter(&recv_sys->mutex);
+ buf_block_t* block= nullptr;
+ mutex_enter(&recv_sys.mutex);
recv_addr_t* recv_addr= recv_get_fil_addr_struct(page_id.space(),
page_id.page_no());
if (recv_addr && recv_addr->state == RECV_WILL_NOT_READ)
- {
block= recv_recovery_create_page_low(page_id, recv_addr);
- }
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
return block;
}
@@ -2356,18 +2276,18 @@ void recv_apply_hashed_log_recs(bool last_batch)
|| srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT);
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
- while (recv_sys->apply_batch_on) {
- bool abort = recv_sys->found_corrupt_log;
- mutex_exit(&recv_sys->mutex);
+ while (recv_sys.apply_batch_on) {
+ bool abort = recv_sys.found_corrupt_log;
+ mutex_exit(&recv_sys.mutex);
if (abort) {
return;
}
os_thread_sleep(500000);
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
}
ut_ad(!last_batch == log_mutex_own());
@@ -2378,7 +2298,18 @@ void recv_apply_hashed_log_recs(bool last_batch)
ut_d(recv_no_log_write = recv_no_ibuf_operations);
- if (ulint n = recv_sys->n_addrs) {
+ if (ulint n = recv_sys.n_addrs) {
+ if (!log_sys.log.subformat && !srv_force_recovery
+ && srv_undo_tablespaces_open) {
+ ib::error() << "Recovery of separately logged"
+ " TRUNCATE operations is no longer supported."
+ " Set innodb_force_recovery=1"
+ " if no *trunc.log files exist";
+ recv_sys.found_corrupt_log = true;
+ mutex_exit(&recv_sys.mutex);
+ return;
+ }
+
const char* msg = last_batch
? "Starting final batch to recover "
: "Starting a batch to recover ";
@@ -2386,11 +2317,11 @@ void recv_apply_hashed_log_recs(bool last_batch)
sd_notifyf(0, "STATUS=%s" ULINTPF " pages from redo log",
msg, n);
}
- recv_sys->apply_log_recs = TRUE;
- recv_sys->apply_batch_on = TRUE;
+ recv_sys.apply_log_recs = true;
+ recv_sys.apply_batch_on = true;
for (ulint id = srv_undo_tablespaces_open; id--; ) {
- recv_sys_t::trunc& t = recv_sys->truncated_undo_spaces[id];
+ recv_sys_t::trunc& t = recv_sys.truncated_undo_spaces[id];
if (t.lsn) {
recv_addr_trim(id + srv_undo_space_id_start, t.pages,
t.lsn);
@@ -2399,16 +2330,16 @@ void recv_apply_hashed_log_recs(bool last_batch)
mtr_t mtr;
- for (ulint i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) {
+ for (ulint i = 0; i < hash_get_n_cells(recv_sys.addr_hash); i++) {
for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>(
- HASH_GET_FIRST(recv_sys->addr_hash, i));
+ HASH_GET_FIRST(recv_sys.addr_hash, i));
recv_addr;
recv_addr = static_cast<recv_addr_t*>(
HASH_GET_NEXT(addr_hash, recv_addr))) {
if (!UT_LIST_GET_LEN(recv_addr->rec_list)) {
ignore:
- ut_a(recv_sys->n_addrs);
- recv_sys->n_addrs--;
+ ut_a(recv_sys.n_addrs);
+ recv_sys.n_addrs--;
continue;
}
@@ -2424,13 +2355,6 @@ ignore:
break;
}
- if (srv_is_tablespace_truncated(recv_addr->space)) {
- /* Avoid applying REDO log for the tablespace
- that is schedule for TRUNCATE. */
- recv_addr->state = RECV_DISCARDED;
- goto ignore;
- }
-
const page_id_t page_id(recv_addr->space,
recv_addr->page_no);
@@ -2439,8 +2363,7 @@ apply:
mtr.start();
mtr.set_log_mode(MTR_LOG_NONE);
if (buf_block_t* block = buf_page_get_low(
- page_id, univ_page_size,
- RW_X_LATCH, NULL,
+ page_id, 0, RW_X_LATCH, NULL,
BUF_GET_IF_IN_POOL,
__FILE__, __LINE__, &mtr, NULL)) {
buf_block_dbg_add_level(
@@ -2461,16 +2384,16 @@ apply:
/* Wait until all the pages have been processed */
- while (recv_sys->n_addrs != 0) {
- const bool abort = recv_sys->found_corrupt_log
- || recv_sys->found_corrupt_fs;
+ while (recv_sys.n_addrs != 0) {
+ const bool abort = recv_sys.found_corrupt_log
+ || recv_sys.found_corrupt_fs;
- if (recv_sys->found_corrupt_fs && !srv_force_recovery) {
+ if (recv_sys.found_corrupt_fs && !srv_force_recovery) {
ib::info() << "Set innodb_force_recovery=1"
" to ignore corrupted pages.";
}
- mutex_exit(&(recv_sys->mutex));
+ mutex_exit(&(recv_sys.mutex));
if (abort) {
return;
@@ -2478,47 +2401,47 @@ apply:
os_thread_sleep(500000);
- mutex_enter(&(recv_sys->mutex));
+ mutex_enter(&(recv_sys.mutex));
}
if (!last_batch) {
/* Flush all the file pages to disk and invalidate them in
the buffer pool */
- mutex_exit(&(recv_sys->mutex));
+ mutex_exit(&(recv_sys.mutex));
log_mutex_exit();
/* Stop the recv_writer thread from issuing any LRU
flush batches. */
- mutex_enter(&recv_sys->writer_mutex);
+ mutex_enter(&recv_sys.writer_mutex);
/* Wait for any currently run batch to end. */
buf_flush_wait_LRU_batch_end();
- os_event_reset(recv_sys->flush_end);
- recv_sys->flush_type = BUF_FLUSH_LIST;
- os_event_set(recv_sys->flush_start);
- os_event_wait(recv_sys->flush_end);
+ os_event_reset(recv_sys.flush_end);
+ recv_sys.flush_type = BUF_FLUSH_LIST;
+ os_event_set(recv_sys.flush_start);
+ os_event_wait(recv_sys.flush_end);
buf_pool_invalidate();
/* Allow batches from recv_writer thread. */
- mutex_exit(&recv_sys->writer_mutex);
+ mutex_exit(&recv_sys.writer_mutex);
log_mutex_enter();
- mutex_enter(&(recv_sys->mutex));
+ mutex_enter(&(recv_sys.mutex));
mlog_init.reset();
} else if (!recv_no_ibuf_operations) {
/* We skipped this in buf_page_create(). */
mlog_init.ibuf_merge(mtr);
}
- recv_sys->apply_log_recs = FALSE;
- recv_sys->apply_batch_on = FALSE;
+ recv_sys.apply_log_recs = false;
+ recv_sys.apply_batch_on = false;
- recv_sys_empty_hash();
+ recv_sys.empty();
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
}
/** Tries to parse a single log record.
@@ -2564,7 +2487,7 @@ recv_parse_log_rec(
if (new_ptr != NULL) {
const lsn_t lsn = static_cast<lsn_t>(
*space) << 32 | *page_no;
- ut_a(lsn == recv_sys->recovered_lsn);
+ ut_a(lsn == recv_sys.recovered_lsn);
}
*type = MLOG_LSN;
@@ -2585,7 +2508,7 @@ recv_parse_log_rec(
case MLOG_CHECKPOINT | MLOG_SINGLE_REC_FLAG:
ib::error() << "Incorrect log record type "
<< ib::hex(unsigned(*ptr));
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
return(0);
}
@@ -2600,7 +2523,8 @@ recv_parse_log_rec(
const byte* old_ptr = new_ptr;
new_ptr = recv_parse_or_apply_log_rec_body(
- *type, new_ptr, end_ptr, *space, *page_no, apply, NULL, NULL);
+ *type, new_ptr, end_ptr, page_id_t(*space, *page_no), apply,
+ NULL, NULL);
if (UNIV_UNLIKELY(new_ptr == NULL)) {
return(0);
@@ -2615,7 +2539,7 @@ recv_parse_log_rec(
recv_spaces_t::iterator it = recv_spaces.find(*space);
- ut_ad(!recv_sys->mlog_checkpoint_lsn
+ ut_ad(!recv_sys.mlog_checkpoint_lsn
|| *space == TRX_SYS_SPACE
|| srv_is_undo_tablespace(*space)
|| it != recv_spaces.end());
@@ -2640,17 +2564,12 @@ recv_calc_lsn_on_data_add(
ib_uint64_t len) /*!< in: this many bytes of data is
added, log block headers not included */
{
- ulint frag_len;
- ib_uint64_t lsn_len;
-
- frag_len = (lsn % OS_FILE_LOG_BLOCK_SIZE) - LOG_BLOCK_HDR_SIZE;
- ut_ad(frag_len < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
- - LOG_BLOCK_TRL_SIZE);
- lsn_len = len;
- lsn_len += (lsn_len + frag_len)
- / (OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_HDR_SIZE
- - LOG_BLOCK_TRL_SIZE)
- * (LOG_BLOCK_HDR_SIZE + LOG_BLOCK_TRL_SIZE);
+ unsigned frag_len = (lsn % OS_FILE_LOG_BLOCK_SIZE) - LOG_BLOCK_HDR_SIZE;
+ unsigned payload_size = log_sys.payload_size();
+ ut_ad(frag_len < payload_size);
+ lsn_t lsn_len = len;
+ lsn_len += (lsn_len + frag_len) / payload_size
+ * (OS_FILE_LOG_BLOCK_SIZE - payload_size);
return(lsn + lsn_len);
}
@@ -2672,28 +2591,28 @@ recv_report_corrupt_log(
ib::error() <<
"############### CORRUPT LOG RECORD FOUND ##################";
- const ulint ptr_offset = ulint(ptr - recv_sys->buf);
+ const ulint ptr_offset = ulint(ptr - recv_sys.buf);
ib::info() << "Log record type " << type << ", page " << space << ":"
<< page_no << ". Log parsing proceeded successfully up to "
- << recv_sys->recovered_lsn << ". Previous log record type "
+ << recv_sys.recovered_lsn << ". Previous log record type "
<< recv_previous_parsed_rec_type << ", is multi "
<< recv_previous_parsed_rec_is_multi << " Recv offset "
<< ptr_offset << ", prev "
<< recv_previous_parsed_rec_offset;
- ut_ad(ptr <= recv_sys->buf + recv_sys->len);
+ ut_ad(ptr <= recv_sys.buf + recv_sys.len);
const ulint limit = 100;
const ulint prev_offset = std::min(recv_previous_parsed_rec_offset,
ptr_offset);
const ulint before = std::min(prev_offset, limit);
- const ulint after = std::min(recv_sys->len - ptr_offset, limit);
+ const ulint after = std::min(recv_sys.len - ptr_offset, limit);
ib::info() << "Hex dump starting " << before << " bytes before and"
" ending " << after << " bytes after the corrupted record:";
- const byte* start = recv_sys->buf + prev_offset - before;
+ const byte* start = recv_sys.buf + prev_offset - before;
ut_print_buf(stderr, start, ulint(ptr - start) + after);
putc('\n', stderr);
@@ -2735,17 +2654,16 @@ of buffer pool. Store last_stored_lsn if it is not in last phase
read redo logs. */
static bool recv_sys_heap_check(store_t* store, ulint available_mem)
{
- if (*store != STORE_NO
- && mem_heap_get_size(recv_sys->heap) >= available_mem)
+ if (*store != STORE_NO && mem_heap_get_size(recv_sys.heap) >= available_mem)
{
if (*store == STORE_YES)
- recv_sys->last_stored_lsn= recv_sys->recovered_lsn;
+ recv_sys.last_stored_lsn= recv_sys.recovered_lsn;
*store= STORE_NO;
DBUG_PRINT("ib_log",("Ran out of memory and last "
"stored lsn " LSN_PF " last stored offset "
- ULINTPF "\n",recv_sys->recovered_lsn,
- recv_sys->recovered_offset));
+ ULINTPF "\n",
+ recv_sys.recovered_lsn, recv_sys.recovered_offset));
return true;
}
@@ -2776,12 +2694,12 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t* store,
const bool last_phase = (*store == STORE_IF_EXISTS);
ut_ad(log_mutex_own());
- ut_ad(mutex_own(&recv_sys->mutex));
- ut_ad(recv_sys->parse_start_lsn != 0);
+ ut_ad(mutex_own(&recv_sys.mutex));
+ ut_ad(recv_sys.parse_start_lsn != 0);
loop:
- ptr = recv_sys->buf + recv_sys->recovered_offset;
+ ptr = recv_sys.buf + recv_sys.recovered_offset;
- end_ptr = recv_sys->buf + recv_sys->len;
+ end_ptr = recv_sys.buf + recv_sys.len;
if (ptr == end_ptr) {
@@ -2809,7 +2727,7 @@ loop:
if (single_rec) {
/* The mtr did not modify multiple pages */
- old_lsn = recv_sys->recovered_lsn;
+ old_lsn = recv_sys.recovered_lsn;
/* Try to parse a log record, fetching its type, space id,
page no, and a pointer to the body of the log record */
@@ -2817,12 +2735,12 @@ loop:
len = recv_parse_log_rec(&type, ptr, end_ptr, &space,
&page_no, apply, &body);
- if (recv_sys->found_corrupt_log) {
+ if (recv_sys.found_corrupt_log) {
recv_report_corrupt_log(ptr, type, space, page_no);
return(true);
}
- if (recv_sys->found_corrupt_fs) {
+ if (recv_sys.found_corrupt_fs) {
return(true);
}
@@ -2832,7 +2750,7 @@ loop:
new_recovered_lsn = recv_calc_lsn_on_data_add(old_lsn, len);
- if (new_recovered_lsn > recv_sys->scanned_lsn) {
+ if (new_recovered_lsn > recv_sys.scanned_lsn) {
/* The log record filled a log block, and we require
that also the next log block should have been scanned
in */
@@ -2841,11 +2759,11 @@ loop:
}
recv_previous_parsed_rec_type = type;
- recv_previous_parsed_rec_offset = recv_sys->recovered_offset;
+ recv_previous_parsed_rec_offset = recv_sys.recovered_offset;
recv_previous_parsed_rec_is_multi = 0;
- recv_sys->recovered_offset += len;
- recv_sys->recovered_lsn = new_recovered_lsn;
+ recv_sys.recovered_offset += len;
+ recv_sys.recovered_lsn = new_recovered_lsn;
switch (type) {
lsn_t lsn;
@@ -2861,9 +2779,9 @@ loop:
"MLOG_CHECKPOINT(" LSN_PF ") %s at "
LSN_PF "\n", lsn,
lsn != checkpoint_lsn ? "ignored"
- : recv_sys->mlog_checkpoint_lsn
+ : recv_sys.mlog_checkpoint_lsn
? "reread" : "read",
- recv_sys->recovered_lsn);
+ recv_sys.recovered_lsn);
}
DBUG_PRINT("ib_log",
@@ -2871,18 +2789,18 @@ loop:
LSN_PF,
lsn,
lsn != checkpoint_lsn ? "ignored"
- : recv_sys->mlog_checkpoint_lsn
+ : recv_sys.mlog_checkpoint_lsn
? "reread" : "read",
- recv_sys->recovered_lsn));
+ recv_sys.recovered_lsn));
if (lsn == checkpoint_lsn) {
- if (recv_sys->mlog_checkpoint_lsn) {
- ut_ad(recv_sys->mlog_checkpoint_lsn
- <= recv_sys->recovered_lsn);
+ if (recv_sys.mlog_checkpoint_lsn) {
+ ut_ad(recv_sys.mlog_checkpoint_lsn
+ <= recv_sys.recovered_lsn);
break;
}
- recv_sys->mlog_checkpoint_lsn
- = recv_sys->recovered_lsn;
+ recv_sys.mlog_checkpoint_lsn
+ = recv_sys.recovered_lsn;
return(true);
}
break;
@@ -2904,10 +2822,10 @@ loop:
}
/* fall through */
case STORE_YES:
- recv_add_to_hash_table(
+ recv_sys.add(
type, space, page_no, body,
ptr + len, old_lsn,
- recv_sys->recovered_lsn);
+ recv_sys.recovered_lsn);
}
/* fall through */
case MLOG_INDEX_LOAD:
@@ -2944,7 +2862,7 @@ loop:
&type, ptr, end_ptr, &space, &page_no,
false, &body);
- if (recv_sys->found_corrupt_log) {
+ if (recv_sys.found_corrupt_log) {
corrupted_log:
recv_report_corrupt_log(
ptr, type, space, page_no);
@@ -2954,11 +2872,11 @@ corrupted_log:
if (ptr == end_ptr) {
} else if (type == MLOG_CHECKPOINT
|| (*ptr & MLOG_SINGLE_REC_FLAG)) {
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
goto corrupted_log;
}
- if (recv_sys->found_corrupt_fs) {
+ if (recv_sys.found_corrupt_fs) {
return(true);
}
@@ -2968,7 +2886,7 @@ corrupted_log:
recv_previous_parsed_rec_type = type;
recv_previous_parsed_rec_offset
- = recv_sys->recovered_offset + total_len;
+ = recv_sys.recovered_offset + total_len;
recv_previous_parsed_rec_is_multi = 1;
/* MLOG_FILE_NAME redo log records doesn't make changes
@@ -2981,10 +2899,10 @@ corrupted_log:
if (only_mlog_file) {
new_recovered_lsn = recv_calc_lsn_on_data_add(
- recv_sys->recovered_lsn, len);
+ recv_sys.recovered_lsn, len);
mlog_rec_len += len;
- recv_sys->recovered_offset += len;
- recv_sys->recovered_lsn = new_recovered_lsn;
+ recv_sys.recovered_offset += len;
+ recv_sys.recovered_lsn = new_recovered_lsn;
}
total_len += len;
@@ -2998,7 +2916,7 @@ corrupted_log:
": multi-log end"
" total_len " ULINTPF
" n=" ULINTPF,
- recv_sys->recovered_lsn,
+ recv_sys.recovered_lsn,
total_len, n_recs));
total_len -= mlog_rec_len;
break;
@@ -3008,14 +2926,14 @@ corrupted_log:
("scan " LSN_PF ": multi-log rec %s"
" len " ULINTPF
" page " ULINTPF ":" ULINTPF,
- recv_sys->recovered_lsn,
+ recv_sys.recovered_lsn,
get_mlog_string(type), len, space, page_no));
}
new_recovered_lsn = recv_calc_lsn_on_data_add(
- recv_sys->recovered_lsn, total_len);
+ recv_sys.recovered_lsn, total_len);
- if (new_recovered_lsn > recv_sys->scanned_lsn) {
+ if (new_recovered_lsn > recv_sys.scanned_lsn) {
/* The log record filled a log block, and we require
that also the next log block should have been scanned
in */
@@ -3025,10 +2943,10 @@ corrupted_log:
/* Add all the records to the hash table */
- ptr = recv_sys->buf + recv_sys->recovered_offset;
+ ptr = recv_sys.buf + recv_sys.recovered_offset;
for (;;) {
- old_lsn = recv_sys->recovered_lsn;
+ old_lsn = recv_sys.recovered_lsn;
/* This will apply MLOG_FILE_ records. We
had to skip them in the first scan, because we
did not know if the mini-transaction was
@@ -3037,21 +2955,21 @@ corrupted_log:
&type, ptr, end_ptr, &space, &page_no,
apply, &body);
- if (recv_sys->found_corrupt_log
+ if (recv_sys.found_corrupt_log
&& !recv_report_corrupt_log(
ptr, type, space, page_no)) {
return(true);
}
- if (recv_sys->found_corrupt_fs) {
+ if (recv_sys.found_corrupt_fs) {
return(true);
}
ut_a(len != 0);
ut_a(!(*ptr & MLOG_SINGLE_REC_FLAG));
- recv_sys->recovered_offset += len;
- recv_sys->recovered_lsn
+ recv_sys.recovered_offset += len;
+ recv_sys.recovered_lsn
= recv_calc_lsn_on_data_add(old_lsn, len);
switch (type) {
@@ -3088,7 +3006,7 @@ corrupted_log:
}
/* fall through */
case STORE_YES:
- recv_add_to_hash_table(
+ recv_sys.add(
type, space, page_no,
body, ptr + len,
old_lsn,
@@ -3104,7 +3022,7 @@ corrupted_log:
}
/** Adds data from a new log block to the parsing buffer of recv_sys if
-recv_sys->parse_start_lsn is non-zero.
+recv_sys.parse_start_lsn is non-zero.
@param[in] log_block log block to add
@param[in] scanned_lsn lsn of how far we were able to find
data in this log block
@@ -3116,9 +3034,9 @@ bool recv_sys_add_to_parsing_buf(const byte* log_block, lsn_t scanned_lsn)
ulint start_offset;
ulint end_offset;
- ut_ad(scanned_lsn >= recv_sys->scanned_lsn);
+ ut_ad(scanned_lsn >= recv_sys.scanned_lsn);
- if (!recv_sys->parse_start_lsn) {
+ if (!recv_sys.parse_start_lsn) {
/* Cannot start parsing yet because no start point for
it found */
return(false);
@@ -3126,18 +3044,18 @@ bool recv_sys_add_to_parsing_buf(const byte* log_block, lsn_t scanned_lsn)
data_len = log_block_get_data_len(log_block);
- if (recv_sys->parse_start_lsn >= scanned_lsn) {
+ if (recv_sys.parse_start_lsn >= scanned_lsn) {
return(false);
- } else if (recv_sys->scanned_lsn >= scanned_lsn) {
+ } else if (recv_sys.scanned_lsn >= scanned_lsn) {
return(false);
- } else if (recv_sys->parse_start_lsn > recv_sys->scanned_lsn) {
- more_len = (ulint) (scanned_lsn - recv_sys->parse_start_lsn);
+ } else if (recv_sys.parse_start_lsn > recv_sys.scanned_lsn) {
+ more_len = (ulint) (scanned_lsn - recv_sys.parse_start_lsn);
} else {
- more_len = (ulint) (scanned_lsn - recv_sys->scanned_lsn);
+ more_len = (ulint) (scanned_lsn - recv_sys.scanned_lsn);
}
if (more_len == 0) {
@@ -3152,21 +3070,17 @@ bool recv_sys_add_to_parsing_buf(const byte* log_block, lsn_t scanned_lsn)
start_offset = LOG_BLOCK_HDR_SIZE;
}
- end_offset = data_len;
-
- if (end_offset > OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE) {
- end_offset = OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE;
- }
+ end_offset = std::min<ulint>(data_len, log_sys.trailer_offset());
ut_ad(start_offset <= end_offset);
if (start_offset < end_offset) {
- ut_memcpy(recv_sys->buf + recv_sys->len,
+ ut_memcpy(recv_sys.buf + recv_sys.len,
log_block + start_offset, end_offset - start_offset);
- recv_sys->len += end_offset - start_offset;
+ recv_sys.len += end_offset - start_offset;
- ut_a(recv_sys->len <= RECV_PARSING_BUF_SIZE);
+ ut_a(recv_sys.len <= RECV_PARSING_BUF_SIZE);
}
return(true);
@@ -3175,13 +3089,12 @@ bool recv_sys_add_to_parsing_buf(const byte* log_block, lsn_t scanned_lsn)
/** Moves the parsing buffer data left to the buffer start. */
void recv_sys_justify_left_parsing_buf()
{
- memmove(recv_sys->buf,
- recv_sys->buf + recv_sys->recovered_offset,
- recv_sys->len - recv_sys->recovered_offset);
+ memmove(recv_sys.buf, recv_sys.buf + recv_sys.recovered_offset,
+ recv_sys.len - recv_sys.recovered_offset);
- recv_sys->len -= recv_sys->recovered_offset;
+ recv_sys.len -= recv_sys.recovered_offset;
- recv_sys->recovered_offset = 0;
+ recv_sys.recovered_offset = 0;
}
/** Scan redo log from a buffer and stores new log data to the parsing buffer.
@@ -3216,7 +3129,7 @@ static bool recv_scan_log_recs(
bool finished = false;
ulint data_len;
bool more_data = false;
- bool apply = recv_sys->mlog_checkpoint_lsn != 0;
+ bool apply = recv_sys.mlog_checkpoint_lsn != 0;
ulint recv_parsing_buf_size = RECV_PARSING_BUF_SIZE;
const bool last_phase = (*store_to_hash == STORE_IF_EXISTS);
ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
@@ -3243,10 +3156,10 @@ static bool recv_scan_log_recs(
data_len = log_block_get_data_len(log_block);
- if (scanned_lsn + data_len > recv_sys->scanned_lsn
+ if (scanned_lsn + data_len > recv_sys.scanned_lsn
&& log_block_get_checkpoint_no(log_block)
- < recv_sys->scanned_checkpoint_no
- && (recv_sys->scanned_checkpoint_no
+ < recv_sys.scanned_checkpoint_no
+ && (recv_sys.scanned_checkpoint_no
- log_block_get_checkpoint_no(log_block)
> 0x80000000UL)) {
@@ -3256,16 +3169,16 @@ static bool recv_scan_log_recs(
break;
}
- if (!recv_sys->parse_start_lsn
+ if (!recv_sys.parse_start_lsn
&& (log_block_get_first_rec_group(log_block) > 0)) {
/* We found a point from which to start the parsing
of log records */
- recv_sys->parse_start_lsn = scanned_lsn
+ recv_sys.parse_start_lsn = scanned_lsn
+ log_block_get_first_rec_group(log_block);
- recv_sys->scanned_lsn = recv_sys->parse_start_lsn;
- recv_sys->recovered_lsn = recv_sys->parse_start_lsn;
+ recv_sys.scanned_lsn = recv_sys.parse_start_lsn;
+ recv_sys.recovered_lsn = recv_sys.parse_start_lsn;
}
scanned_lsn += data_len;
@@ -3276,17 +3189,17 @@ static bool recv_scan_log_recs(
&& checkpoint_lsn == mach_read_from_8(LOG_BLOCK_HDR_SIZE
+ 1 + log_block)) {
/* The redo log is logically empty. */
- ut_ad(recv_sys->mlog_checkpoint_lsn == 0
- || recv_sys->mlog_checkpoint_lsn
+ ut_ad(recv_sys.mlog_checkpoint_lsn == 0
+ || recv_sys.mlog_checkpoint_lsn
== checkpoint_lsn);
- recv_sys->mlog_checkpoint_lsn = checkpoint_lsn;
+ recv_sys.mlog_checkpoint_lsn = checkpoint_lsn;
DBUG_PRINT("ib_log", ("found empty log; LSN=" LSN_PF,
scanned_lsn));
finished = true;
break;
}
- if (scanned_lsn > recv_sys->scanned_lsn) {
+ if (scanned_lsn > recv_sys.scanned_lsn) {
ut_ad(!srv_log_files_created);
if (!recv_needed_recovery) {
recv_needed_recovery = true;
@@ -3299,7 +3212,7 @@ static bool recv_scan_log_recs(
ib::info() << "Starting crash recovery from"
" checkpoint LSN="
- << recv_sys->scanned_lsn;
+ << recv_sys.scanned_lsn;
}
/* We were able to find more log data: add it to the
@@ -3312,12 +3225,12 @@ static bool recv_scan_log_recs(
= (70 * 1024);
);
- if (recv_sys->len + 4 * OS_FILE_LOG_BLOCK_SIZE
+ if (recv_sys.len + 4 * OS_FILE_LOG_BLOCK_SIZE
>= recv_parsing_buf_size) {
ib::error() << "Log parsing buffer overflow."
" Recovery may have failed!";
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
if (!srv_force_recovery) {
ib::error()
@@ -3325,20 +3238,20 @@ static bool recv_scan_log_recs(
" to ignore this error.";
return(true);
}
- } else if (!recv_sys->found_corrupt_log) {
+ } else if (!recv_sys.found_corrupt_log) {
more_data = recv_sys_add_to_parsing_buf(
log_block, scanned_lsn);
}
- recv_sys->scanned_lsn = scanned_lsn;
- recv_sys->scanned_checkpoint_no
+ recv_sys.scanned_lsn = scanned_lsn;
+ recv_sys.scanned_checkpoint_no
= log_block_get_checkpoint_no(log_block);
}
/* During last phase of scanning, there can be redo logs
- left in recv_sys->buf to parse & store it in recv_sys->heap */
+ left in recv_sys.buf to parse & store it in recv_sys.heap */
if (last_phase
- && recv_sys->recovered_lsn < recv_sys->scanned_lsn) {
+ && recv_sys.recovered_lsn < recv_sys.scanned_lsn) {
more_data = true;
}
@@ -3353,38 +3266,38 @@ static bool recv_scan_log_recs(
*group_scanned_lsn = scanned_lsn;
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
- if (more_data && !recv_sys->found_corrupt_log) {
+ if (more_data && !recv_sys.found_corrupt_log) {
/* Try to parse more log records */
if (recv_parse_log_recs(checkpoint_lsn,
store_to_hash, available_mem,
apply)) {
- ut_ad(recv_sys->found_corrupt_log
- || recv_sys->found_corrupt_fs
- || recv_sys->mlog_checkpoint_lsn
- == recv_sys->recovered_lsn);
+ ut_ad(recv_sys.found_corrupt_log
+ || recv_sys.found_corrupt_fs
+ || recv_sys.mlog_checkpoint_lsn
+ == recv_sys.recovered_lsn);
finished = true;
goto func_exit;
}
recv_sys_heap_check(store_to_hash, available_mem);
- if (recv_sys->recovered_offset > recv_parsing_buf_size / 4) {
+ if (recv_sys.recovered_offset > recv_parsing_buf_size / 4) {
/* Move parsing buffer data to the buffer start */
recv_sys_justify_left_parsing_buf();
}
/* Need to re-parse the redo log which're stored
- in recv_sys->buf */
+ in recv_sys.buf */
if (last_phase && *store_to_hash == STORE_NO) {
finished = false;
}
}
func_exit:
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
return(finished);
}
@@ -3404,28 +3317,28 @@ recv_group_scan_log_recs(
bool last_phase)
{
DBUG_ENTER("recv_group_scan_log_recs");
- DBUG_ASSERT(!last_phase || recv_sys->mlog_checkpoint_lsn > 0);
+ DBUG_ASSERT(!last_phase || recv_sys.mlog_checkpoint_lsn > 0);
- mutex_enter(&recv_sys->mutex);
- recv_sys->len = 0;
- recv_sys->recovered_offset = 0;
- recv_sys->n_addrs = 0;
- recv_sys_empty_hash();
+ mutex_enter(&recv_sys.mutex);
+ recv_sys.len = 0;
+ recv_sys.recovered_offset = 0;
+ recv_sys.n_addrs = 0;
+ recv_sys.empty();
srv_start_lsn = *contiguous_lsn;
- recv_sys->parse_start_lsn = *contiguous_lsn;
- recv_sys->scanned_lsn = *contiguous_lsn;
- recv_sys->recovered_lsn = *contiguous_lsn;
- recv_sys->scanned_checkpoint_no = 0;
+ recv_sys.parse_start_lsn = *contiguous_lsn;
+ recv_sys.scanned_lsn = *contiguous_lsn;
+ recv_sys.recovered_lsn = *contiguous_lsn;
+ recv_sys.scanned_checkpoint_no = 0;
recv_previous_parsed_rec_type = MLOG_SINGLE_REC_FLAG;
recv_previous_parsed_rec_offset = 0;
recv_previous_parsed_rec_is_multi = 0;
ut_ad(recv_max_page_lsn == 0);
ut_ad(last_phase || !recv_writer_thread_active);
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
lsn_t start_lsn;
lsn_t end_lsn;
- store_t store_to_hash = recv_sys->mlog_checkpoint_lsn == 0
+ store_t store_to_hash = recv_sys.mlog_checkpoint_lsn == 0
? STORE_NO : (last_phase ? STORE_IF_EXISTS : STORE_YES);
ulint available_mem = (buf_pool_get_n_pages() * 2 / 3)
<< srv_page_size_shift;
@@ -3442,7 +3355,7 @@ recv_group_scan_log_recs(
finished the redo log scan. */
recv_apply_hashed_log_recs(false);
/* Rescan the redo logs from last stored lsn */
- end_lsn = recv_sys->recovered_lsn;
+ end_lsn = recv_sys.recovered_lsn;
}
start_lsn = ut_uint64_align_down(end_lsn,
@@ -3456,7 +3369,7 @@ recv_group_scan_log_recs(
start_lsn, end_lsn,
contiguous_lsn, &log_sys.log.scanned_lsn));
- if (recv_sys->found_corrupt_log || recv_sys->found_corrupt_fs) {
+ if (recv_sys.found_corrupt_log || recv_sys.found_corrupt_fs) {
DBUG_RETURN(false);
}
@@ -3477,10 +3390,12 @@ recv_init_missing_space(dberr_t err, const recv_spaces_t::const_iterator& i)
{
if (srv_operation == SRV_OPERATION_RESTORE
|| srv_operation == SRV_OPERATION_RESTORE_EXPORT) {
- ib::warn() << "Tablespace " << i->first << " was not"
- " found at " << i->second.name << " when"
- " restoring a (partial?) backup. All redo log"
- " for this file will be ignored!";
+ if (i->second.name.find(TEMP_TABLE_PATH_PREFIX) != std::string::npos) {
+ ib::warn() << "Tablespace " << i->first << " was not"
+ " found at " << i->second.name << " when"
+ " restoring a (partial?) backup. All redo log"
+ " for this file will be ignored!";
+ }
return(err);
}
@@ -3516,9 +3431,9 @@ recv_validate_tablespace(bool rescan, bool& missing_tablespace)
{
dberr_t err = DB_SUCCESS;
- for (ulint h = 0; h < hash_get_n_cells(recv_sys->addr_hash); h++) {
+ for (ulint h = 0; h < hash_get_n_cells(recv_sys.addr_hash); h++) {
for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>(
- HASH_GET_FIRST(recv_sys->addr_hash, h));
+ HASH_GET_FIRST(recv_sys.addr_hash, h));
recv_addr != 0;
recv_addr = static_cast<recv_addr_t*>(
HASH_GET_NEXT(addr_hash, recv_addr))) {
@@ -3551,21 +3466,19 @@ recv_validate_tablespace(bool rescan, bool& missing_tablespace)
return(err);
}
- /* When rescan is not needed then recv_sys->addr_hash will have
- all space id belongs to redo log. If rescan is needed and
- innodb_force_recovery > 0 then InnoDB can ignore missing tablespace. */
- for (recv_spaces_t::iterator i = recv_spaces.begin();
- i != recv_spaces.end(); i++) {
-
- if (i->second.status != file_name_t::MISSING) {
+ /* When rescan is not needed, recv_sys.addr_hash will contain the
+ entire redo log. If rescan is needed or innodb_force_recovery
+ is set, we can ignore missing tablespaces. */
+ for (const recv_spaces_t::value_type& rs : recv_spaces) {
+ if (rs.second.status != file_name_t::MISSING) {
continue;
}
missing_tablespace = true;
if (srv_force_recovery > 0) {
- ib::warn() << "Tablespace " << i->first
- <<" was not found at " << i->second.name
+ ib::warn() << "Tablespace " << rs.first
+ <<" was not found at " << rs.second.name
<<", and innodb_force_recovery was set."
<<" All redo log for this tablespace"
<<" will be ignored!";
@@ -3573,9 +3486,9 @@ recv_validate_tablespace(bool rescan, bool& missing_tablespace)
}
if (!rescan) {
- ib::info() << "Tablespace " << i->first
+ ib::info() << "Tablespace " << rs.first
<< " was not found at '"
- << i->second.name << "', but there"
+ << rs.second.name << "', but there"
<<" were no modifications either.";
}
}
@@ -3600,33 +3513,34 @@ recv_init_crash_recovery_spaces(bool rescan, bool& missing_tablespace)
ut_ad(!srv_read_only_mode);
ut_ad(recv_needed_recovery);
- for (recv_spaces_t::iterator i = recv_spaces.begin();
- i != recv_spaces.end(); i++) {
- ut_ad(!is_predefined_tablespace(i->first));
- ut_ad(i->second.status != file_name_t::DELETED || !i->second.space);
+ for (recv_spaces_t::value_type& rs : recv_spaces) {
+ ut_ad(!is_predefined_tablespace(rs.first));
+ ut_ad(rs.second.status != file_name_t::DELETED
+ || !rs.second.space);
- if (i->second.status == file_name_t::DELETED) {
+ if (rs.second.status == file_name_t::DELETED) {
/* The tablespace was deleted,
so we can ignore any redo log for it. */
flag_deleted = true;
- } else if (i->second.space != NULL) {
+ } else if (rs.second.space != NULL) {
/* The tablespace was found, and there
are some redo log records for it. */
- fil_names_dirty(i->second.space);
- i->second.space->enable_lsn = i->second.enable_lsn;
- } else if (i->second.name == "") {
+ fil_names_dirty(rs.second.space);
+ rs.second.space->enable_lsn = rs.second.enable_lsn;
+ } else if (rs.second.name == "") {
ib::error() << "Missing MLOG_FILE_NAME"
" or MLOG_FILE_DELETE"
" before MLOG_CHECKPOINT for tablespace "
- << i->first;
- recv_sys->found_corrupt_log = true;
+ << rs.first;
+ recv_sys.found_corrupt_log = true;
return(DB_CORRUPTION);
} else {
- i->second.status = file_name_t::MISSING;
+ rs.second.status = file_name_t::MISSING;
flag_deleted = true;
}
- ut_ad(i->second.status == file_name_t::DELETED || i->second.name != "");
+ ut_ad(rs.second.status == file_name_t::DELETED
+ || rs.second.name != "");
}
if (flag_deleted) {
@@ -3675,7 +3589,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
if (err != DB_SUCCESS) {
- srv_start_lsn = recv_sys->recovered_lsn = log_sys.lsn;
+ srv_start_lsn = recv_sys.recovered_lsn = log_sys.lsn;
log_mutex_exit();
return(err);
}
@@ -3690,14 +3604,14 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
/* Start reading the log from the checkpoint lsn. The variable
contiguous_lsn contains an lsn up to which the log is known to
be contiguously written. */
- recv_sys->mlog_checkpoint_lsn = 0;
+ recv_sys.mlog_checkpoint_lsn = 0;
ut_ad(RECV_SCAN_SIZE <= srv_log_buffer_size);
const lsn_t end_lsn = mach_read_from_8(
buf + LOG_CHECKPOINT_END_LSN);
- ut_ad(recv_sys->n_addrs == 0);
+ ut_ad(recv_sys.n_addrs == 0);
contiguous_lsn = checkpoint_lsn;
switch (log_sys.log.format) {
case 0:
@@ -3712,7 +3626,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
contiguous_lsn = end_lsn;
break;
}
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
log_mutex_exit();
return(DB_ERROR);
}
@@ -3720,21 +3634,21 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
/* Look for MLOG_CHECKPOINT. */
recv_group_scan_log_recs(checkpoint_lsn, &contiguous_lsn, false);
/* The first scan should not have stored or applied any records. */
- ut_ad(recv_sys->n_addrs == 0);
- ut_ad(!recv_sys->found_corrupt_fs);
+ ut_ad(recv_sys.n_addrs == 0);
+ ut_ad(!recv_sys.found_corrupt_fs);
if (srv_read_only_mode && recv_needed_recovery) {
log_mutex_exit();
return(DB_READ_ONLY);
}
- if (recv_sys->found_corrupt_log && !srv_force_recovery) {
+ if (recv_sys.found_corrupt_log && !srv_force_recovery) {
log_mutex_exit();
ib::warn() << "Log scan aborted at LSN " << contiguous_lsn;
return(DB_ERROR);
}
- if (recv_sys->mlog_checkpoint_lsn == 0) {
+ if (recv_sys.mlog_checkpoint_lsn == 0) {
lsn_t scan_lsn = log_sys.log.scanned_lsn;
if (!srv_read_only_mode && scan_lsn != checkpoint_lsn) {
log_mutex_exit();
@@ -3755,8 +3669,8 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
rescan = recv_group_scan_log_recs(
checkpoint_lsn, &contiguous_lsn, false);
- if ((recv_sys->found_corrupt_log && !srv_force_recovery)
- || recv_sys->found_corrupt_fs) {
+ if ((recv_sys.found_corrupt_log && !srv_force_recovery)
+ || recv_sys.found_corrupt_fs) {
log_mutex_exit();
return(DB_ERROR);
}
@@ -3767,7 +3681,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
user about recovery: */
if (flush_lsn == checkpoint_lsn + SIZE_OF_MLOG_CHECKPOINT
- && recv_sys->mlog_checkpoint_lsn == checkpoint_lsn) {
+ && recv_sys.mlog_checkpoint_lsn == checkpoint_lsn) {
/* The redo log is logically empty. */
} else if (checkpoint_lsn != flush_lsn) {
ut_ad(!srv_log_files_created);
@@ -3799,7 +3713,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
}
}
- log_sys.lsn = recv_sys->recovered_lsn;
+ log_sys.lsn = recv_sys.recovered_lsn;
if (recv_needed_recovery) {
bool missing_tablespace = false;
@@ -3822,17 +3736,17 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
DBUG_PRINT("ib_log", ("Rescan of redo log to validate "
"the missing tablespace. Scan "
"from last stored LSN " LSN_PF,
- recv_sys->last_stored_lsn));
+ recv_sys.last_stored_lsn));
- lsn_t recent_stored_lsn = recv_sys->last_stored_lsn;
+ lsn_t recent_stored_lsn = recv_sys.last_stored_lsn;
rescan = recv_group_scan_log_recs(
checkpoint_lsn, &recent_stored_lsn, false);
- ut_ad(!recv_sys->found_corrupt_fs);
+ ut_ad(!recv_sys.found_corrupt_fs);
missing_tablespace = false;
- err = recv_sys->found_corrupt_log
+ err = recv_sys.found_corrupt_log
? DB_ERROR
: recv_validate_tablespace(
rescan, missing_tablespace);
@@ -3862,15 +3776,15 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
recv_group_scan_log_recs(
checkpoint_lsn, &contiguous_lsn, true);
- if ((recv_sys->found_corrupt_log
+ if ((recv_sys.found_corrupt_log
&& !srv_force_recovery)
- || recv_sys->found_corrupt_fs) {
+ || recv_sys.found_corrupt_fs) {
log_mutex_exit();
return(DB_ERROR);
}
}
} else {
- ut_ad(!rescan || recv_sys->n_addrs == 0);
+ ut_ad(!rescan || recv_sys.n_addrs == 0);
}
if (log_sys.log.scanned_lsn < checkpoint_lsn
@@ -3884,11 +3798,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
" database is now corrupt!";
}
- if (recv_sys->recovered_lsn < checkpoint_lsn) {
+ if (recv_sys.recovered_lsn < checkpoint_lsn) {
log_mutex_exit();
ib::error() << "Recovered only to lsn:"
- << recv_sys->recovered_lsn << " checkpoint_lsn: " << checkpoint_lsn;
+ << recv_sys.recovered_lsn << " checkpoint_lsn: " << checkpoint_lsn;
return(DB_ERROR);
}
@@ -3899,9 +3813,9 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
recv_synchronize_groups();
if (!recv_needed_recovery) {
- ut_a(checkpoint_lsn == recv_sys->recovered_lsn);
+ ut_a(checkpoint_lsn == recv_sys.recovered_lsn);
} else {
- srv_start_lsn = recv_sys->recovered_lsn;
+ srv_start_lsn = recv_sys.recovered_lsn;
}
log_sys.buf_free = ulong(log_sys.lsn % OS_FILE_LOG_BLOCK_SIZE);
@@ -3923,11 +3837,11 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
log_sys.next_checkpoint_no = ++checkpoint_no;
- mutex_enter(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
- recv_sys->apply_log_recs = TRUE;
+ recv_sys.apply_log_recs = true;
- mutex_exit(&recv_sys->mutex);
+ mutex_exit(&recv_sys.mutex);
log_mutex_exit();
@@ -3948,7 +3862,7 @@ recv_recovery_from_checkpoint_finish(void)
required because it grabs various mutexes and we want to
ensure that when we enable sync_order_checks there is no
mutex currently held by any thread. */
- mutex_enter(&recv_sys->writer_mutex);
+ mutex_enter(&recv_sys.writer_mutex);
/* Free the resources of the recovery system */
recv_recovery_on = false;
@@ -3958,7 +3872,7 @@ recv_recovery_from_checkpoint_finish(void)
in progress batches to finish. */
buf_flush_wait_LRU_batch_end();
- mutex_exit(&recv_sys->writer_mutex);
+ mutex_exit(&recv_sys.writer_mutex);
ulint count = 0;
while (recv_writer_thread_active) {
@@ -3971,7 +3885,7 @@ recv_recovery_from_checkpoint_finish(void)
}
}
- recv_sys_debug_free();
+ recv_sys.debug_free();
/* Free up the flush_rbt. */
buf_flush_free_flush_rbt();
@@ -4025,9 +3939,8 @@ recv_dblwr_t::find_page(ulint space_id, ulint page_no)
const byte *result= NULL;
lsn_t max_lsn= 0;
- for (list::const_iterator i = pages.begin(); i != pages.end(); ++i)
+ for (const byte *page : pages)
{
- const byte *page= *i;
if (page_get_page_no(page) != page_no ||
page_get_space_id(page) != space_id)
continue;
@@ -4209,6 +4122,12 @@ static const char* get_mlog_string(mlog_id_t type)
case MLOG_TRUNCATE:
return("MLOG_TRUNCATE");
+ case MLOG_MEMSET:
+ return("MLOG_MEMSET");
+
+ case MLOG_INIT_FREE_PAGE:
+ return("MLOG_INIT_FREE_PAGE");
+
case MLOG_FILE_WRITE_CRYPT_DATA:
return("MLOG_FILE_WRITE_CRYPT_DATA");
}
diff --git a/storage/innobase/mtr/mtr0log.cc b/storage/innobase/mtr/mtr0log.cc
index 714bd4435dc..da7088dd7d9 100644
--- a/storage/innobase/mtr/mtr0log.cc
+++ b/storage/innobase/mtr/mtr0log.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 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
@@ -100,7 +100,7 @@ mlog_parse_initial_log_record(
*type = mlog_id_t(*ptr & ~MLOG_SINGLE_REC_FLAG);
if (UNIV_UNLIKELY(*type > MLOG_BIGGEST_TYPE
&& !EXTRA_CHECK_MLOG_NUMBER(*type))) {
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
return NULL;
}
@@ -121,7 +121,7 @@ mlog_parse_initial_log_record(
}
/********************************************************//**
-Parses a log record written by mlog_write_ulint or mlog_write_ull.
+Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset.
@return parsed record end, NULL if not a complete record or a corrupt record */
byte*
mlog_parse_nbytes(
@@ -137,29 +137,46 @@ mlog_parse_nbytes(
ulint val;
ib_uint64_t dval;
- ut_a(type <= MLOG_8BYTES);
+ ut_ad(type <= MLOG_8BYTES || type == MLOG_MEMSET);
ut_a(!page || !page_zip
+ || type == MLOG_MEMSET
|| !fil_page_index_page_check(page));
if (end_ptr < ptr + 2) {
-
- return(NULL);
+ return NULL;
}
offset = mach_read_from_2(ptr);
ptr += 2;
- if (offset >= srv_page_size) {
- recv_sys->found_corrupt_log = TRUE;
-
- return(NULL);
+ if (UNIV_UNLIKELY(offset >= srv_page_size)) {
+ goto corrupt;
}
- if (type == MLOG_8BYTES) {
+ switch (type) {
+ case MLOG_MEMSET:
+ if (end_ptr < ptr + 3) {
+ return NULL;
+ }
+ val = mach_read_from_2(ptr);
+ ptr += 2;
+ if (UNIV_UNLIKELY(offset + val > srv_page_size)) {
+ goto corrupt;
+ }
+ if (page) {
+ memset(page + offset, *ptr, val);
+ if (page_zip) {
+ ut_ad(offset + val <= PAGE_DATA
+ || !fil_page_index_page_check(page));
+ memset(static_cast<page_zip_des_t*>(page_zip)
+ ->data + offset, *ptr, val);
+ }
+ }
+ return const_cast<byte*>(++ptr);
+ case MLOG_8BYTES:
dval = mach_u64_parse_compressed(&ptr, end_ptr);
if (ptr == NULL) {
-
- return(NULL);
+ return NULL;
}
if (page) {
@@ -171,14 +188,13 @@ mlog_parse_nbytes(
mach_write_to_8(page + offset, dval);
}
- return(const_cast<byte*>(ptr));
+ return const_cast<byte*>(ptr);
+ default:
+ val = mach_parse_compressed(&ptr, end_ptr);
}
- val = mach_parse_compressed(&ptr, end_ptr);
-
if (ptr == NULL) {
-
- return(NULL);
+ return NULL;
}
switch (type) {
@@ -221,11 +237,11 @@ mlog_parse_nbytes(
break;
default:
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = true;
ptr = NULL;
}
- return(const_cast<byte*>(ptr));
+ return const_cast<byte*>(ptr);
}
/********************************************************//**
@@ -388,7 +404,7 @@ mlog_parse_string(
ptr += 2;
if (offset >= srv_page_size || len + offset > srv_page_size) {
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -409,6 +425,72 @@ mlog_parse_string(
return(ptr + len);
}
+/** Initialize a string of bytes.
+@param[in,out] b buffer page
+@param[in] ofs byte offset from block->frame
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void
+mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr)
+{
+ ut_ad(len);
+ ut_ad(ofs <= ulint(srv_page_size));
+ ut_ad(ofs + len <= ulint(srv_page_size));
+ memset(ofs + b->frame, val, len);
+
+ mtr->set_modified();
+ switch (mtr->get_log_mode()) {
+ case MTR_LOG_NONE:
+ case MTR_LOG_NO_REDO:
+ return;
+ case MTR_LOG_SHORT_INSERTS:
+ ut_ad(0);
+ /* fall through */
+ case MTR_LOG_ALL:
+ break;
+ }
+
+ byte* l = mtr->get_log()->open(11 + 2 + 2 + 1);
+ l = mlog_write_initial_log_record_low(
+ MLOG_MEMSET, b->page.id.space(), b->page.id.page_no(), l, mtr);
+ mach_write_to_2(l, ofs);
+ mach_write_to_2(l + 2, len);
+ l[4] = val;
+ mlog_close(mtr, l + 5);
+}
+
+/** Initialize a string of bytes.
+@param[in,out] byte byte address
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr)
+{
+ ut_ad(len);
+ ut_ad(page_offset(b) + len <= ulint(srv_page_size));
+ memset(b, val, len);
+
+ mtr->set_modified();
+ switch (mtr->get_log_mode()) {
+ case MTR_LOG_NONE:
+ case MTR_LOG_NO_REDO:
+ return;
+ case MTR_LOG_SHORT_INSERTS:
+ ut_ad(0);
+ /* fall through */
+ case MTR_LOG_ALL:
+ break;
+ }
+
+ byte* l = mtr->get_log()->open(11 + 2 + 2 + 1);
+ l = mlog_write_initial_log_record_fast(b, MLOG_MEMSET, l, mtr);
+ mach_write_to_2(l, page_offset(b));
+ mach_write_to_2(l + 2, len);
+ l[4] = val;
+ mlog_close(mtr, l + 5);
+}
+
/********************************************************//**
Opens a buffer for mlog, writes the initial log record and,
if needed, the field lengths of an index.
@@ -562,7 +644,7 @@ mlog_parse_index(
n_core_fields = mach_read_from_2(ptr);
if (!n_core_fields || n_core_fields > n) {
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 14c274b5b40..9918d0bbc21 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -28,9 +28,9 @@ Created 11/26/1995 Heikki Tuuri
#include "buf0buf.h"
#include "buf0flu.h"
+#include "fsp0sysspace.h"
#include "page0types.h"
#include "mtr0log.h"
-#include "row0trunc.h"
#include "log0recv.h"
/** Iterate over a memo block in reverse. */
@@ -167,7 +167,7 @@ struct FindPage
slot->object);
if (m_ptr < block->frame
- || m_ptr >= block->frame + block->page.size.logical()) {
+ || m_ptr >= block->frame + srv_page_size) {
return(true);
}
@@ -226,7 +226,7 @@ static void memo_slot_release(mtr_memo_slot_t *slot)
case MTR_MEMO_PAGE_SX_FIX:
case MTR_MEMO_PAGE_X_FIX:
buf_block_t *block= reinterpret_cast<buf_block_t*>(slot->object);
- buf_block_unfix(block);
+ block->unfix();
buf_page_release_latch(block, slot->type);
break;
}
@@ -262,7 +262,7 @@ struct ReleaseLatches {
case MTR_MEMO_PAGE_SX_FIX:
case MTR_MEMO_PAGE_X_FIX:
buf_block_t *block= reinterpret_cast<buf_block_t*>(slot->object);
- buf_block_unfix(block);
+ block->unfix();
buf_page_release_latch(block, slot->type);
break;
}
@@ -564,8 +564,7 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line)
ut_ad(get_log_mode() != MTR_LOG_NO_REDO
|| space->purpose == FIL_TYPE_TEMPORARY
|| space->purpose == FIL_TYPE_IMPORT
- || my_atomic_loadlint(&space->redo_skipped_count) > 0
- || srv_is_tablespace_truncated(space->id));
+ || space->redo_skipped_count > 0);
}
ut_ad(space);
diff --git a/storage/innobase/os/os0event.cc b/storage/innobase/os/os0event.cc
index f1d7b2ed337..0676ba5f6c1 100644
--- a/storage/innobase/os/os0event.cc
+++ b/storage/innobase/os/os0event.cc
@@ -218,7 +218,7 @@ private:
int64_t signal_count; /*!< this is incremented
each time the event becomes
signaled */
- mutable EventMutex mutex; /*!< this mutex protects
+ mutable OSMutex mutex; /*!< this mutex protects
the next fields */
diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc
index 2031dcb1ef3..062a2bed8ac 100644
--- a/storage/innobase/os/os0file.cc
+++ b/storage/innobase/os/os0file.cc
@@ -38,14 +38,14 @@ Created 10/21/1995 Heikki Tuuri
#include "sql_const.h"
#ifdef UNIV_LINUX
-#include <sys/types.h>
-#include <sys/stat.h>
+# include <sys/types.h>
+# include <sys/stat.h>
#endif
#include "srv0srv.h"
#include "srv0start.h"
#include "fil0fil.h"
-#include "srv0srv.h"
+#include "fsp0fsp.h"
#ifdef HAVE_LINUX_UNISTD_H
#include "unistd.h"
#endif
@@ -70,18 +70,14 @@ Created 10/21/1995 Heikki Tuuri
# endif
#endif
-#if defined(UNIV_LINUX) && defined(HAVE_SYS_STATVFS_H)
-#include <sys/statvfs.h>
-#endif
-
-#if defined(UNIV_LINUX) && defined(HAVE_LINUX_FALLOC_H)
-#include <linux/falloc.h>
-#endif
-
#ifdef _WIN32
#include <winioctl.h>
+#else
+// my_test_if_atomic_write()
+#include <my_sys.h>
#endif
+
/** Insert buffer segment id */
static const ulint IO_IBUF_SEGMENT = 0;
@@ -821,108 +817,6 @@ os_win32_device_io_control(
#endif
-/***********************************************************************//**
-Try to get number of bytes per sector from file system.
-@return file block size */
-UNIV_INTERN
-ulint
-os_file_get_block_size(
-/*===================*/
- os_file_t file, /*!< in: handle to a file */
- const char* name) /*!< in: file name */
-{
- ulint fblock_size = 512;
-
-#if defined(UNIV_LINUX)
- struct stat local_stat;
- int err;
-
- err = fstat((int)file, &local_stat);
-
- if (err != 0) {
- os_file_handle_error_no_exit(name, "fstat()", FALSE);
- } else {
- fblock_size = local_stat.st_blksize;
- }
-#endif /* UNIV_LINUX */
-#ifdef _WIN32
-
- fblock_size = 0;
- BOOL result = false;
- size_t len = 0;
- // Open volume for this file, find out it "physical bytes per sector"
-
- HANDLE volume_handle = INVALID_HANDLE_VALUE;
- char volume[MAX_PATH + 4]="\\\\.\\"; // Special prefix required for volume names.
- if (!GetVolumePathName(name , volume + 4, MAX_PATH)) {
- os_file_handle_error_no_exit(name,
- "GetVolumePathName()", FALSE);
- goto end;
- }
-
- len = strlen(volume);
- if (volume[len - 1] == '\\') {
- // Trim trailing backslash from volume name.
- volume[len - 1] = 0;
- }
-
- volume_handle = CreateFile(volume, FILE_READ_ATTRIBUTES,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- 0, OPEN_EXISTING, 0, 0);
-
- if (volume_handle == INVALID_HANDLE_VALUE) {
- if (GetLastError() != ERROR_ACCESS_DENIED) {
- os_file_handle_error_no_exit(volume,
- "CreateFile()", FALSE);
- }
- goto end;
- }
-
- DWORD tmp;
- STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR disk_alignment;
-
- STORAGE_PROPERTY_QUERY storage_query;
- memset(&storage_query, 0, sizeof(storage_query));
- storage_query.PropertyId = StorageAccessAlignmentProperty;
- storage_query.QueryType = PropertyStandardQuery;
-
- result = os_win32_device_io_control(volume_handle,
- IOCTL_STORAGE_QUERY_PROPERTY,
- &storage_query,
- sizeof(storage_query),
- &disk_alignment,
- sizeof(disk_alignment),
- &tmp);
-
- if (!result) {
- DWORD err = GetLastError();
- if (err != ERROR_INVALID_FUNCTION && err != ERROR_NOT_SUPPORTED) {
- os_file_handle_error_no_exit(volume,
- "DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY)", FALSE);
- }
- goto end;
- }
-
- fblock_size = disk_alignment.BytesPerPhysicalSector;
-
-end:
- if (volume_handle != INVALID_HANDLE_VALUE) {
- CloseHandle(volume_handle);
- }
-#endif /* _WIN32 */
-
- /* Currently we support file block size up to 4Kb */
- if (fblock_size > 4096 || fblock_size < 512) {
- if (fblock_size < 512) {
- fblock_size = 512;
- } else {
- fblock_size = 4096;
- }
- }
-
- return fblock_size;
-}
-
#ifdef WIN_ASYNC_IO
/** This function is only used in Windows asynchronous i/o.
Waits for an aio operation to complete. This function is used to wait the
@@ -1084,15 +978,8 @@ os_aio_validate_skip()
/** Try os_aio_validate() every this many times */
# define OS_AIO_VALIDATE_SKIP 13
- static int os_aio_validate_count;
-
- if (my_atomic_add32_explicit(&os_aio_validate_count, -1,
- MY_MEMORY_ORDER_RELAXED)
- % OS_AIO_VALIDATE_SKIP) {
- return true;
- }
-
- return(os_aio_validate());
+ static Atomic_counter<uint32_t> os_aio_validate_count;
+ return (os_aio_validate_count++ % OS_AIO_VALIDATE_SKIP) || os_aio_validate();
}
#endif /* UNIV_DEBUG */
@@ -3563,8 +3450,6 @@ static WinIoInit win_io_init;
/** Free storage space associated with a section of the file.
@param[in] fh Open file handle
-@param[in] page_size Tablespace page size
-@param[in] block_size File system block size
@param[in] off Starting offset (SEEK_SET)
@param[in] len Size of the hole
@return 0 on success or errno */
@@ -5322,6 +5207,34 @@ short_warning:
#endif /* _WIN32 */
+/** Check if the file system supports sparse files.
+@param fh file handle
+@return true if the file system supports sparse files */
+IF_WIN(static,) bool os_is_sparse_file_supported(os_file_t fh)
+{
+ /* In this debugging mode, we act as if punch hole is supported,
+ then we skip any calls to actually punch a hole. In this way,
+ Transparent Page Compression is still being tested. */
+ DBUG_EXECUTE_IF("ignore_punch_hole",
+ return(true);
+ );
+
+#ifdef _WIN32
+ FILE_ATTRIBUTE_TAG_INFO info;
+ if (GetFileInformationByHandleEx(fh, FileAttributeTagInfo,
+ &info, (DWORD)sizeof(info))) {
+ if (info.FileAttributes != INVALID_FILE_ATTRIBUTES) {
+ return (info.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0;
+ }
+ }
+ return false;
+#else
+ /* We don't know the FS block size, use the sector size. The FS
+ will do the magic. */
+ return DB_SUCCESS == os_file_punch_hole_posix(fh, 0, srv_page_size);
+#endif /* _WIN32 */
+}
+
/** Extend a file.
On Windows, extending a file allocates blocks for the file,
@@ -5550,15 +5463,16 @@ os_file_punch_hole(
os_offset_t off,
os_offset_t len)
{
- dberr_t err;
-
#ifdef _WIN32
- err = os_file_punch_hole_win32(fh, off, len);
+ return os_file_punch_hole_win32(fh, off, len);
#else
- err = os_file_punch_hole_posix(fh, off, len);
+ return os_file_punch_hole_posix(fh, off, len);
#endif /* _WIN32 */
+}
- return (err);
+inline bool IORequest::should_punch_hole() const
+{
+ return m_fil_node && m_fil_node->space->punch_hole;
}
/** Free storage space associated with a section of the file.
@@ -5598,7 +5512,9 @@ IORequest::punch_hole(os_file_t fh, os_offset_t off, ulint len)
/* If punch hole is not supported,
set space so that it is not used. */
if (err == DB_IO_NO_PUNCH_HOLE) {
- space_no_punch_hole();
+ if (m_fil_node) {
+ m_fil_node->space->punch_hole = false;
+ }
err = DB_SUCCESS;
}
}
@@ -5606,43 +5522,6 @@ IORequest::punch_hole(os_file_t fh, os_offset_t off, ulint len)
return (err);
}
-/** Check if the file system supports sparse files.
-
-Warning: On POSIX systems we try and punch a hole from offset 0 to
-the system configured page size. This should only be called on an empty
-file.
-@param[in] fh File handle for the file - if opened
-@return true if the file system supports sparse files */
-bool
-os_is_sparse_file_supported(os_file_t fh)
-{
- /* In this debugging mode, we act as if punch hole is supported,
- then we skip any calls to actually punch a hole. In this way,
- Transparent Page Compression is still being tested. */
- DBUG_EXECUTE_IF("ignore_punch_hole",
- return(true);
- );
-
-#ifdef _WIN32
- FILE_ATTRIBUTE_TAG_INFO info;
- if (GetFileInformationByHandleEx(fh, FileAttributeTagInfo,
- &info, (DWORD)sizeof(info))) {
- if (info.FileAttributes != INVALID_FILE_ATTRIBUTES) {
- return (info.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) != 0;
- }
- }
- return false;
-#else
- dberr_t err;
-
- /* We don't know the FS block size, use the sector size. The FS
- will do the magic. */
- err = os_file_punch_hole_posix(fh, 0, srv_page_size);
-
- return(err == DB_SUCCESS);
-#endif /* _WIN32 */
-}
-
/** This function returns information about the specified file
@param[in] path pathname of the file
@param[out] stat_info information of a file in a directory
@@ -7673,6 +7552,310 @@ os_file_set_umask(ulint umask)
os_innodb_umask = umask;
}
+#ifdef _WIN32
+static int win32_get_block_size(HANDLE volume_handle, const char *volume_name)
+{
+ STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR disk_alignment;
+ STORAGE_PROPERTY_QUERY storage_query;
+ DWORD tmp;
+
+ memset(&storage_query, 0, sizeof(storage_query));
+ storage_query.PropertyId = StorageAccessAlignmentProperty;
+ storage_query.QueryType = PropertyStandardQuery;
+
+ if (os_win32_device_io_control(volume_handle,
+ IOCTL_STORAGE_QUERY_PROPERTY,
+ &storage_query,
+ sizeof storage_query,
+ &disk_alignment,
+ sizeof disk_alignment,
+ &tmp) && tmp == sizeof disk_alignment) {
+ return disk_alignment.BytesPerPhysicalSector;
+ }
+
+ switch (GetLastError()) {
+ case ERROR_INVALID_FUNCTION:
+ case ERROR_NOT_SUPPORTED:
+ break;
+ default:
+ os_file_handle_error_no_exit(
+ volume_name,
+ "DeviceIoControl(IOCTL_STORAGE_QUERY_PROPERTY / StorageAccessAlignmentProperty)",
+ FALSE);
+ }
+ return 512;
+}
+
+static bool win32_is_ssd(HANDLE volume_handle)
+{
+ DWORD tmp;
+ DEVICE_SEEK_PENALTY_DESCRIPTOR seek_penalty;
+ STORAGE_PROPERTY_QUERY storage_query;
+ memset(&storage_query, 0, sizeof(storage_query));
+
+ storage_query.PropertyId = StorageDeviceSeekPenaltyProperty;
+ storage_query.QueryType = PropertyStandardQuery;
+
+ if (os_win32_device_io_control(volume_handle,
+ IOCTL_STORAGE_QUERY_PROPERTY,
+ &storage_query,
+ sizeof storage_query,
+ &seek_penalty,
+ sizeof seek_penalty,
+ &tmp) && tmp == sizeof(seek_penalty)){
+ return !seek_penalty.IncursSeekPenalty;
+ }
+
+ DEVICE_TRIM_DESCRIPTOR trim;
+ storage_query.PropertyId = StorageDeviceTrimProperty;
+ if (os_win32_device_io_control(volume_handle,
+ IOCTL_STORAGE_QUERY_PROPERTY,
+ &storage_query,
+ sizeof storage_query,
+ &trim,
+ sizeof trim,
+ &tmp) && tmp == sizeof trim) {
+ return trim.TrimEnabled;
+ }
+ return false;
+}
+#endif
+
+/** Determine some file metadata when creating or reading the file.
+@param file the file that is being created, or OS_FILE_CLOSED */
+void fil_node_t::find_metadata(os_file_t file
+#ifdef UNIV_LINUX
+ , struct stat* statbuf
+#endif
+ )
+{
+ if (file == OS_FILE_CLOSED) {
+ file = handle;
+ ut_ad(is_open());
+ }
+
+#ifdef _WIN32 /* FIXME: make this unconditional */
+ if (space->punch_hole) {
+ space->punch_hole = os_is_sparse_file_supported(file);
+ }
+#endif
+
+ /*
+ For the temporary tablespace and during the
+ non-redo-logged adjustments in
+ IMPORT TABLESPACE, we do not care about
+ the atomicity of writes.
+
+ Atomic writes is supported if the file can be used
+ with atomic_writes (not log file), O_DIRECT is
+ used (tested in ha_innodb.cc) and the file is
+ device and file system that supports atomic writes
+ for the given block size.
+ */
+ space->atomic_write_supported = space->purpose == FIL_TYPE_TEMPORARY
+ || space->purpose == FIL_TYPE_IMPORT;
+#ifdef _WIN32
+ block_size = 512;
+ on_ssd = false;
+ // Open volume for this file, find out it "physical bytes per sector"
+ char volume[MAX_PATH + 4];
+ if (!GetVolumePathName(name, volume + 4, MAX_PATH)) {
+ os_file_handle_error_no_exit(name,
+ "GetVolumePathName()", FALSE);
+ return;
+ }
+ // Special prefix required for volume names.
+ memcpy(volume, "\\\\.\\", 4);
+
+ size_t len = strlen(volume);
+ if (volume[len - 1] == '\\') {
+ // Trim trailing backslash from volume name.
+ volume[len - 1] = 0;
+ }
+
+ HANDLE volume_handle = CreateFile(volume, FILE_READ_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0, OPEN_EXISTING, 0, 0);
+
+ if (volume_handle != INVALID_HANDLE_VALUE) {
+ block_size = win32_get_block_size(volume_handle, volume);
+ on_ssd = win32_is_ssd(volume_handle);
+ CloseHandle(volume_handle);
+ } else {
+ /*
+ Report error, unless it is expected, e.g
+ missing permissions, or error when trying to
+ open volume for UNC share.
+ */
+ if (GetLastError() != ERROR_ACCESS_DENIED
+ && GetDriveType(volume) == DRIVE_FIXED) {
+ os_file_handle_error_no_exit(volume, "CreateFile()", FALSE);
+ }
+ }
+
+ /* Currently we support file block size up to 4KiB */
+ if (block_size > 4096) {
+ block_size = 4096;
+ } else if (block_size < 512) {
+ block_size = 512;
+ }
+#else
+ on_ssd = space->atomic_write_supported;
+# ifdef UNIV_LINUX
+ if (!on_ssd) {
+ struct stat sbuf;
+ if (!statbuf && !fstat(file, &sbuf)) {
+ statbuf = &sbuf;
+ }
+ if (statbuf && fil_system.is_ssd(statbuf->st_dev)) {
+ on_ssd = true;
+ }
+ }
+# endif
+#endif
+ if (!space->atomic_write_supported) {
+ space->atomic_write_supported = atomic_write
+ && srv_use_atomic_writes
+#ifndef _WIN32
+ && my_test_if_atomic_write(file,
+ space->physical_size())
+#else
+ /* On Windows, all single sector writes are atomic,
+ as per WriteFile() documentation on MSDN.
+ We also require SSD for atomic writes, eventhough
+ technically it is not necessary- the reason is that
+ on hard disks, we still want the benefit from
+ (non-atomic) neighbor page flushing in the buffer
+ pool code. */
+ && srv_page_size == block_size
+ && on_ssd
+#endif
+ ;
+ }
+}
+
+/** Read the first page of a data file.
+@param[in] first whether this is the very first read
+@return whether the page was found valid */
+bool fil_node_t::read_page0(bool first)
+{
+ ut_ad(mutex_own(&fil_system.mutex));
+ ut_a(space->purpose != FIL_TYPE_LOG);
+ const ulint psize = space->physical_size();
+#ifndef _WIN32
+ struct stat statbuf;
+ if (fstat(handle, &statbuf)) {
+ return false;
+ }
+ block_size = statbuf.st_blksize;
+ os_offset_t size_bytes = statbuf.st_size;
+#else
+ os_offset_t size_bytes = os_file_get_size(handle);
+ ut_a(size_bytes != (os_offset_t) -1);
+#endif
+ const ulint min_size = FIL_IBD_FILE_INITIAL_SIZE * psize;
+
+ if (size_bytes < min_size) {
+ ib::error() << "The size of the file " << name
+ << " is only " << size_bytes
+ << " bytes, should be at least " << min_size;
+ return false;
+ }
+
+ byte* buf2 = static_cast<byte*>(ut_malloc_nokey(2 * psize));
+
+ /* Align the memory for file i/o if we might have O_DIRECT set */
+ byte* page = static_cast<byte*>(ut_align(buf2, psize));
+ IORequest request(IORequest::READ);
+ if (os_file_read(request, handle, page, 0, psize) != DB_SUCCESS) {
+ ib::error() << "Unable to read first page of file " << name;
+ ut_free(buf2);
+ return false;
+ }
+ const ulint space_id = fsp_header_get_space_id(page);
+ ulint flags = fsp_header_get_flags(page);
+ const ulint size = fsp_header_get_field(page, FSP_SIZE);
+ const ulint free_limit = fsp_header_get_field(page, FSP_FREE_LIMIT);
+ const ulint free_len = flst_get_len(FSP_HEADER_OFFSET + FSP_FREE
+ + page);
+ if (!fil_space_t::is_valid_flags(flags, space->id)) {
+ ulint cflags = fsp_flags_convert_from_101(flags);
+ if (cflags == ULINT_UNDEFINED) {
+invalid:
+ ib::error()
+ << "Expected tablespace flags "
+ << ib::hex(space->flags)
+ << " but found " << ib::hex(flags)
+ << " in the file " << name;
+ ut_free(buf2);
+ return false;
+ }
+
+ ulint cf = cflags & ~FSP_FLAGS_MEM_MASK;
+ ulint sf = space->flags & ~FSP_FLAGS_MEM_MASK;
+
+ if (!fil_space_t::is_flags_equal(cf, sf)
+ && !fil_space_t::is_flags_equal(sf, cf)) {
+ goto invalid;
+ }
+
+ flags = cflags;
+ }
+
+ ut_ad(!(flags & FSP_FLAGS_MEM_MASK));
+
+ /* Try to read crypt_data from page 0 if it is not yet read. */
+ if (!space->crypt_data) {
+ space->crypt_data = fil_space_read_crypt_data(
+ fil_space_t::zip_size(flags), page);
+ }
+ ut_free(buf2);
+
+ if (UNIV_UNLIKELY(space_id != space->id)) {
+ ib::error() << "Expected tablespace id " << space->id
+ << " but found " << space_id
+ << " in the file " << name;
+ return false;
+ }
+
+ if (first) {
+ ut_ad(space->id != TRX_SYS_SPACE);
+#ifdef UNIV_LINUX
+ find_metadata(handle, &statbuf);
+#else
+ find_metadata();
+#endif
+
+ /* Truncate the size to a multiple of extent size. */
+ ulint mask = psize * FSP_EXTENT_SIZE - 1;
+
+ if (size_bytes <= mask) {
+ /* .ibd files start smaller than an
+ extent size. Do not truncate valid data. */
+ } else {
+ size_bytes &= ~os_offset_t(mask);
+ }
+
+ space->flags = (space->flags & FSP_FLAGS_MEM_MASK) | flags;
+
+ this->size = ulint(size_bytes / psize);
+ space->size += this->size;
+ } else if (space->id != TRX_SYS_SPACE || space->size_in_header) {
+ /* If this is not the first-time open, do nothing.
+ For the system tablespace, we always get invoked as
+ first=false, so we detect the true first-time-open based
+ on size_in_header and proceed to initiailze the data. */
+ return true;
+ }
+
+ ut_ad(space->free_limit == 0 || space->free_limit == free_limit);
+ ut_ad(space->free_len == 0 || space->free_len == free_len);
+ space->size_in_header = size;
+ space->free_limit = free_limit;
+ space->free_len = free_len;
+ return true;
+}
+
#else
#include "univ.i"
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/os/os0proc.cc b/storage/innobase/os/os0proc.cc
index 60057880c18..32067297a24 100644
--- a/storage/innobase/os/os0proc.cc
+++ b/storage/innobase/os/os0proc.cc
@@ -40,7 +40,7 @@ MAP_ANON but MAP_ANON is marked as deprecated */
/** The total amount of memory currently allocated from the operating
system with os_mem_alloc_large(). */
-ulint os_total_large_mem_allocated = 0;
+Atomic_counter<ulint> os_total_large_mem_allocated;
/** Converts the current process id to a number.
@return process id as a number */
@@ -98,9 +98,7 @@ os_mem_alloc_large(
if (ptr) {
*n = size;
- my_atomic_addlint(
- &os_total_large_mem_allocated, size);
-
+ os_total_large_mem_allocated += size;
UNIV_MEM_ALLOC(ptr, size);
return(ptr);
}
@@ -123,8 +121,7 @@ skip:
ib::info() << "VirtualAlloc(" << size << " bytes) failed;"
" Windows error " << GetLastError();
} else {
- my_atomic_addlint(
- &os_total_large_mem_allocated, size);
+ os_total_large_mem_allocated += size;
UNIV_MEM_ALLOC(ptr, size);
}
#else
@@ -139,8 +136,7 @@ skip:
" errno " << errno;
ptr = NULL;
} else {
- my_atomic_addlint(
- &os_total_large_mem_allocated, size);
+ os_total_large_mem_allocated += size;
UNIV_MEM_ALLOC(ptr, size);
}
#endif
@@ -165,8 +161,7 @@ os_mem_free_large(
#ifdef HAVE_LINUX_LARGE_PAGES
if (my_use_large_pages && opt_large_page_size && !shmdt(ptr)) {
- my_atomic_addlint(
- &os_total_large_mem_allocated, -size);
+ os_total_large_mem_allocated -= size;
return;
}
#endif /* HAVE_LINUX_LARGE_PAGES */
@@ -177,8 +172,7 @@ os_mem_free_large(
ib::error() << "VirtualFree(" << ptr << ", " << size
<< ") failed; Windows error " << GetLastError();
} else {
- my_atomic_addlint(
- &os_total_large_mem_allocated, -lint(size));
+ os_total_large_mem_allocated -= size;
}
#elif !defined OS_MAP_ANON
ut_free(ptr);
@@ -191,8 +185,7 @@ os_mem_free_large(
ib::error() << "munmap(" << ptr << ", " << size << ") failed;"
" errno " << errno;
} else {
- my_atomic_addlint(
- &os_total_large_mem_allocated, -size);
+ os_total_large_mem_allocated -= size;
}
#endif
}
diff --git a/storage/innobase/os/os0thread.cc b/storage/innobase/os/os0thread.cc
index 0c97ebccc1b..bb5da7df7c4 100644
--- a/storage/innobase/os/os0thread.cc
+++ b/storage/innobase/os/os0thread.cc
@@ -28,7 +28,7 @@ Created 9/8/1995 Heikki Tuuri
#include "srv0srv.h"
/** Number of threads active. */
-ulint os_thread_count;
+Atomic_counter<ulint> os_thread_count;
/***************************************************************//**
Compares two thread ids for equality.
@@ -118,7 +118,7 @@ os_thread_create_func(
CloseHandle(handle);
- my_atomic_addlint(&os_thread_count, 1);
+ os_thread_count++;
return((os_thread_t)new_thread_id);
#else /* _WIN32 else */
@@ -133,7 +133,7 @@ os_thread_create_func(
abort();
}
- my_atomic_addlint(&os_thread_count, 1);
+ os_thread_count++;
ret = pthread_create(&new_thread_id, &attr, func, arg);
@@ -188,7 +188,7 @@ os_thread_exit(bool detach)
pfs_delete_thread();
#endif
- my_atomic_addlint(&os_thread_count, ulint(-1));
+ os_thread_count--;
#ifdef _WIN32
ExitThread(0);
diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc
index 16f0495527d..4bc9d1eb094 100644
--- a/storage/innobase/page/page0cur.cc
+++ b/storage/innobase/page/page0cur.cc
@@ -701,7 +701,7 @@ up_slot_match:
& REC_INFO_MIN_REC_FLAG)) {
ut_ad(!page_has_prev(page_align(mid_rec)));
ut_ad(!page_rec_is_leaf(mid_rec)
- || rec_is_metadata(mid_rec, index));
+ || rec_is_metadata(mid_rec, *index));
cmp = 1;
goto low_rec_match;
}
@@ -1026,7 +1026,7 @@ page_cur_parse_insert_rec(
if (offset >= srv_page_size) {
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -1040,7 +1040,7 @@ page_cur_parse_insert_rec(
}
if (end_seg_len >= srv_page_size << 1) {
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -1330,7 +1330,7 @@ use_heap:
switch (rec_get_status(current_rec)) {
case REC_STATUS_ORDINARY:
case REC_STATUS_NODE_PTR:
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
case REC_STATUS_INFIMUM:
break;
case REC_STATUS_SUPREMUM:
@@ -1339,7 +1339,7 @@ use_heap:
switch (rec_get_status(insert_rec)) {
case REC_STATUS_ORDINARY:
case REC_STATUS_NODE_PTR:
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
break;
case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM:
@@ -1526,7 +1526,7 @@ page_cur_insert_rec_zip(
get rid of the modification log. */
page_create_zip(page_cur_get_block(cursor), index,
page_header_get_field(page, PAGE_LEVEL),
- 0, NULL, mtr);
+ 0, mtr);
ut_ad(!page_header_get_ptr(page, PAGE_FREE));
if (page_zip_available(
@@ -1601,7 +1601,7 @@ page_cur_insert_rec_zip(
if (!log_compressed) {
if (page_zip_compress(
page_zip, page, index,
- level, NULL, NULL)) {
+ level, NULL)) {
page_cur_insert_rec_write_log(
insert_rec, rec_size,
cursor->rec, index, mtr);
@@ -1747,17 +1747,11 @@ too_small:
columns of free_rec, in case it will not be
overwritten by insert_rec. */
- ulint trx_id_col;
ulint trx_id_offs;
ulint len;
- trx_id_col = dict_index_get_sys_col_pos(index,
- DATA_TRX_ID);
- ut_ad(trx_id_col > 0);
- ut_ad(trx_id_col != ULINT_UNDEFINED);
-
- trx_id_offs = rec_get_nth_field_offs(foffsets,
- trx_id_col, &len);
+ trx_id_offs = rec_get_nth_field_offs(
+ foffsets, index->db_trx_id(), &len);
ut_ad(len == DATA_TRX_ID_LEN);
if (DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN + trx_id_offs
@@ -1773,7 +1767,7 @@ too_small:
ut_ad(free_rec + trx_id_offs + DATA_TRX_ID_LEN
== rec_get_nth_field(free_rec, foffsets,
- trx_id_col + 1, &len));
+ index->db_roll_ptr(), &len));
ut_ad(len == DATA_ROLL_PTR_LEN);
}
@@ -2223,7 +2217,7 @@ page_cur_parse_delete_rec(
ptr += 2;
if (UNIV_UNLIKELY(offset >= srv_page_size)) {
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
return NULL;
}
@@ -2297,7 +2291,8 @@ page_cur_delete_rec(
/* The record must not be the supremum or infimum record. */
ut_ad(page_rec_is_user_rec(current_rec));
- if (page_get_n_recs(page) == 1 && !recv_recovery_is_on()) {
+ if (page_get_n_recs(page) == 1 && !recv_recovery_is_on()
+ && !rec_is_alter_metadata(current_rec, *index)) {
/* Empty the page, unless we are applying the redo log
during crash recovery. During normal operation, the
page_create_empty() gets logged as one of MLOG_PAGE_CREATE,
diff --git a/storage/innobase/page/page0page.cc b/storage/innobase/page/page0page.cc
index a916effa9b8..28a7d506975 100644
--- a/storage/innobase/page/page0page.cc
+++ b/storage/innobase/page/page0page.cc
@@ -29,8 +29,8 @@ Created 2/2/1994 Heikki Tuuri
#include "page0cur.h"
#include "page0zip.h"
#include "buf0buf.h"
+#include "buf0checksum.h"
#include "btr0btr.h"
-#include "row0trunc.h"
#include "srv0srv.h"
#include "lock0lock.h"
#include "fut0lst.h"
@@ -449,28 +449,19 @@ page_create_zip(
buf_block_t* block, /*!< in/out: a buffer frame
where the page is created */
dict_index_t* index, /*!< in: the index of the
- page, or NULL when applying
- TRUNCATE log
- record during recovery */
+ page */
ulint level, /*!< in: the B-tree level
of the page */
trx_id_t max_trx_id, /*!< in: PAGE_MAX_TRX_ID */
- const redo_page_compress_t* page_comp_info,
- /*!< in: used for applying
- TRUNCATE log
- record during recovery */
mtr_t* mtr) /*!< in/out: mini-transaction
handle */
{
page_t* page;
page_zip_des_t* page_zip = buf_block_get_page_zip(block);
- bool is_spatial;
ut_ad(block);
ut_ad(page_zip);
- ut_ad(index == NULL || dict_table_is_comp(index->table));
- is_spatial = index ? dict_index_is_spatial(index)
- : page_comp_info->type & DICT_SPATIAL;
+ ut_ad(dict_table_is_comp(index->table));
/* PAGE_MAX_TRX_ID or PAGE_ROOT_AUTO_INC are always 0 for
temporary tables. */
@@ -488,22 +479,11 @@ page_create_zip(
|| !dict_index_is_sec_or_ibuf(index)
|| index->table->is_temporary());
- page = page_create_low(block, TRUE, is_spatial);
+ page = page_create_low(block, TRUE, dict_index_is_spatial(index));
mach_write_to_2(PAGE_HEADER + PAGE_LEVEL + page, level);
mach_write_to_8(PAGE_HEADER + PAGE_MAX_TRX_ID + page, max_trx_id);
- if (truncate_t::s_fix_up_active) {
- /* Compress the index page created when applying
- TRUNCATE log during recovery */
- if (!page_zip_compress(page_zip, page, index, page_zip_level,
- page_comp_info, NULL)) {
- /* The compression of a newly created
- page should always succeed. */
- ut_error;
- }
-
- } else if (!page_zip_compress(page_zip, page, index,
- page_zip_level, NULL, mtr)) {
+ if (!page_zip_compress(page_zip, page, index, page_zip_level, mtr)) {
/* The compression of a newly created
page should always succeed. */
ut_error;
@@ -549,7 +529,7 @@ page_create_empty(
ut_ad(!index->table->is_temporary());
page_create_zip(block, index,
page_header_get_field(page, PAGE_LEVEL),
- max_trx_id, NULL, mtr);
+ max_trx_id, mtr);
} else {
page_create(block, mtr, page_is_comp(page),
dict_index_is_spatial(index));
@@ -724,11 +704,8 @@ page_copy_rec_list_end(
if (new_page_zip) {
mtr_set_log_mode(mtr, log_mode);
- if (!page_zip_compress(new_page_zip,
- new_page,
- index,
- page_zip_level,
- NULL, mtr)) {
+ if (!page_zip_compress(new_page_zip, new_page, index,
+ page_zip_level, mtr)) {
/* Before trying to reorganize the page,
store the number of preceding records on the page. */
ulint ret_pos
@@ -893,7 +870,7 @@ page_copy_rec_list_start(
goto zip_reorganize;);
if (!page_zip_compress(new_page_zip, new_page, index,
- page_zip_level, NULL, mtr)) {
+ page_zip_level, mtr)) {
ulint ret_pos;
#ifndef DBUG_OFF
zip_reorganize:
@@ -1834,6 +1811,7 @@ page_print_list(
count = 0;
for (;;) {
offsets = rec_get_offsets(cur.rec, index, offsets,
+ page_rec_is_leaf(cur.rec),
ULINT_UNDEFINED, &heap);
page_rec_print(cur.rec, offsets);
@@ -1856,6 +1834,7 @@ page_print_list(
if (count + pr_n >= n_recs) {
offsets = rec_get_offsets(cur.rec, index, offsets,
+ page_rec_is_leaf(cur.rec),
ULINT_UNDEFINED, &heap);
page_rec_print(cur.rec, offsets);
}
@@ -2550,16 +2529,14 @@ wrong_page_type:
ib::error() << "REC_INFO_MIN_REC_FLAG "
"is set in a leaf-page record";
ret = false;
- } else if (rec_get_deleted_flag(
- rec, page_is_comp(page))) {
- /* If this were a 10.4 metadata
- record for index->table->instant
- we should not get here in 10.3, because
- the metadata record should not have
- been recognized by
- btr_cur_instant_init_low(). */
- ib::error() << "Metadata record "
- "is delete-marked";
+ } else if (!rec_get_deleted_flag(
+ rec, page_is_comp(page))
+ != !index->table->instant) {
+ ib::error() << (index->table->instant
+ ? "Metadata record "
+ "is not delete-marked"
+ : "Metadata record "
+ "is delete-marked");
ret = false;
}
} else if (!page_has_prev(page)
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 05b4d907ff0..727e6c21653 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -25,8 +25,12 @@ Compressed page interface
Created June 2005 by Marko Makela
*******************************************************/
-#include "page0size.h"
#include "page0zip.h"
+#include "fsp0types.h"
+#include "page0page.h"
+#include "buf0checksum.h"
+#include "ut0crc32.h"
+#include "zlib.h"
#include "span.h"
using st_::span;
@@ -34,28 +38,21 @@ using st_::span;
/** A BLOB field reference full of zero, for use in assertions and tests.
Initially, BLOB field references are set to zero, in
dtuple_convert_big_rec(). */
+alignas(UNIV_PAGE_SIZE_MIN)
const byte field_ref_zero[UNIV_PAGE_SIZE_MAX] = { 0, };
#ifndef UNIV_INNOCHECKSUM
-#include "page0page.h"
#include "mtr0log.h"
#include "dict0dict.h"
#include "btr0cur.h"
-#include "page0types.h"
#include "log0recv.h"
#include "row0row.h"
-#include "row0trunc.h"
-#include "zlib.h"
-#include "buf0buf.h"
-#include "buf0types.h"
-#include "buf0checksum.h"
#include "btr0sea.h"
#include "dict0boot.h"
#include "lock0lock.h"
#include "srv0srv.h"
#include "buf0lru.h"
#include "srv0mon.h"
-#include "ut0crc32.h"
#include <map>
#include <algorithm>
@@ -104,7 +101,7 @@ Compare at most sizeof(field_ref_zero) bytes.
@param s in: size of the memory block, in bytes */
#define ASSERT_ZERO(b, s) \
ut_ad(!memcmp(b, field_ref_zero, \
- ut_min(static_cast<size_t>(s), sizeof field_ref_zero)));
+ std::min<size_t>(s, sizeof field_ref_zero)));
/** Assert that a BLOB pointer is filled with zero bytes.
@param b in: BLOB pointer */
#define ASSERT_ZERO_BLOB(b) \
@@ -176,18 +173,17 @@ page_zip_is_too_big(
const dict_index_t* index,
const dtuple_t* entry)
{
- const page_size_t& page_size =
- dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
/* Estimate the free space of an empty compressed page.
Subtract one byte for the encoded heap_no in the
modification log. */
ulint free_space_zip = page_zip_empty_size(
- index->n_fields, page_size.physical());
+ index->n_fields, zip_size);
ulint n_uniq = dict_index_get_n_unique_in_tree(index);
ut_ad(dict_table_is_comp(index->table));
- ut_ad(page_size.is_compressed());
+ ut_ad(zip_size);
if (free_space_zip == 0) {
return(true);
@@ -1246,17 +1242,11 @@ page_zip_compress(
dict_index_t* index, /*!< in: index of the B-tree
node */
ulint level, /*!< in: commpression level */
- const redo_page_compress_t* page_comp_info,
- /*!< in: used for applying
- TRUNCATE log
- record during recovery */
mtr_t* mtr) /*!< in/out: mini-transaction,
or NULL */
{
z_stream c_stream;
int err;
- ulint n_fields; /* number of index fields
- needed */
byte* fields; /*!< index field information */
byte* buf; /*!< compressed payload of the
page */
@@ -1271,7 +1261,6 @@ page_zip_compress(
ulint n_blobs = 0;
byte* storage; /* storage of uncompressed
columns */
- index_id_t ind_id;
const ulonglong ns = my_interval_timer();
#ifdef PAGE_ZIP_COMPRESS_DBG
FILE* logfile = NULL;
@@ -1286,10 +1275,8 @@ page_zip_compress(
ut_a(fil_page_index_page_check(page));
ut_ad(page_simple_validate_new((page_t*) page));
ut_ad(page_zip_simple_validate(page_zip));
- ut_ad(!index
- || (index
- && dict_table_is_comp(index->table)
- && !dict_index_is_ibuf(index)));
+ ut_ad(dict_table_is_comp(index->table));
+ ut_ad(!dict_index_is_ibuf(index));
UNIV_MEM_ASSERT_RW(page, srv_page_size);
@@ -1309,18 +1296,10 @@ page_zip_compress(
== PAGE_NEW_SUPREMUM);
}
- if (truncate_t::s_fix_up_active) {
- ut_ad(page_comp_info != NULL);
- n_fields = page_comp_info->n_fields;
- ind_id = page_comp_info->index_id;
- } else {
- if (page_is_leaf(page)) {
- n_fields = dict_index_get_n_fields(index);
- } else {
- n_fields = dict_index_get_n_unique_in_tree_nonleaf(index);
- }
- ind_id = index->id;
- }
+ const ulint n_fields = page_is_leaf(page)
+ ? dict_index_get_n_fields(index)
+ : dict_index_get_n_unique_in_tree_nonleaf(index);
+ index_id_t ind_id = index->id;
/* The dense directory excludes the infimum and supremum records. */
n_dense = ulint(page_dir_get_n_heap(page)) - PAGE_HEAP_NO_USER_LOW;
@@ -1431,20 +1410,8 @@ page_zip_compress(
/* Dense page directory and uncompressed columns, if any */
if (page_is_leaf(page)) {
- if ((index && dict_index_is_clust(index))
- || (page_comp_info
- && (page_comp_info->type & DICT_CLUSTERED))) {
-
- if (index) {
- trx_id_col = dict_index_get_sys_col_pos(
- index, DATA_TRX_ID);
- ut_ad(trx_id_col > 0);
- ut_ad(trx_id_col != ULINT_UNDEFINED);
- } else if (page_comp_info
- && (page_comp_info->type
- & DICT_CLUSTERED)) {
- trx_id_col = page_comp_info->trx_id_pos;
- }
+ if (dict_index_is_clust(index)) {
+ trx_id_col = index->db_trx_id();
slot_size = PAGE_ZIP_DIR_SLOT_SIZE
+ DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN;
@@ -1452,10 +1419,6 @@ page_zip_compress(
} else {
/* Signal the absence of trx_id
in page_zip_fields_encode() */
- if (index) {
- ut_ad(dict_index_get_sys_col_pos(
- index, DATA_TRX_ID) == ULINT_UNDEFINED);
- }
trx_id_col = 0;
slot_size = PAGE_ZIP_DIR_SLOT_SIZE;
}
@@ -1469,19 +1432,9 @@ page_zip_compress(
goto zlib_error;
}
- c_stream.avail_out -= static_cast<uInt>(n_dense * slot_size);
- if (truncate_t::s_fix_up_active) {
- ut_ad(page_comp_info != NULL);
- c_stream.avail_in = static_cast<uInt>(
- page_comp_info->field_len);
- for (ulint i = 0; i < page_comp_info->field_len; i++) {
- fields[i] = page_comp_info->fields[i];
- }
- } else {
- c_stream.avail_in = static_cast<uInt>(
- page_zip_fields_encode(
- n_fields, index, trx_id_col, fields));
- }
+ c_stream.avail_out -= uInt(n_dense * slot_size);
+ c_stream.avail_in = uInt(page_zip_fields_encode(n_fields, index,
+ trx_id_col, fields));
c_stream.next_in = fields;
if (UNIV_LIKELY(!trx_id_col)) {
@@ -1635,7 +1588,7 @@ err_exit:
mutex_exit(&page_zip_stat_per_index_mutex);
}
- if (page_is_leaf(page) && !truncate_t::s_fix_up_active) {
+ if (page_is_leaf(page)) {
dict_index_zip_success(index);
}
@@ -1652,7 +1605,7 @@ page_zip_fields_free(
{
if (index) {
dict_table_t* table = index->table;
- dict_index_zip_pad_mutex_destroy(index);
+ mutex_free(&index->zip_pad.mutex);
mem_heap_free(index->heap);
dict_mem_table_free(table);
@@ -2167,6 +2120,10 @@ page_zip_apply_log(
rec_get_offsets_reverse(data, index,
hs & REC_STATUS_NODE_PTR,
offsets);
+ /* Silence a debug assertion in rec_offs_make_valid().
+ This will be overwritten in page_zip_set_extra_bytes(),
+ called by page_zip_decompress_low(). */
+ ut_d(rec[-REC_NEW_INFO_BITS] = 0);
rec_offs_make_valid(rec, index, is_leaf, offsets);
/* Copy the extra bytes (backwards). */
@@ -3781,29 +3738,25 @@ page_zip_write_rec(
ulint len;
if (dict_index_is_clust(index)) {
- ulint trx_id_col;
-
- trx_id_col = dict_index_get_sys_col_pos(index,
- DATA_TRX_ID);
- ut_ad(trx_id_col != ULINT_UNDEFINED);
-
/* Store separately trx_id, roll_ptr and
the BTR_EXTERN_FIELD_REF of each BLOB column. */
if (rec_offs_any_extern(offsets)) {
data = page_zip_write_rec_ext(
page_zip, page,
rec, index, offsets, create,
- trx_id_col, heap_no, storage, data);
+ index->db_trx_id(), heap_no,
+ storage, data);
} else {
/* Locate trx_id and roll_ptr. */
const byte* src
= rec_get_nth_field(rec, offsets,
- trx_id_col, &len);
+ index->db_trx_id(),
+ &len);
ut_ad(len == DATA_TRX_ID_LEN);
ut_ad(src + DATA_TRX_ID_LEN
== rec_get_nth_field(
rec, offsets,
- trx_id_col + 1, &len));
+ index->db_roll_ptr(), &len));
ut_ad(len == DATA_ROLL_PTR_LEN);
/* Log the preceding fields. */
@@ -3831,8 +3784,6 @@ page_zip_write_rec(
} else {
/* Leaf page of a secondary index:
no externally stored columns */
- ut_ad(dict_index_get_sys_col_pos(index, DATA_TRX_ID)
- == ULINT_UNDEFINED);
ut_ad(!rec_offs_any_extern(offsets));
/* Log the entire record. */
@@ -3906,7 +3857,7 @@ page_zip_parse_write_blob_ptr(
|| offset >= srv_page_size
|| z_offset >= srv_page_size) {
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -4048,7 +3999,7 @@ page_zip_parse_write_node_ptr(
|| offset >= srv_page_size
|| z_offset >= srv_page_size) {
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -4263,7 +4214,7 @@ page_zip_parse_write_trx_id(
|| offset >= srv_page_size
|| z_offset >= srv_page_size) {
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -4680,7 +4631,7 @@ page_zip_parse_write_header(
if (len == 0 || offset + len >= PAGE_DATA) {
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -4816,9 +4767,7 @@ page_zip_reorganize(
/* Restore logging. */
mtr_set_log_mode(mtr, log_mode);
- if (!page_zip_compress(page_zip, page, index,
- page_zip_level, NULL, mtr)) {
-
+ if (!page_zip_compress(page_zip, page, index, page_zip_level, mtr)) {
buf_block_free(temp_block);
return(FALSE);
}
@@ -4960,7 +4909,7 @@ byte* page_zip_parse_compress(const byte* ptr, const byte* end_ptr,
if (!page_zip || page_zip_get_size(page_zip) < size
|| block->page.id.page_no() < 3) {
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys.found_corrupt_log = TRUE;
return(NULL);
}
@@ -4999,12 +4948,7 @@ uint32_t
page_zip_calc_checksum(
const void* data,
ulint size,
- srv_checksum_algorithm_t algo
-#ifdef INNODB_BUG_ENDIAN_CRC32
- /** for crc32, use the big-endian bug-compatible crc32 variant */
- , bool use_legacy_big_endian
-#endif
-)
+ srv_checksum_algorithm_t algo)
{
uLong adler;
const Bytef* s = static_cast<const byte*>(data);
@@ -5013,22 +4957,11 @@ page_zip_calc_checksum(
and FIL_PAGE_FILE_FLUSH_LSN from the checksum. */
switch (algo) {
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
ut_ad(size > FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
-#ifdef INNODB_BUG_ENDIAN_CRC32
- if (use_legacy_big_endian) {
- return ut_crc32_legacy_big_endian(s + FIL_PAGE_OFFSET,
- FIL_PAGE_LSN
- - FIL_PAGE_OFFSET)
- ^ ut_crc32_legacy_big_endian(
- s + FIL_PAGE_TYPE, 2)
- ^ ut_crc32_legacy_big_endian(
- s + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
- size
- - FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- }
-#endif
return ut_crc32(s + FIL_PAGE_OFFSET,
FIL_PAGE_LSN - FIL_PAGE_OFFSET)
^ ut_crc32(s + FIL_PAGE_TYPE, 2)
@@ -5111,40 +5044,26 @@ bool page_zip_verify_checksum(const byte *data, size_t size)
}
switch (curr_algo) {
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
-#ifdef INNODB_BUG_ENDIAN_CRC32
- return stored == page_zip_calc_checksum(data, size, curr_algo,
- true);
-#endif
- /* fall through */
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
return FALSE;
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
case SRV_CHECKSUM_ALGORITHM_CRC32:
if (stored == BUF_NO_CHECKSUM_MAGIC) {
return(TRUE);
}
- return
-#ifdef INNODB_BUG_ENDIAN_CRC32
- stored == page_zip_calc_checksum(data, size, curr_algo,
- true) ||
-#endif
- stored == page_zip_calc_checksum(
- data, size, SRV_CHECKSUM_ALGORITHM_INNODB);
+ return stored == page_zip_calc_checksum(
+ data, size, SRV_CHECKSUM_ALGORITHM_INNODB);
case SRV_CHECKSUM_ALGORITHM_INNODB:
if (stored == BUF_NO_CHECKSUM_MAGIC) {
return TRUE;
}
return stored == page_zip_calc_checksum(
- data, size, SRV_CHECKSUM_ALGORITHM_CRC32)
-#ifdef INNODB_BUG_ENDIAN_CRC32
- || stored == page_zip_calc_checksum(
- data, size,
- SRV_CHECKSUM_ALGORITHM_CRC32, true)
-#endif
- ;
+ data, size, SRV_CHECKSUM_ALGORITHM_CRC32);
case SRV_CHECKSUM_ALGORITHM_NONE:
return TRUE;
}
diff --git a/storage/innobase/pars/pars0pars.cc b/storage/innobase/pars/pars0pars.cc
index 43f089e3bf7..ebfe7ada3b1 100644
--- a/storage/innobase/pars/pars0pars.cc
+++ b/storage/innobase/pars/pars0pars.cc
@@ -1986,7 +1986,7 @@ pars_sql(
heap = mem_heap_create(16000);
/* Currently, the parser is not reentrant: */
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
pars_sym_tab_global = sym_tab_create(heap);
diff --git a/storage/innobase/pars/pars0sym.cc b/storage/innobase/pars/pars0sym.cc
index 6e416d7b635..5e4c0e0f6e0 100644
--- a/storage/innobase/pars/pars0sym.cc
+++ b/storage/innobase/pars/pars0sym.cc
@@ -67,7 +67,7 @@ sym_tab_free_private(
sym_node_t* sym;
func_node_t* func;
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_ad(mutex_own(&dict_sys.mutex));
for (sym = UT_LIST_GET_FIRST(sym_tab->sym_list);
sym != NULL;
diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc
index abd4672517e..3f4810dcc0e 100644
--- a/storage/innobase/que/que0que.cc
+++ b/storage/innobase/que/que0que.cc
@@ -1185,9 +1185,9 @@ que_eval_sql(
/*=========*/
pars_info_t* info, /*!< in: info struct, or NULL */
const char* sql, /*!< in: SQL string */
- ibool reserve_dict_mutex,
- /*!< in: if TRUE, acquire/release
- dict_sys->mutex around call to pars_sql. */
+ bool reserve_dict_mutex,
+ /*!< in: whether to acquire/release
+ dict_sys.mutex around call to pars_sql. */
trx_t* trx) /*!< in: trx */
{
que_thr_t* thr;
@@ -1199,13 +1199,13 @@ que_eval_sql(
ut_a(trx->error_state == DB_SUCCESS);
if (reserve_dict_mutex) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
graph = pars_sql(info, sql);
if (reserve_dict_mutex) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
graph->trx = trx;
@@ -1218,13 +1218,13 @@ que_eval_sql(
que_run_threads(thr);
if (reserve_dict_mutex) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
que_graph_free(graph);
if (reserve_dict_mutex) {
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
DBUG_RETURN(trx->error_state);
diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc
index e14f564e264..1cc88f4b758 100644
--- a/storage/innobase/read/read0read.cc
+++ b/storage/innobase/read/read0read.cc
@@ -200,7 +200,7 @@ inline void ReadView::snapshot(trx_t *trx)
void ReadView::open(trx_t *trx)
{
ut_ad(this == &trx->read_view);
- switch (m_state)
+ switch (state())
{
case READ_VIEW_STATE_OPEN:
ut_ad(!srv_read_only_mode);
@@ -254,8 +254,7 @@ void ReadView::open(trx_t *trx)
*/
mutex_enter(&trx_sys.mutex);
mutex_exit(&trx_sys.mutex);
- my_atomic_store32_explicit(&m_state, READ_VIEW_STATE_SNAPSHOT,
- MY_MEMORY_ORDER_RELAXED);
+ m_state.store(READ_VIEW_STATE_SNAPSHOT, std::memory_order_relaxed);
break;
default:
ut_ad(0);
@@ -264,8 +263,7 @@ void ReadView::open(trx_t *trx)
snapshot(trx);
reopen:
m_creator_trx_id= trx->id;
- my_atomic_store32_explicit(&m_state, READ_VIEW_STATE_OPEN,
- MY_MEMORY_ORDER_RELEASE);
+ m_state.store(READ_VIEW_STATE_OPEN, std::memory_order_release);
}
@@ -284,7 +282,7 @@ void trx_sys_t::clone_oldest_view()
for (const trx_t *trx= UT_LIST_GET_FIRST(trx_list); trx;
trx= UT_LIST_GET_NEXT(trx_list, trx))
{
- int32_t state;
+ uint32_t state;
while ((state= trx->read_view.get_state()) == READ_VIEW_STATE_SNAPSHOT)
ut_delay(1);
diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc
index b093a8b5952..34ae5b08bab 100644
--- a/storage/innobase/rem/rem0cmp.cc
+++ b/storage/innobase/rem/rem0cmp.cc
@@ -798,7 +798,7 @@ cmp_dtuple_rec_with_match_bytes(
& rec_get_info_bits(rec, rec_offs_comp(offsets)))) {
ut_ad(page_rec_is_first(rec, page_align(rec)));
ut_ad(!page_has_prev(page_align(rec)));
- ut_ad(rec_is_metadata(rec, index));
+ ut_ad(rec_is_metadata(rec, *index));
return 1;
}
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 458457c52d5..a1e19164ce9 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2019, MariaDB Corporation.
+Copyright (c) 2017, 2020, 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
@@ -169,7 +169,7 @@ rec_get_n_extern_new(
ut_ad(!index->table->supports_instant() || index->is_dummy);
ut_ad(!index->is_instant());
ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY
- || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED);
+ || rec_get_status(rec) == REC_STATUS_INSTANT);
ut_ad(n == ULINT_UNDEFINED || n <= dict_index_get_n_fields(index));
if (n == ULINT_UNDEFINED) {
@@ -231,40 +231,22 @@ rec_get_n_extern_new(
return(n_extern);
}
-/** Get the added field count in a REC_STATUS_COLUMNS_ADDED record.
-@param[in,out] header variable header of a REC_STATUS_COLUMNS_ADDED record
-@return number of added fields */
-static inline unsigned rec_get_n_add_field(const byte*& header)
-{
- unsigned n_fields_add = *--header;
- if (n_fields_add < 0x80) {
- ut_ad(rec_get_n_add_field_len(n_fields_add) == 1);
- return n_fields_add;
- }
-
- n_fields_add &= 0x7f;
- n_fields_add |= unsigned(*--header) << 7;
- ut_ad(n_fields_add < REC_MAX_N_FIELDS);
- ut_ad(rec_get_n_add_field_len(n_fields_add) == 2);
- return n_fields_add;
-}
-
/** Format of a leaf-page ROW_FORMAT!=REDUNDANT record */
enum rec_leaf_format {
/** Temporary file record */
REC_LEAF_TEMP,
- /** Temporary file record, with added columns
- (REC_STATUS_COLUMNS_ADDED) */
- REC_LEAF_TEMP_COLUMNS_ADDED,
+ /** Temporary file record, with added columns (REC_STATUS_INSTANT) */
+ REC_LEAF_TEMP_INSTANT,
/** Normal (REC_STATUS_ORDINARY) */
REC_LEAF_ORDINARY,
- /** With added columns (REC_STATUS_COLUMNS_ADDED) */
- REC_LEAF_COLUMNS_ADDED
+ /** With add or drop columns (REC_STATUS_INSTANT) */
+ REC_LEAF_INSTANT
};
/** Determine the offset to each field in a leaf-page record
in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED.
This is a special case of rec_init_offsets() and rec_get_offsets_func().
+@tparam mblob whether the record includes a metadata BLOB
@param[in] rec leaf-page record
@param[in] index the index that the record belongs in
@param[in] n_core number of core fields (index->n_core_fields)
@@ -272,6 +254,7 @@ This is a special case of rec_init_offsets() and rec_get_offsets_func().
NULL to refer to index->fields[].col->def_val
@param[in,out] offsets offsets, with valid rec_offs_n_fields(offsets)
@param[in] format record format */
+template<bool mblob = false>
static inline
void
rec_init_offsets_comp_ordinary(
@@ -293,12 +276,32 @@ rec_init_offsets_comp_ordinary(
ut_ad(n_core > 0);
ut_ad(index->n_fields >= n_core);
ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
- ut_ad(format == REC_LEAF_TEMP || format == REC_LEAF_TEMP_COLUMNS_ADDED
+ ut_ad(format == REC_LEAF_TEMP || format == REC_LEAF_TEMP_INSTANT
|| dict_table_is_comp(index->table));
- ut_ad(format != REC_LEAF_TEMP_COLUMNS_ADDED
+ ut_ad(format != REC_LEAF_TEMP_INSTANT
|| index->n_fields == rec_offs_n_fields(offsets));
ut_d(ulint n_null= 0);
+ if (mblob) {
+ ut_ad(index->is_dummy || index->table->instant);
+ ut_ad(index->is_dummy || index->is_instant());
+ ut_ad(rec_offs_n_fields(offsets)
+ <= ulint(index->n_fields) + 1);
+ ut_ad(!def_val);
+ ut_ad(format == REC_LEAF_INSTANT);
+ nulls -= REC_N_NEW_EXTRA_BYTES;
+ n_fields = n_core + 1 + rec_get_n_add_field(nulls);
+ ut_ad(n_fields <= ulint(index->n_fields) + 1);
+ const ulint n_nullable = index->get_n_nullable(n_fields - 1);
+ const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable);
+ ut_d(n_null = n_nullable);
+ ut_ad(n_null <= index->n_nullable);
+ ut_ad(n_null_bytes >= index->n_core_null_bytes
+ || n_core < index->n_core_fields);
+ lens = --nulls - n_null_bytes;
+ goto start;
+ }
+
switch (format) {
case REC_LEAF_TEMP:
if (dict_table_is_comp(index->table)) {
@@ -312,17 +315,15 @@ rec_init_offsets_comp_ordinary(
ordinary:
lens = --nulls - index->n_core_null_bytes;
- ut_d(n_null = std::min(index->n_core_null_bytes * 8U,
- index->n_nullable));
+ ut_d(n_null = std::min<uint>(index->n_core_null_bytes * 8U,
+ index->n_nullable));
break;
- case REC_LEAF_COLUMNS_ADDED:
- /* We would have !index->is_instant() when rolling back
- an instant ADD COLUMN operation. */
+ case REC_LEAF_INSTANT:
nulls -= REC_N_NEW_EXTRA_BYTES;
ut_ad(index->is_instant());
/* fall through */
- case REC_LEAF_TEMP_COLUMNS_ADDED:
- n_fields = n_core + 1 + rec_get_n_add_field(nulls);
+ case REC_LEAF_TEMP_INSTANT:
+ n_fields = n_core + rec_get_n_add_field(nulls) + 1;
ut_ad(n_fields <= index->n_fields);
const ulint n_nullable = index->get_n_nullable(n_fields);
const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable);
@@ -333,6 +334,7 @@ ordinary:
lens = --nulls - n_null_bytes;
}
+start:
#ifdef UNIV_DEBUG
/* We cannot invoke rec_offs_make_valid() if format==REC_LEAF_TEMP.
Similarly, rec_offs_validate() will fail in that case, because
@@ -342,17 +344,26 @@ ordinary:
#endif /* UNIV_DEBUG */
/* read the lengths of fields 0..n_fields */
+ offset_t len;
ulint i = 0;
- do {
- const dict_field_t* field
- = dict_index_get_nth_field(index, i);
- const dict_col_t* col
- = dict_field_get_col(field);
- offset_t len;
+ const dict_field_t* field = index->fields;
- /* set default value flag */
- if (i < n_fields) {
- } else if (def_val) {
+ do {
+ if (mblob) {
+ if (i == index->first_user_field()) {
+ offs += FIELD_REF_SIZE;
+ len = combine(offs, STORED_OFFPAGE);
+ any |= REC_OFFS_EXTERNAL;
+ field--;
+ continue;
+ } else if (i >= n_fields) {
+ len = combine(offs, DEFAULT);
+ any |= REC_OFFS_DEFAULT;
+ continue;
+ }
+ } else if (i < n_fields) {
+ /* The field is present, and will be covered below. */
+ } else if (!mblob && def_val) {
const dict_col_t::def_t& d = def_val[i - n_core];
if (!d.data) {
len = combine(offs, SQL_NULL);
@@ -362,7 +373,7 @@ ordinary:
any |= REC_OFFS_DEFAULT;
}
- goto resolved;
+ continue;
} else {
ulint dlen;
if (!index->instant_field_value(i, &dlen)) {
@@ -373,10 +384,12 @@ ordinary:
any |= REC_OFFS_DEFAULT;
}
- goto resolved;
+ continue;
}
- if (!(col->prtype & DATA_NOT_NULL)) {
+ const dict_col_t* col = field->col;
+
+ if (col->is_nullable()) {
/* nullable field => read the null flag */
ut_ad(n_null--);
@@ -392,7 +405,7 @@ ordinary:
the length to zero and enable the
SQL NULL flag in offsets[]. */
len = combine(offs, SQL_NULL);
- goto resolved;
+ continue;
}
null_mask <<= 1;
}
@@ -423,16 +436,15 @@ ordinary:
len = offs;
}
- goto resolved;
+ continue;
}
len = offs += len;
} else {
len = offs += field->fixed_len;
}
-resolved:
- rec_offs_base(offsets)[i + 1] = len;
- } while (++i < rec_offs_n_fields(offsets));
+ } while (field++, rec_offs_base(offsets)[++i] = len,
+ i < rec_offs_n_fields(offsets));
*rec_offs_base(offsets)
= static_cast<offset_t>(rec - (lens + 1)) | REC_OFFS_COMPACT | any;
@@ -451,7 +463,10 @@ rec_offs_make_valid(
bool leaf,
offset_t* offsets)
{
- ut_ad(rec_offs_n_fields(offsets)
+ const bool is_alter_metadata = leaf
+ && rec_is_alter_metadata(rec, *index);
+ ut_ad(is_alter_metadata
+ || rec_offs_n_fields(offsets)
<= (leaf
? dict_index_get_n_fields(index)
: dict_index_get_n_unique_in_tree_nonleaf(index) + 1)
@@ -469,7 +484,8 @@ rec_offs_make_valid(
|| n >= rec_offs_n_fields(offsets));
for (; n < rec_offs_n_fields(offsets); n++) {
ut_ad(leaf);
- ut_ad(get_type(rec_offs_base(offsets)[1 + n]) == DEFAULT);
+ ut_ad(is_alter_metadata
+ || get_type(rec_offs_base(offsets)[1 + n]) == DEFAULT);
}
memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec));
memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index));
@@ -509,14 +525,18 @@ rec_offs_validate(
}
}
if (index) {
- ulint max_n_fields;
ut_ad(!memcmp(&index, &offsets[INDEX_OFFSET], sizeof(index)));
- max_n_fields = ut_max(
+ ulint max_n_fields = std::max(
dict_index_get_n_fields(index),
dict_index_get_n_unique_in_tree(index) + 1);
if (comp && rec) {
switch (rec_get_status(rec)) {
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
+ ut_ad(index->is_instant() || index->is_dummy);
+ ut_ad(max_n_fields == index->n_fields);
+ max_n_fields += index->table->instant
+ || index->is_dummy;
+ break;
case REC_STATUS_ORDINARY:
break;
case REC_STATUS_NODE_PTR:
@@ -530,14 +550,19 @@ rec_offs_validate(
default:
ut_error;
}
+ } else if (max_n_fields == index->n_fields
+ && (index->is_dummy
+ || (index->is_instant()
+ && index->table->instant))) {
+ max_n_fields++;
}
/* index->n_def == 0 for dummy indexes if !comp */
- ut_a(!comp || index->n_def);
- ut_a(!index->n_def || i <= max_n_fields);
+ ut_ad(!comp || index->n_def);
+ ut_ad(!index->n_def || i <= max_n_fields);
}
while (i--) {
ulint curr = get_value(rec_offs_base(offsets)[1 + i]);
- ut_a(curr <= last);
+ ut_ad(curr <= last);
last = curr;
}
return(TRUE);
@@ -571,7 +596,13 @@ rec_init_offsets(
ulint i = 0;
offset_t offs;
- ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable));
+ /* This assertion was relaxed for the btr_cur_open_at_index_side()
+ call in btr_cur_instant_init_low(). We cannot invoke
+ index->is_instant(), because the same assertion would fail there
+ until btr_cur_instant_init_low() has invoked
+ dict_table_t::deserialise_columns(). */
+ ut_ad(index->n_core_null_bytes <= UT_BITS_IN_BYTES(index->n_nullable)
+ || index->in_instant_init);
ut_d(memcpy(&offsets[RECORD_OFFSET], &rec, sizeof(rec)));
ut_d(memcpy(&offsets[INDEX_OFFSET], &index, sizeof(index)));
@@ -597,13 +628,13 @@ rec_init_offsets(
= dict_index_get_n_unique_in_tree_nonleaf(
index);
break;
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
ut_ad(leaf);
ut_ad(index->is_instant());
rec_init_offsets_comp_ordinary(rec, index, offsets,
index->n_core_fields,
NULL,
- REC_LEAF_COLUMNS_ADDED);
+ REC_LEAF_INSTANT);
return;
case REC_STATUS_ORDINARY:
ut_ad(leaf);
@@ -785,14 +816,17 @@ rec_get_offsets_func(
{
ulint n;
ulint size;
+ bool alter_metadata = false;
if (dict_table_is_comp(index->table)) {
switch (UNIV_EXPECT(rec_get_status(rec),
REC_STATUS_ORDINARY)) {
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
+ alter_metadata = rec_is_alter_metadata(rec, true);
+ /* fall through */
case REC_STATUS_ORDINARY:
ut_ad(leaf);
- n = dict_index_get_n_fields(index);
+ n = dict_index_get_n_fields(index) + alter_metadata;
break;
case REC_STATUS_NODE_PTR:
/* Node pointer records consist of the
@@ -836,7 +870,8 @@ rec_get_offsets_func(
|| dict_index_is_ibuf(index)
|| n == n_fields /* btr_pcur_restore_position() */
|| (n + (index->id == DICT_INDEXES_ID)
- >= index->n_core_fields && n <= index->n_fields));
+ >= index->n_core_fields && n <= index->n_fields
+ + unsigned(rec_is_alter_metadata(rec, false))));
if (is_user_rec && leaf && n < index->n_fields) {
ut_ad(!index->is_dummy);
@@ -866,8 +901,25 @@ rec_get_offsets_func(
}
rec_offs_set_n_fields(offsets, n);
- rec_init_offsets(rec, index, leaf, offsets);
- return(offsets);
+
+ if (UNIV_UNLIKELY(alter_metadata) && index->table->not_redundant()) {
+#ifdef UNIV_DEBUG
+ memcpy(&offsets[RECORD_OFFSET], &rec, sizeof rec);
+ memcpy(&offsets[INDEX_OFFSET], &index, sizeof index);
+#endif /* UNIV_DEBUG */
+ ut_ad(leaf);
+ ut_ad(index->is_dummy || index->table->instant);
+ ut_ad(index->is_dummy || index->is_instant());
+ ut_ad(rec_offs_n_fields(offsets)
+ <= ulint(index->n_fields) + 1);
+ rec_init_offsets_comp_ordinary<true>(rec, index, offsets,
+ index->n_core_fields,
+ NULL,
+ REC_LEAF_INSTANT);
+ } else {
+ rec_init_offsets(rec, index, leaf, offsets);
+ }
+ return offsets;
}
/******************************************************//**
@@ -1041,36 +1093,45 @@ rec_get_nth_field_offs_old(
return(os);
}
-/**********************************************************//**
-Determines the size of a data tuple prefix in ROW_FORMAT=COMPACT.
+/** Determine the size of a data tuple prefix in ROW_FORMAT=COMPACT.
+@tparam mblob whether the record includes a metadata BLOB
+@param[in] index record descriptor; dict_table_is_comp()
+ is assumed to hold, even if it doesn't
+@param[in] dfield array of data fields
+@param[in] n_fields number of data fields
+@param[out] extra extra size
+@param[in] status status flags
+@param[in] temp whether this is a temporary file record
@return total size */
-MY_ATTRIBUTE((warn_unused_result, nonnull(1,2)))
+template<bool mblob = false>
static inline
ulint
rec_get_converted_size_comp_prefix_low(
-/*===================================*/
- const dict_index_t* index, /*!< in: record descriptor;
- dict_table_is_comp() is
- assumed to hold, even if
- it does not */
- const dfield_t* fields, /*!< in: array of data fields */
- ulint n_fields,/*!< in: number of data fields */
- ulint* extra, /*!< out: extra size */
- rec_comp_status_t status, /*!< in: status flags */
- bool temp) /*!< in: whether this is a
- temporary file record */
+ const dict_index_t* index,
+ const dfield_t* dfield,
+ ulint n_fields,
+ ulint* extra,
+ rec_comp_status_t status,
+ bool temp)
{
ulint extra_size = temp ? 0 : REC_N_NEW_EXTRA_BYTES;
- ulint data_size;
- ulint i;
ut_ad(n_fields > 0);
- ut_ad(n_fields <= dict_index_get_n_fields(index));
+ ut_ad(n_fields <= dict_index_get_n_fields(index) + mblob);
ut_d(ulint n_null = index->n_nullable);
ut_ad(status == REC_STATUS_ORDINARY || status == REC_STATUS_NODE_PTR
- || status == REC_STATUS_COLUMNS_ADDED);
+ || status == REC_STATUS_INSTANT);
- if (status == REC_STATUS_COLUMNS_ADDED
- && (!temp || n_fields > index->n_core_fields)) {
+ if (mblob) {
+ ut_ad(!temp);
+ ut_ad(index->table->instant);
+ ut_ad(index->is_instant());
+ ut_ad(status == REC_STATUS_INSTANT);
+ ut_ad(n_fields == ulint(index->n_fields) + 1);
+ extra_size += UT_BITS_IN_BYTES(index->n_nullable)
+ + rec_get_n_add_field_len(n_fields - 1
+ - index->n_core_fields);
+ } else if (status == REC_STATUS_INSTANT
+ && (!temp || n_fields > index->n_core_fields)) {
ut_ad(index->is_instant());
ut_ad(UT_BITS_IN_BYTES(n_null) >= index->n_core_null_bytes);
extra_size += UT_BITS_IN_BYTES(index->get_n_nullable(n_fields))
@@ -1081,7 +1142,7 @@ rec_get_converted_size_comp_prefix_low(
extra_size += index->n_core_null_bytes;
}
- data_size = 0;
+ ulint data_size = 0;
if (temp && dict_table_is_comp(index->table)) {
/* No need to do adjust fixed_len=0. We only need to
@@ -1089,46 +1150,53 @@ rec_get_converted_size_comp_prefix_low(
temp = false;
}
+ const dfield_t* const end = dfield + n_fields;
/* read the lengths of fields 0..n */
- for (i = 0; i < n_fields; i++) {
- const dict_field_t* field;
- ulint len;
- ulint fixed_len;
- const dict_col_t* col;
+ for (ulint i = 0; dfield < end; i++, dfield++) {
+ if (mblob && i == index->first_user_field()) {
+ data_size += FIELD_REF_SIZE;
+ if (++dfield == end) {
+ ut_ad(i == index->n_fields);
+ break;
+ }
+ }
- field = dict_index_get_nth_field(index, i);
- len = dfield_get_len(&fields[i]);
- col = dict_field_get_col(field);
+ ulint len = dfield_get_len(dfield);
+ const dict_field_t* field = dict_index_get_nth_field(index, i);
#ifdef UNIV_DEBUG
- 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);
+ if (DATA_GEOMETRY_MTYPE(field->col->mtype) && i == 0) {
+ ut_ad(dfield->type.prtype & DATA_GIS_MBR);
} else {
- ut_ad(type->mtype == DATA_SYS_CHILD
- || dict_col_type_assert_equal(col, type));
+ ut_ad(dfield->type.mtype == DATA_SYS_CHILD
+ || dict_col_type_assert_equal(
+ field->col, &dfield->type));
}
} else {
- ut_ad(dict_col_type_assert_equal(col, type));
+ ut_ad(field->col->is_dropped()
+ || dict_col_type_assert_equal(field->col,
+ &dfield->type));
}
#endif
/* All NULLable fields must be included in the n_null count. */
- ut_ad((col->prtype & DATA_NOT_NULL) || n_null--);
+ ut_ad(!field->col->is_nullable() || n_null--);
- if (dfield_is_null(&fields[i])) {
+ if (dfield_is_null(dfield)) {
/* No length is stored for NULL fields. */
- ut_ad(!(col->prtype & DATA_NOT_NULL));
+ ut_ad(field->col->is_nullable());
continue;
}
- ut_ad(len <= col->len || DATA_LARGE_MTYPE(col->mtype)
- || (col->len == 0 && col->mtype == DATA_VARCHAR));
+ ut_ad(len <= field->col->len
+ || DATA_LARGE_MTYPE(field->col->mtype)
+ || (field->col->len == 0
+ && field->col->mtype == DATA_VARCHAR));
- fixed_len = field->fixed_len;
+ ulint fixed_len = field->fixed_len;
if (temp && fixed_len
- && !dict_col_get_fixed_size(col, temp)) {
+ && !dict_col_get_fixed_size(field->col, temp)) {
fixed_len = 0;
}
/* If the maximum length of a variable-length field
@@ -1143,25 +1211,27 @@ rec_get_converted_size_comp_prefix_low(
ut_ad(len <= fixed_len);
if (dict_index_is_spatial(index)) {
- ut_ad(type->mtype == DATA_SYS_CHILD
- || !col->mbmaxlen
- || len >= col->mbminlen
- * fixed_len / col->mbmaxlen);
+ ut_ad(dfield->type.mtype == DATA_SYS_CHILD
+ || !field->col->mbmaxlen
+ || len >= field->col->mbminlen
+ * fixed_len / field->col->mbmaxlen);
} else {
- ut_ad(type->mtype != DATA_SYS_CHILD);
- ut_ad(!col->mbmaxlen
- || len >= col->mbminlen
- * fixed_len / col->mbmaxlen);
+ ut_ad(dfield->type.mtype != DATA_SYS_CHILD);
+
+ ut_ad(field->col->is_dropped()
+ || !field->col->mbmaxlen
+ || len >= field->col->mbminlen
+ * fixed_len / field->col->mbmaxlen);
}
/* dict_index_add_col() should guarantee this */
ut_ad(!field->prefix_len
|| fixed_len == field->prefix_len);
#endif /* UNIV_DEBUG */
- } else if (dfield_is_ext(&fields[i])) {
- ut_ad(DATA_BIG_COL(col));
+ } else if (dfield_is_ext(dfield)) {
+ ut_ad(DATA_BIG_COL(field->col));
extra_size += 2;
- } else if (len < 128 || !DATA_BIG_COL(col)) {
+ } else if (len < 128 || !DATA_BIG_COL(field->col)) {
extra_size++;
} else {
/* For variable-length columns, we look up the
@@ -1197,43 +1267,51 @@ rec_get_converted_size_comp_prefix(
REC_STATUS_ORDINARY, false));
}
-/**********************************************************//**
-Determines the size of a data tuple in ROW_FORMAT=COMPACT.
+/** Determine the size of a record in ROW_FORMAT=COMPACT.
+@param[in] index record descriptor. dict_table_is_comp()
+ is assumed to hold, even if it doesn't
+@param[in] tuple logical record
+@param[out] extra extra size
@return total size */
ulint
rec_get_converted_size_comp(
-/*========================*/
- const dict_index_t* index, /*!< in: record descriptor;
- dict_table_is_comp() is
- assumed to hold, even if
- it does not */
- rec_comp_status_t status, /*!< in: status bits of the record */
- const dfield_t* fields, /*!< in: array of data fields */
- ulint n_fields,/*!< in: number of data fields */
- ulint* extra) /*!< out: extra size */
+ const dict_index_t* index,
+ const dtuple_t* tuple,
+ ulint* extra)
{
- ut_ad(n_fields > 0);
+ ut_ad(tuple->n_fields > 0);
+
+ rec_comp_status_t status = rec_comp_status_t(tuple->info_bits
+ & REC_NEW_STATUS_MASK);
switch (UNIV_EXPECT(status, REC_STATUS_ORDINARY)) {
case REC_STATUS_ORDINARY:
- if (n_fields > index->n_core_fields) {
+ ut_ad(!tuple->is_metadata());
+ if (tuple->n_fields > index->n_core_fields) {
ut_ad(index->is_instant());
- status = REC_STATUS_COLUMNS_ADDED;
+ status = REC_STATUS_INSTANT;
}
/* fall through */
- case REC_STATUS_COLUMNS_ADDED:
- ut_ad(n_fields >= index->n_core_fields);
- ut_ad(n_fields <= index->n_fields);
+ case REC_STATUS_INSTANT:
+ ut_ad(tuple->n_fields >= index->n_core_fields);
+ if (tuple->is_alter_metadata()) {
+ return rec_get_converted_size_comp_prefix_low<true>(
+ index, tuple->fields, tuple->n_fields,
+ extra, status, false);
+ }
+ ut_ad(tuple->n_fields <= index->n_fields);
return rec_get_converted_size_comp_prefix_low(
- index, fields, n_fields, extra, status, false);
+ index, tuple->fields, tuple->n_fields,
+ extra, status, false);
case REC_STATUS_NODE_PTR:
- n_fields--;
- ut_ad(n_fields == dict_index_get_n_unique_in_tree_nonleaf(
- index));
- ut_ad(dfield_get_len(&fields[n_fields]) == REC_NODE_PTR_SIZE);
+ ut_ad(tuple->n_fields - 1
+ == dict_index_get_n_unique_in_tree_nonleaf(index));
+ ut_ad(dfield_get_len(&tuple->fields[tuple->n_fields - 1])
+ == REC_NODE_PTR_SIZE);
return REC_NODE_PTR_SIZE /* child page number */
+ rec_get_converted_size_comp_prefix_low(
- index, fields, n_fields, extra, status, false);
+ index, tuple->fields, tuple->n_fields - 1,
+ extra, status, false);
case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM:
/* not supported */
@@ -1411,33 +1489,30 @@ rec_convert_dtuple_to_rec_old(
}
/** Convert a data tuple into a ROW_FORMAT=COMPACT record.
+@tparam mblob whether the record includes a metadata BLOB
@param[out] rec converted record
@param[in] index index
-@param[in] fields data fields to convert
+@param[in] field data fields to convert
@param[in] n_fields number of data fields
@param[in] status rec_get_status(rec)
@param[in] temp whether to use the format for temporary files
in index creation */
+template<bool mblob = false>
static inline
void
rec_convert_dtuple_to_rec_comp(
rec_t* rec,
const dict_index_t* index,
- const dfield_t* fields,
+ const dfield_t* field,
ulint n_fields,
rec_comp_status_t status,
bool temp)
{
- const dfield_t* field;
- const dtype_t* type;
byte* end;
byte* nulls = temp
? rec - 1 : rec - (REC_N_NEW_EXTRA_BYTES + 1);
byte* UNINIT_VAR(lens);
- ulint len;
- ulint i;
ulint UNINIT_VAR(n_node_ptr_field);
- ulint fixed_len;
ulint null_mask = 1;
ut_ad(n_fields > 0);
@@ -1446,8 +1521,22 @@ rec_convert_dtuple_to_rec_comp(
ut_d(ulint n_null = index->n_nullable);
+ if (mblob) {
+ ut_ad(!temp);
+ ut_ad(index->table->instant);
+ ut_ad(index->is_instant());
+ ut_ad(status == REC_STATUS_INSTANT);
+ ut_ad(n_fields == ulint(index->n_fields) + 1);
+ rec_set_n_add_field(nulls, n_fields - 1
+ - index->n_core_fields);
+ rec_set_heap_no_new(rec, PAGE_HEAP_NO_USER_LOW);
+ rec_set_status(rec, REC_STATUS_INSTANT);
+ n_node_ptr_field = ULINT_UNDEFINED;
+ lens = nulls - UT_BITS_IN_BYTES(index->n_nullable);
+ goto start;
+ }
switch (status) {
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
ut_ad(index->is_instant());
ut_ad(n_fields > index->n_core_fields);
rec_set_n_add_field(nulls, n_fields - 1
@@ -1457,19 +1546,24 @@ rec_convert_dtuple_to_rec_comp(
ut_ad(n_fields <= dict_index_get_n_fields(index));
if (!temp) {
rec_set_heap_no_new(rec, PAGE_HEAP_NO_USER_LOW);
- rec_set_status(rec, n_fields == index->n_core_fields
- ? REC_STATUS_ORDINARY
- : REC_STATUS_COLUMNS_ADDED);
- } if (dict_table_is_comp(index->table)) {
+
+ rec_set_status(
+ rec, n_fields == index->n_core_fields
+ ? REC_STATUS_ORDINARY
+ : REC_STATUS_INSTANT);
+ }
+
+ if (dict_table_is_comp(index->table)) {
/* No need to do adjust fixed_len=0. We only
need to adjust it for ROW_FORMAT=REDUNDANT. */
temp = false;
}
n_node_ptr_field = ULINT_UNDEFINED;
+
lens = nulls - (index->is_instant()
? UT_BITS_IN_BYTES(index->get_n_nullable(
- n_fields))
+ n_fields))
: UT_BITS_IN_BYTES(
unsigned(index->n_nullable)));
break;
@@ -1479,8 +1573,8 @@ rec_convert_dtuple_to_rec_comp(
rec_set_status(rec, status);
ut_ad(n_fields
== dict_index_get_n_unique_in_tree_nonleaf(index) + 1);
- ut_d(n_null = std::min(index->n_core_null_bytes * 8U,
- index->n_nullable));
+ ut_d(n_null = std::min<uint>(index->n_core_null_bytes * 8U,
+ index->n_nullable));
n_node_ptr_field = n_fields - 1;
lens = nulls - index->n_core_null_bytes;
break;
@@ -1490,30 +1584,37 @@ rec_convert_dtuple_to_rec_comp(
return;
}
+start:
end = rec;
/* clear the SQL-null flags */
memset(lens + 1, 0, ulint(nulls - lens));
+ const dfield_t* const fend = field + n_fields;
/* Store the data and the offsets */
-
- for (i = 0; i < n_fields; i++) {
- const dict_field_t* ifield;
- dict_col_t* col = NULL;
-
- field = &fields[i];
-
- type = dfield_get_type(field);
- len = dfield_get_len(field);
-
- if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
- ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
+ for (ulint i = 0; field < fend; i++, field++) {
+ ulint len = dfield_get_len(field);
+
+ if (mblob) {
+ if (i == index->first_user_field()) {
+ ut_ad(len == FIELD_REF_SIZE);
+ ut_ad(dfield_is_ext(field));
+ memcpy(end, dfield_get_data(field), len);
+ end += len;
+ if (++field == fend) {
+ ut_ad(i == index->n_fields);
+ break;
+ }
+ len = dfield_get_len(field);
+ }
+ } else if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
+ ut_ad(field->type.prtype & DATA_NOT_NULL);
ut_ad(len == REC_NODE_PTR_SIZE);
memcpy(end, dfield_get_data(field), len);
end += REC_NODE_PTR_SIZE;
break;
}
- if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ if (!(field->type.prtype & DATA_NOT_NULL)) {
/* nullable field */
ut_ad(n_null--);
@@ -1536,11 +1637,12 @@ rec_convert_dtuple_to_rec_comp(
/* only nullable fields can be null */
ut_ad(!dfield_is_null(field));
- ifield = dict_index_get_nth_field(index, i);
- fixed_len = ifield->fixed_len;
- col = ifield->col;
+ const dict_field_t* ifield
+ = dict_index_get_nth_field(index, i);
+ ulint fixed_len = ifield->fixed_len;
+
if (temp && fixed_len
- && !dict_col_get_fixed_size(col, temp)) {
+ && !dict_col_get_fixed_size(ifield->col, temp)) {
fixed_len = 0;
}
@@ -1552,23 +1654,23 @@ rec_convert_dtuple_to_rec_comp(
it is 128 or more, or when the field is stored externally. */
if (fixed_len) {
ut_ad(len <= fixed_len);
- ut_ad(!col->mbmaxlen
- || len >= col->mbminlen
- * fixed_len / col->mbmaxlen);
+ ut_ad(!ifield->col->mbmaxlen
+ || len >= ifield->col->mbminlen
+ * fixed_len / ifield->col->mbmaxlen);
ut_ad(!dfield_is_ext(field));
} else if (dfield_is_ext(field)) {
- ut_ad(DATA_BIG_COL(col));
+ ut_ad(DATA_BIG_COL(ifield->col));
ut_ad(len <= REC_ANTELOPE_MAX_INDEX_COL_LEN
- + BTR_EXTERN_FIELD_REF_SIZE);
+ + BTR_EXTERN_FIELD_REF_SIZE);
*lens-- = (byte) (len >> 8) | 0xc0;
*lens-- = (byte) len;
} else {
- ut_ad(len <= dtype_get_len(type)
- || DATA_LARGE_MTYPE(dtype_get_mtype(type))
+ ut_ad(len <= field->type.len
+ || DATA_LARGE_MTYPE(field->type.mtype)
|| !strcmp(index->name,
FTS_INDEX_TABLE_IND_NAME));
if (len < 128 || !DATA_BIG_LEN_MTYPE(
- dtype_get_len(type), dtype_get_mtype(type))) {
+ field->type.len, field->type.mtype)) {
*lens-- = (byte) len;
} else {
@@ -1601,24 +1703,37 @@ rec_convert_dtuple_to_rec_new(
ut_ad(!(dtuple->info_bits
& ~(REC_NEW_STATUS_MASK | REC_INFO_DELETED_FLAG
| REC_INFO_MIN_REC_FLAG)));
- rec_comp_status_t status = static_cast<rec_comp_status_t>(
- dtuple->info_bits & REC_NEW_STATUS_MASK);
- if (status == REC_STATUS_ORDINARY
- && dtuple->n_fields > index->n_core_fields) {
- ut_ad(index->is_instant());
- status = REC_STATUS_COLUMNS_ADDED;
- }
ulint extra_size;
- rec_get_converted_size_comp(
- index, status, dtuple->fields, dtuple->n_fields, &extra_size);
- rec_t* rec = buf + extra_size;
+ if (UNIV_UNLIKELY(dtuple->is_alter_metadata())) {
+ ut_ad((dtuple->info_bits & REC_NEW_STATUS_MASK)
+ == REC_STATUS_INSTANT);
+ rec_get_converted_size_comp_prefix_low<true>(
+ index, dtuple->fields, dtuple->n_fields,
+ &extra_size, REC_STATUS_INSTANT, false);
+ buf += extra_size;
+ rec_convert_dtuple_to_rec_comp<true>(
+ buf, index, dtuple->fields, dtuple->n_fields,
+ REC_STATUS_INSTANT, false);
+ } else {
+ rec_get_converted_size_comp(index, dtuple, &extra_size);
+ buf += extra_size;
+ rec_comp_status_t status = rec_comp_status_t(
+ dtuple->info_bits & REC_NEW_STATUS_MASK);
+ if (status == REC_STATUS_ORDINARY
+ && dtuple->n_fields > index->n_core_fields) {
+ ut_ad(index->is_instant());
+ status = REC_STATUS_INSTANT;
+ }
- rec_convert_dtuple_to_rec_comp(
- rec, index, dtuple->fields, dtuple->n_fields, status, false);
- rec_set_info_bits_new(rec, dtuple->info_bits & ~REC_NEW_STATUS_MASK);
- return(rec);
+ rec_convert_dtuple_to_rec_comp(
+ buf, index, dtuple->fields, dtuple->n_fields,
+ status, false);
+ }
+
+ rec_set_info_bits_new(buf, dtuple->info_bits & ~REC_NEW_STATUS_MASK);
+ return buf;
}
/*********************************************************//**
@@ -1657,7 +1772,7 @@ rec_convert_dtuple_to_rec(
@param[in] fields data fields
@param[in] n_fields number of data fields
@param[out] extra record header size
-@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED
+@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT
@return total size, in bytes */
ulint
rec_get_converted_size_temp(
@@ -1677,7 +1792,7 @@ rec_get_converted_size_temp(
@param[in,out] offsets offsets to the fields; in: rec_offs_n_fields(offsets)
@param[in] n_core number of core fields (index->n_core_fields)
@param[in] def_val default values for non-core fields
-@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED */
+@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT */
void
rec_init_offsets_temp(
const rec_t* rec,
@@ -1688,14 +1803,14 @@ rec_init_offsets_temp(
rec_comp_status_t status)
{
ut_ad(status == REC_STATUS_ORDINARY
- || status == REC_STATUS_COLUMNS_ADDED);
+ || status == REC_STATUS_INSTANT);
/* The table may have been converted to plain format
if it was emptied during an ALTER TABLE operation. */
ut_ad(index->n_core_fields == n_core || !index->is_instant());
ut_ad(index->n_core_fields >= n_core);
rec_init_offsets_comp_ordinary(rec, index, offsets, n_core, def_val,
- status == REC_STATUS_COLUMNS_ADDED
- ? REC_LEAF_TEMP_COLUMNS_ADDED
+ status == REC_STATUS_INSTANT
+ ? REC_LEAF_TEMP_INSTANT
: REC_LEAF_TEMP);
}
@@ -1721,7 +1836,7 @@ rec_init_offsets_temp(
@param[in] index clustered or secondary index
@param[in] fields data fields
@param[in] n_fields number of data fields
-@param[in] status REC_STATUS_ORDINARY or REC_STATUS_COLUMNS_ADDED
+@param[in] status REC_STATUS_ORDINARY or REC_STATUS_INSTANT
*/
void
rec_convert_dtuple_to_temp(
@@ -1891,13 +2006,15 @@ rec_copy_prefix_to_buf(
ut_ad(n_fields
<= dict_index_get_n_unique_in_tree_nonleaf(index));
break;
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
/* We would have !index->is_instant() when rolling back
an instant ADD COLUMN operation. */
ut_ad(index->is_instant() || page_rec_is_metadata(rec));
+ ut_ad(n_fields <= index->first_user_field());
nulls++;
const ulint n_rec = ulint(index->n_core_fields) + 1
- + rec_get_n_add_field(nulls);
+ + rec_get_n_add_field(nulls)
+ - rec_is_alter_metadata(rec, true);
instant_omit = ulint(&rec[-REC_N_NEW_EXTRA_BYTES] - nulls);
ut_ad(instant_omit == 1 || instant_omit == 2);
nullf = nulls;
@@ -1986,7 +2103,7 @@ rec_copy_prefix_to_buf(
/* copy the fixed-size header and the record prefix */
memcpy(b - REC_N_NEW_EXTRA_BYTES, rec - REC_N_NEW_EXTRA_BYTES,
prefix_len + REC_N_NEW_EXTRA_BYTES);
- ut_ad(rec_get_status(b) == REC_STATUS_COLUMNS_ADDED);
+ ut_ad(rec_get_status(b) == REC_STATUS_INSTANT);
rec_set_status(b, REC_STATUS_ORDINARY);
return b;
} else {
@@ -2504,8 +2621,6 @@ rec_get_trx_id(
const rec_t* rec,
const dict_index_t* index)
{
- ulint trx_id_col
- = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
const byte* trx_id;
ulint len;
mem_heap_t* heap = NULL;
@@ -2513,15 +2628,10 @@ rec_get_trx_id(
rec_offs_init(offsets_);
offset_t* offsets = offsets_;
- ut_ad(trx_id_col <= MAX_REF_PARTS);
- ut_ad(dict_index_is_clust(index));
- ut_ad(trx_id_col > 0);
- ut_ad(trx_id_col != ULINT_UNDEFINED);
-
offsets = rec_get_offsets(rec, index, offsets, true,
- trx_id_col + 1, &heap);
+ index->db_trx_id() + 1, &heap);
- trx_id = rec_get_nth_field(rec, offsets, trx_id_col, &len);
+ trx_id = rec_get_nth_field(rec, offsets, index->db_trx_id(), &len);
ut_ad(len == DATA_TRX_ID_LEN);
diff --git a/storage/innobase/row/row0ext.cc b/storage/innobase/row/row0ext.cc
index 60864b60ef9..9b07727d058 100644
--- a/storage/innobase/row/row0ext.cc
+++ b/storage/innobase/row/row0ext.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 2006, 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
@@ -29,14 +30,14 @@ Created September 2006 Marko Makela
/** Fills the column prefix cache of an externally stored column.
@param[in,out] ext column prefix cache
@param[in] i index of ext->ext[]
-@param[in] page_size page size
+@param[in] space tablespace
@param[in] dfield data field */
static
void
row_ext_cache_fill(
row_ext_t* ext,
ulint i,
- const page_size_t& page_size,
+ fil_space_t* space,
const dfield_t* dfield)
{
const byte* field = static_cast<const byte*>(
@@ -75,7 +76,8 @@ row_ext_cache_fill(
crashed during the execution of
btr_free_externally_stored_field(). */
ext->len[i] = btr_copy_externally_stored_field_prefix(
- buf, ext->max_len, page_size, field, f_len);
+ buf, ext->max_len, ext->zip_size,
+ field, f_len);
}
}
}
@@ -91,7 +93,7 @@ row_ext_create(
in the InnoDB table object, as reported by
dict_col_get_no(); NOT relative to the records
in the clustered index */
- ulint flags, /*!< in: table->flags */
+ const dict_table_t& table, /*!< in: table */
const dtuple_t* tuple, /*!< in: data tuple containing the field
references of the externally stored
columns; must be indexed by col_no;
@@ -100,36 +102,30 @@ row_ext_create(
to prevent deletion (rollback or purge). */
mem_heap_t* heap) /*!< in: heap where created */
{
- ulint i;
- const page_size_t& page_size = dict_tf_get_page_size(flags);
-
- row_ext_t* ret;
+ if (!table.space) {
+ return NULL;
+ }
ut_ad(n_ext > 0);
- ret = static_cast<row_ext_t*>(
+ row_ext_t* ret = static_cast<row_ext_t*>(
mem_heap_alloc(heap,
(sizeof *ret) + (n_ext - 1) * sizeof ret->len));
ret->n_ext = n_ext;
ret->ext = ext;
- ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags);
- ret->page_size.copy_from(page_size);
+ ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(table.flags);
+ ret->zip_size = dict_tf_get_zip_size(table.flags);
ret->buf = static_cast<byte*>(
mem_heap_alloc(heap, n_ext * ret->max_len));
-#ifdef UNIV_DEBUG
- memset(ret->buf, 0xaa, n_ext * ret->max_len);
- UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len);
-#endif
-
/* Fetch the BLOB prefixes */
- for (i = 0; i < n_ext; i++) {
+ for (ulint i = 0; i < n_ext; i++) {
const dfield_t* dfield;
dfield = dtuple_get_nth_field(tuple, ext[i]);
- row_ext_cache_fill(ret, i, page_size, dfield);
+ row_ext_cache_fill(ret, i, table.space, dfield);
}
return(ret);
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index d439d7563d9..7e3b70bfadb 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -163,22 +163,22 @@ row_merge_create_fts_sort_index(
/** Initialize FTS parallel sort structures.
@param[in] trx transaction
@param[in,out] dup descriptor of FTS index being created
-@param[in] new_table table where indexes are created
+@param[in,out] new_table table where indexes are created
@param[in] opt_doc_id_size whether to use 4 bytes instead of 8 bytes
integer to store Doc ID during sort
-@param[in] old_page_size page size of the old table during alter
+@param[in] old_zip_size page size of the old table during alter
@param[out] psort parallel sort info to be instantiated
@param[out] merge parallel merge info to be instantiated
-@return TRUE if all successful */
-ibool
+@return true if all successful */
+bool
row_fts_psort_info_init(
- trx_t* trx,
- row_merge_dup_t* dup,
- const dict_table_t* new_table,
- ibool opt_doc_id_size,
- const page_size_t old_page_size,
- fts_psort_t** psort,
- fts_psort_t** merge)
+ trx_t* trx,
+ row_merge_dup_t*dup,
+ dict_table_t* new_table,
+ bool opt_doc_id_size,
+ ulint old_zip_size,
+ fts_psort_t** psort,
+ fts_psort_t** merge)
{
ulint i;
ulint j;
@@ -188,6 +188,7 @@ row_fts_psort_info_init(
ulint block_size;
ibool ret = TRUE;
bool encrypted = false;
+ ut_ad(ut_is_2pow(old_zip_size));
block_size = 3 * srv_sort_buf_size;
@@ -210,8 +211,8 @@ row_fts_psort_info_init(
}
common_info->dup = dup;
- common_info->new_table = (dict_table_t*) new_table;
- common_info->old_page_size = old_page_size;
+ common_info->new_table = new_table;
+ common_info->old_zip_size = old_zip_size;
common_info->trx = trx;
common_info->all_info = psort_info;
common_info->sort_event = os_event_create(0);
@@ -805,8 +806,7 @@ DECLARE_THREAD(fts_parallel_tokenization)(
block = psort_info->merge_block;
crypt_block = psort_info->crypt_block;
- const page_size_t old_page_size =
- psort_info->psort_common->old_page_size;
+ const ulint zip_size = psort_info->psort_common->old_zip_size;
row_merge_fts_get_next_doc_item(psort_info, &doc_item);
@@ -836,7 +836,7 @@ loop:
doc.text.f_str =
btr_copy_externally_stored_field(
&doc.text.f_len, data,
- old_page_size, data_len, blob_heap);
+ zip_size, data_len, blob_heap);
} else {
doc.text.f_str = data;
doc.text.f_len = data_len;
diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc
index 54a1f5f492e..5bc69c282e1 100644
--- a/storage/innobase/row/row0import.cc
+++ b/storage/innobase/row/row0import.cc
@@ -50,10 +50,12 @@ Created 2012-02-08 by Sunny Bains.
#include <my_aes.h>
#endif
+using st_::span;
+
/** The size of the buffer to use for IO.
@param n physical page size
@return number of pages */
-#define IO_BUFFER_SIZE(n) ((1024 * 1024) / n)
+#define IO_BUFFER_SIZE(n) ((1024 * 1024) / (n))
/** For gathering stats on records during phase I */
struct row_stats_t {
@@ -115,7 +117,7 @@ struct row_import {
m_hostname(NULL),
m_table_name(NULL),
m_autoinc(0),
- m_page_size(0, 0, false),
+ m_zip_size(0),
m_flags(0),
m_n_cols(0),
m_cols(NULL),
@@ -196,7 +198,8 @@ struct row_import {
ib_uint64_t m_autoinc; /*!< Next autoinc value */
- page_size_t m_page_size; /*!< Tablespace page size */
+ ulint m_zip_size; /*!< ROW_FORMAT=COMPRESSED
+ page size, or 0 */
ulint m_flags; /*!< Table flags */
@@ -356,7 +359,7 @@ public:
@param trx covering transaction */
AbstractCallback(trx_t* trx, ulint space_id)
:
- m_page_size(0, 0, false),
+ m_zip_size(0),
m_trx(trx),
m_space(space_id),
m_xdes(),
@@ -380,7 +383,7 @@ public:
/** @return true if compressed table. */
bool is_compressed_table() const UNIV_NOTHROW
{
- return(get_page_size().is_compressed());
+ return get_zip_size();
}
/** @return the tablespace flags */
@@ -400,7 +403,11 @@ public:
m_filepath = filename;
}
- const page_size_t& get_page_size() const { return m_page_size; }
+ ulint get_zip_size() const { return m_zip_size; }
+ ulint physical_size() const
+ {
+ return m_zip_size ? m_zip_size : srv_page_size;
+ }
const char* filename() const { return m_filepath; }
@@ -439,7 +446,7 @@ protected:
{
ulint offset;
- offset = xdes_calc_descriptor_index(get_page_size(), page_no);
+ offset = xdes_calc_descriptor_index(get_zip_size(), page_no);
return(page + XDES_ARR_OFFSET + XDES_SIZE * offset);
}
@@ -461,15 +468,12 @@ protected:
UT_DELETE_ARRAY(m_xdes);
m_xdes = NULL;
- ulint state;
- const xdes_t* xdesc = page + XDES_ARR_OFFSET;
-
- state = mach_read_ulint(xdesc + XDES_STATE, MLOG_4BYTES);
+ if (mach_read_from_4(XDES_ARR_OFFSET + XDES_STATE + page)
+ != XDES_FREE) {
+ const ulint physical_size = m_zip_size
+ ? m_zip_size : srv_page_size;
- if (state != XDES_FREE) {
-
- m_xdes = UT_NEW_ARRAY_NOKEY(xdes_t,
- m_page_size.physical());
+ m_xdes = UT_NEW_ARRAY_NOKEY(xdes_t, physical_size);
/* Trigger OOM */
DBUG_EXECUTE_IF(
@@ -482,7 +486,7 @@ protected:
return(DB_OUT_OF_MEMORY);
}
- memcpy(m_xdes, page, m_page_size.physical());
+ memcpy(m_xdes, page, physical_size);
}
return(DB_SUCCESS);
@@ -493,7 +497,7 @@ protected:
@return true if the page is marked as free */
bool is_free(ulint page_no) const UNIV_NOTHROW
{
- ut_a(xdes_calc_descriptor_page(get_page_size(), page_no)
+ ut_a(xdes_calc_descriptor_page(get_zip_size(), page_no)
== m_xdes_page_no);
if (m_xdes != 0) {
@@ -508,8 +512,8 @@ protected:
}
protected:
- /** The tablespace page size. */
- page_size_t m_page_size;
+ /** The ROW_FORMAT=COMPRESSED page size, or 0. */
+ ulint m_zip_size;
/** File handle to the tablespace */
pfs_os_file_t m_file;
@@ -556,7 +560,7 @@ AbstractCallback::init(
const page_t* page = block->frame;
m_space_flags = fsp_header_get_flags(page);
- if (!fsp_flags_is_valid(m_space_flags, true)) {
+ if (!fil_space_t::is_valid_flags(m_space_flags, true)) {
ulint cflags = fsp_flags_convert_from_101(m_space_flags);
if (cflags == ULINT_UNDEFINED) {
ib::error() << "Invalid FSP_SPACE_FLAGS="
@@ -568,21 +572,23 @@ AbstractCallback::init(
/* Clear the DATA_DIR flag, which is basically garbage. */
m_space_flags &= ~(1U << FSP_FLAGS_POS_RESERVED);
- m_page_size.copy_from(page_size_t(m_space_flags));
+ m_zip_size = fil_space_t::zip_size(m_space_flags);
+ const ulint logical_size = fil_space_t::logical_size(m_space_flags);
+ const ulint physical_size = fil_space_t::physical_size(m_space_flags);
- if (!is_compressed_table() && !m_page_size.equals_to(univ_page_size)) {
+ if (logical_size != srv_page_size) {
- ib::error() << "Page size " << m_page_size.physical()
+ ib::error() << "Page size " << logical_size
<< " of ibd file is not the same as the server page"
" size " << srv_page_size;
return(DB_CORRUPTION);
- } else if (file_size % m_page_size.physical() != 0) {
+ } else if (file_size & (physical_size - 1)) {
ib::error() << "File size " << file_size << " is not a"
" multiple of the page size "
- << m_page_size.physical();
+ << physical_size;
return(DB_CORRUPTION);
}
@@ -625,12 +631,12 @@ struct FetchIndexRootPages : public AbstractCallback {
m_table(table) UNIV_NOTHROW { }
/** Destructor */
- virtual ~FetchIndexRootPages() UNIV_NOTHROW { }
+ ~FetchIndexRootPages() UNIV_NOTHROW override { }
/** Called for each block as it is read from the file.
@param block block to convert, it is not from the buffer pool.
@retval DB_SUCCESS or error code. */
- dberr_t operator()(buf_block_t* block) UNIV_NOTHROW;
+ dberr_t operator()(buf_block_t* block) UNIV_NOTHROW override;
/** Update the import configuration that will be used to import
the tablespace. */
@@ -694,7 +700,7 @@ FetchIndexRootPages::build_row_import(row_import* cfg) const UNIV_NOTHROW
Indexes::const_iterator end = m_indexes.end();
ut_a(cfg->m_table == m_table);
- cfg->m_page_size.copy_from(m_page_size);
+ cfg->m_zip_size = m_zip_size;
cfg->m_n_indexes = m_indexes.size();
if (cfg->m_n_indexes == 0) {
@@ -803,7 +809,7 @@ public:
rec_offs_init(m_offsets_);
}
- virtual ~PageConverter() UNIV_NOTHROW
+ ~PageConverter() UNIV_NOTHROW override
{
if (m_heap != 0) {
mem_heap_free(m_heap);
@@ -813,7 +819,8 @@ public:
/** Called for each block as it is read from the file.
@param block block to convert, it is not from the buffer pool.
@retval DB_SUCCESS or error code. */
- dberr_t operator()(buf_block_t* block) UNIV_NOTHROW;
+ dberr_t operator()(buf_block_t* block) UNIV_NOTHROW override;
+
private:
/** Update the page, set the space id, max trx id and index id.
@param block block read from file
@@ -1481,7 +1488,7 @@ IndexPurge::open() UNIV_NOTHROW
btr_pcur_open_at_index_side(
true, m_index, BTR_MODIFY_LEAF, &m_pcur, true, 0, &m_mtr);
btr_pcur_move_to_next_user_rec(&m_pcur, &m_mtr);
- if (rec_is_metadata(btr_pcur_get_rec(&m_pcur), m_index)) {
+ if (rec_is_metadata(btr_pcur_get_rec(&m_pcur), *m_index)) {
ut_ad(btr_pcur_is_on_user_rec(&m_pcur));
/* Skip the metadata pseudo-record. */
} else {
@@ -1560,7 +1567,7 @@ IndexPurge::next() UNIV_NOTHROW
dict_index_t* index = m_pcur.btr_cur.index;
buf_block_t* next_block = btr_block_get(
page_id_t(block->page.id.space(), next_page),
- block->page.size, BTR_MODIFY_LEAF, index,
+ block->zip_size(), BTR_MODIFY_LEAF, index,
&m_mtr);
if (UNIV_UNLIKELY(!next_block
@@ -1924,6 +1931,23 @@ PageConverter::update_index_page(
return(DB_CORRUPTION);
}
+ if (index->n_core_fields > index->n_fields) {
+ /* Some columns have been dropped.
+ Refuse to IMPORT TABLESPACE for now.
+
+ NOTE: This is not an accurate check.
+ Columns could have been both
+ added and dropped instantly.
+ For an accurate check, we must read
+ the metadata BLOB page pointed to
+ by the leftmost leaf page.
+
+ But we would have to read
+ those pages in a special way,
+ bypassing the buffer pool! */
+ return DB_UNSUPPORTED;
+ }
+
/* Provisionally set all instantly
added columns to be DEFAULT NULL. */
for (unsigned i = index->n_core_fields;
@@ -2085,27 +2109,30 @@ dberr_t PageConverter::operator()(buf_block_t* block) UNIV_NOTHROW
/* If we already had an old page with matching number
in the buffer pool, evict it now, because
we no longer evict the pages on DISCARD TABLESPACE. */
- buf_page_get_gen(block->page.id, get_page_size(),
+ buf_page_get_gen(block->page.id, get_zip_size(),
RW_NO_LATCH, NULL, BUF_EVICT_IF_IN_POOL,
__FILE__, __LINE__, NULL, NULL);
ulint page_type;
- dberr_t err = update_page(block, page_type);
- if (err != DB_SUCCESS) return err;
+ if (dberr_t err = update_page(block, page_type)) {
+ return err;
+ }
+
+ const bool full_crc32 = fil_space_t::full_crc32(get_space_flags());
if (!block->page.zip.data) {
buf_flush_init_for_writing(
- NULL, block->frame, NULL, m_current_lsn);
+ NULL, block->frame, NULL, m_current_lsn, full_crc32);
} else if (fil_page_type_is_index(page_type)) {
buf_flush_init_for_writing(
NULL, block->page.zip.data, &block->page.zip,
- m_current_lsn);
+ m_current_lsn, full_crc32);
} else {
/* Calculate and update the checksum of non-index
pages for ROW_FORMAT=COMPRESSED tables. */
buf_flush_update_zip_checksum(
- block->page.zip.data, get_page_size().physical(),
+ block->page.zip.data, block->zip_size(),
m_current_lsn);
}
@@ -2329,17 +2356,15 @@ row_import_adjust_root_pages_of_secondary_indexes(
}
/*****************************************************************//**
-Ensure that dict_sys->row_id exceeds SELECT MAX(DB_ROW_ID).
-@return error code */
-static MY_ATTRIBUTE((nonnull, warn_unused_result))
-dberr_t
+Ensure that dict_sys.row_id exceeds SELECT MAX(DB_ROW_ID). */
+MY_ATTRIBUTE((nonnull)) static
+void
row_import_set_sys_max_row_id(
/*==========================*/
row_prebuilt_t* prebuilt, /*!< in/out: prebuilt from
handler */
const dict_table_t* table) /*!< in: table to import */
{
- dberr_t err;
const rec_t* rec;
mtr_t mtr;
btr_pcur_t pcur;
@@ -2347,7 +2372,8 @@ row_import_set_sys_max_row_id(
dict_index_t* index;
index = dict_table_get_first_index(table);
- ut_a(dict_index_is_clust(index));
+ ut_ad(index->is_primary());
+ ut_ad(dict_index_is_auto_gen_clust(index));
mtr_start(&mtr);
@@ -2368,71 +2394,29 @@ row_import_set_sys_max_row_id(
/* Check for empty table. */
if (page_rec_is_infimum(rec)) {
/* The table is empty. */
- err = DB_SUCCESS;
- } else if (rec_is_metadata(rec, index)) {
+ } else if (rec_is_metadata(rec, *index)) {
/* The clustered index contains the metadata record only,
that is, the table is empty. */
- err = DB_SUCCESS;
} else {
- ulint len;
- const byte* field;
- mem_heap_t* heap = NULL;
- offset_t offsets_[1 + REC_OFFS_HEADER_SIZE];
- offset_t* offsets;
-
- rec_offs_init(offsets_);
-
- offsets = rec_get_offsets(
- rec, index, offsets_, true, ULINT_UNDEFINED, &heap);
-
- field = rec_get_nth_field(
- rec, offsets,
- dict_index_get_sys_col_pos(index, DATA_ROW_ID),
- &len);
-
- if (len == DATA_ROW_ID_LEN) {
- row_id = mach_read_from_6(field);
- err = DB_SUCCESS;
- } else {
- err = DB_CORRUPTION;
- }
-
- if (heap != NULL) {
- mem_heap_free(heap);
- }
+ row_id = mach_read_from_6(rec);
}
btr_pcur_close(&pcur);
mtr_commit(&mtr);
- DBUG_EXECUTE_IF("ib_import_set_max_rowid_failure",
- err = DB_CORRUPTION;);
-
- if (err != DB_SUCCESS) {
- ib_errf(prebuilt->trx->mysql_thd,
- IB_LOG_LEVEL_WARN,
- ER_INNODB_INDEX_CORRUPT,
- "Index `%s` corruption detected, invalid DB_ROW_ID"
- " in index.", index->name());
-
- return(err);
-
- } else if (row_id > 0) {
-
+ if (row_id) {
/* Update the system row id if the imported index row id is
greater than the max system row id. */
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
- if (row_id >= dict_sys->row_id) {
- dict_sys->row_id = row_id + 1;
+ if (row_id >= dict_sys.row_id) {
+ dict_sys.row_id = row_id + 1;
dict_hdr_flush_row_id();
}
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
}
-
- return(DB_SUCCESS);
}
/*****************************************************************//**
@@ -3052,10 +3036,7 @@ row_import_read_v1(
cfg->m_flags = mach_read_from_4(ptr);
ptr += sizeof(ib_uint32_t);
- cfg->m_page_size.copy_from(dict_tf_get_page_size(cfg->m_flags));
-
- ut_a(logical_page_size == cfg->m_page_size.logical());
-
+ cfg->m_zip_size = dict_tf_get_zip_size(cfg->m_flags);
cfg->m_n_cols = mach_read_from_4(ptr);
if (!dict_tf_is_valid(cfg->m_flags)) {
@@ -3397,7 +3378,7 @@ fil_iterate(
AbstractCallback& callback)
{
os_offset_t offset;
- const ulint size = callback.get_page_size().physical();
+ const ulint size = callback.physical_size();
ulint n_bytes = iter.n_io_buffers * size;
const ulint buf_size = srv_page_size
@@ -3414,6 +3395,10 @@ fil_iterate(
return DB_OUT_OF_MEMORY;
}
+ ulint actual_space_id = 0;
+ const bool full_crc32 = fil_space_t::full_crc32(
+ callback.get_space_flags());
+
/* TODO: For ROW_FORMAT=COMPRESSED tables we do a lot of useless
copying for non-index pages. Unfortunately, it is
required by buf_zip_decompress() */
@@ -3471,15 +3456,10 @@ fil_iterate(
byte* src = readptr + i * size;
const ulint page_no = page_get_page_no(src);
if (!page_no && block->page.id.page_no()) {
- const ulint* b = reinterpret_cast<const ulint*>
- (src);
- const ulint* const e = b + size / sizeof *b;
- do {
- if (*b++) {
- goto page_corrupted;
- }
- } while (b != e);
-
+ if (!buf_is_zeroes(span<const byte>(src,
+ size))) {
+ goto page_corrupted;
+ }
/* Proceed to the next page,
because this one is all zero. */
continue;
@@ -3495,9 +3475,19 @@ page_corrupted:
goto func_exit;
}
- const bool page_compressed
- = fil_page_is_compressed_encrypted(src)
- || fil_page_is_compressed(src);
+ if (block->page.id.page_no() == 0) {
+ actual_space_id = mach_read_from_4(
+ src + FIL_PAGE_SPACE_ID);
+ }
+
+ const bool page_compressed =
+ (full_crc32
+ && fil_space_t::is_compressed(
+ callback.get_space_flags())
+ && buf_page_is_compressed(
+ src, callback.get_space_flags()))
+ || (fil_page_is_compressed_encrypted(src)
+ || fil_page_is_compressed(src));
if (page_compressed && block->page.zip.data) {
goto page_corrupted;
@@ -3506,11 +3496,11 @@ page_corrupted:
bool decrypted = false;
byte* dst = io_buffer + i * size;
bool frame_changed = false;
+ uint key_version = buf_page_get_key_version(
+ src, callback.get_space_flags());
if (!encrypted) {
- } else if (!mach_read_from_4(
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
- + src)) {
+ } else if (!key_version) {
not_encrypted:
if (block->page.id.page_no() == 0
&& block->page.zip.data) {
@@ -3525,14 +3515,17 @@ not_encrypted:
memcpy(dst, src, size);
}
} else {
- if (!fil_space_verify_crypt_checksum(
- src, callback.get_page_size())) {
+ if (!buf_page_verify_crypt_checksum(
+ src, callback.get_space_flags())) {
goto page_corrupted;
}
decrypted = fil_space_decrypt(
+ actual_space_id,
iter.crypt_data, dst,
- callback.get_page_size(), src, &err);
+ callback.physical_size(),
+ callback.get_space_flags(),
+ src, &err);
if (err != DB_SUCCESS) {
goto func_exit;
@@ -3545,21 +3538,27 @@ not_encrypted:
updated = true;
}
+ /* For full_crc32 format, skip checksum check
+ after decryption. */
+ bool skip_checksum_check = full_crc32 && encrypted;
+
/* If the original page is page_compressed, we need
to decompress it before adjusting further. */
if (page_compressed) {
ulint compress_length = fil_page_decompress(
- page_compress_buf, dst);
+ page_compress_buf, dst,
+ callback.get_space_flags());
ut_ad(compress_length != srv_page_size);
if (compress_length == 0) {
goto page_corrupted;
}
updated = true;
- } else if (buf_page_is_corrupted(
+ } else if (!skip_checksum_check
+ && buf_page_is_corrupted(
false,
encrypted && !frame_changed
? dst : src,
- callback.get_page_size(), NULL)) {
+ callback.get_space_flags())) {
goto page_corrupted;
}
@@ -3622,7 +3621,7 @@ not_encrypted:
if (ulint len = fil_page_compress(
src,
page_compress_buf,
- 0,/* FIXME: compression level */
+ callback.get_space_flags(),
512,/* FIXME: proper block size */
encrypted)) {
/* FIXME: remove memcpy() */
@@ -3635,12 +3634,14 @@ not_encrypted:
/* Encrypt the page if encryption was used. */
if (encrypted && decrypted) {
byte *dest = writeptr + i * size;
+
byte* tmp = fil_encrypt_buf(
iter.crypt_data,
block->page.id.space(),
block->page.id.page_no(),
mach_read_from_8(src + FIL_PAGE_LSN),
- src, callback.get_page_size(), dest);
+ src, block->zip_size(), dest,
+ full_crc32);
if (tmp == src) {
/* TODO: remove unnecessary memcpy's */
@@ -3650,6 +3651,26 @@ not_encrypted:
updated = true;
}
+
+ /* Write checksum for the compressed full crc32 page.*/
+ if (full_crc32 && page_compressed) {
+ ut_ad(updated);
+ byte* dest = writeptr + i * size;
+ ut_d(bool comp = false);
+ ut_d(bool corrupt = false);
+ ulint size = buf_page_full_crc32_size(
+ dest,
+#ifdef UNIV_DEBUG
+ &comp, &corrupt
+#else
+ NULL, NULL
+#endif
+ );
+ ut_ad(!comp == (size == srv_page_size));
+ ut_ad(!corrupt);
+ mach_write_to_4(dest + (size - 4),
+ ut_crc32(dest, size - 4));
+ }
}
/* A page was updated in the set, write back to disk. */
@@ -3765,10 +3786,8 @@ fil_tablespace_iterate(
if (err == DB_SUCCESS) {
block->page.id = page_id_t(callback.get_space_id(), 0);
- block->page.size.copy_from(callback.get_page_size());
- if (block->page.size.is_compressed()) {
- page_zip_set_size(&block->page.zip,
- callback.get_page_size().physical());
+ if (ulint zip_size = callback.get_zip_size()) {
+ page_zip_set_size(&block->page.zip, zip_size);
/* ROW_FORMAT=COMPRESSED is not optimised for block IO
for now. We do the IMPORT page by page. */
n_io_buffers = 1;
@@ -3778,7 +3797,7 @@ fil_tablespace_iterate(
/* read (optional) crypt data */
iter.crypt_data = fil_space_read_crypt_data(
- callback.get_page_size(), page);
+ callback.get_zip_size(), page);
/* If tablespace is encrypted, it needs extra buffers */
if (iter.crypt_data && n_io_buffers > 1) {
@@ -3919,7 +3938,7 @@ row_import_for_mysql(
/* Prevent DDL operations while we are checking. */
- rw_lock_s_lock_func(&dict_operation_lock, 0, __FILE__, __LINE__);
+ rw_lock_s_lock(&dict_sys.latch);
row_import cfg;
@@ -3944,14 +3963,14 @@ row_import_for_mysql(
autoinc = cfg.m_autoinc;
}
- rw_lock_s_unlock_gen(&dict_operation_lock, 0);
+ rw_lock_s_unlock(&dict_sys.latch);
DBUG_EXECUTE_IF("ib_import_set_index_root_failure",
err = DB_TOO_MANY_CONCURRENT_TRXS;);
} else if (cfg.m_missing) {
- rw_lock_s_unlock_gen(&dict_operation_lock, 0);
+ rw_lock_s_unlock(&dict_sys.latch);
/* We don't have a schema file, we will have to discover
the index root pages from the .ibd file and skip the schema
@@ -3959,12 +3978,12 @@ row_import_for_mysql(
ut_a(err == DB_FAIL);
- cfg.m_page_size.copy_from(univ_page_size);
+ cfg.m_zip_size = 0;
FetchIndexRootPages fetchIndexRootPages(table, trx);
err = fil_tablespace_iterate(
- table, IO_BUFFER_SIZE(cfg.m_page_size.physical()),
+ table, IO_BUFFER_SIZE(srv_page_size),
fetchIndexRootPages);
if (err == DB_SUCCESS) {
@@ -3983,7 +4002,7 @@ row_import_for_mysql(
space_flags = fetchIndexRootPages.get_space_flags();
} else {
- rw_lock_s_unlock_gen(&dict_operation_lock, 0);
+ rw_lock_s_unlock(&dict_sys.latch);
}
if (err != DB_SUCCESS) {
@@ -4002,7 +4021,8 @@ row_import_for_mysql(
/* Set the IO buffer size in pages. */
err = fil_tablespace_iterate(
- table, IO_BUFFER_SIZE(cfg.m_page_size.physical()), converter);
+ table, IO_BUFFER_SIZE(cfg.m_zip_size ? cfg.m_zip_size
+ : srv_page_size), converter);
DBUG_EXECUTE_IF("ib_import_reset_space_and_lsn_failure",
err = DB_TOO_MANY_CONCURRENT_TRXS;);
@@ -4073,7 +4093,7 @@ row_import_for_mysql(
/* Open the tablespace so that we can access via the buffer pool.
We set the 2nd param (fix_dict = true) here because we already
- have an x-lock on dict_operation_lock and dict_sys->mutex.
+ have an x-lock on dict_sys.latch and dict_sys.mutex.
The tablespace is initially opened as a temporary one, because
we will not be writing any redo log for it before we have invoked
fil_space_t::set_imported() to declare it a persistent tablespace. */
@@ -4168,12 +4188,7 @@ row_import_for_mysql(
any DB_ROW_ID stored in the table. */
if (prebuilt->clust_index_was_generated) {
-
- err = row_import_set_sys_max_row_id(prebuilt, table);
-
- if (err != DB_SUCCESS) {
- return(row_import_error(prebuilt, trx, err));
- }
+ row_import_set_sys_max_row_id(prebuilt, table);
}
ib::info() << "Phase III - Flush changes to disk";
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index f0e14790d8d..1bde1199906 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -44,11 +44,8 @@ Created 4/20/1996 Heikki Tuuri
#include "buf0lru.h"
#include "fts0fts.h"
#include "fts0types.h"
-
#ifdef WITH_WSREP
-#include <mysql/service_wsrep.h>
-#include "../../../wsrep/wsrep_api.h"
-#include "wsrep_mysqld_c.h"
+#include "wsrep_mysqld.h"
#endif /* WITH_WSREP */
/*************************************************************************
@@ -1015,11 +1012,11 @@ func_exit:
#ifdef WITH_WSREP
dberr_t wsrep_append_foreign_key(trx_t *trx,
- dict_foreign_t* foreign,
- const rec_t* clust_rec,
- dict_index_t* clust_index,
- ibool referenced,
- enum wsrep_key_type key_type);
+ dict_foreign_t* foreign,
+ const rec_t* clust_rec,
+ dict_index_t* clust_index,
+ ibool referenced,
+ Wsrep_service_key_type key_type);
#endif /* WITH_WSREP */
/*********************************************************************//**
@@ -1242,8 +1239,10 @@ row_ins_foreign_check_on_constraint(
}
if (table->fts) {
- doc_id = fts_get_doc_id_from_rec(table, clust_rec,
- clust_index, tmp_heap);
+ doc_id = fts_get_doc_id_from_rec(
+ clust_rec, clust_index,
+ rec_get_offsets(clust_rec, clust_index, NULL, true,
+ ULINT_UNDEFINED, &tmp_heap));
}
if (node->is_delete
@@ -1399,8 +1398,9 @@ row_ins_foreign_check_on_constraint(
cascade->state = UPD_NODE_UPDATE_CLUSTERED;
#ifdef WITH_WSREP
- err = wsrep_append_foreign_key(trx, foreign, cascade->pcur->old_rec, clust_index,
- FALSE, WSREP_KEY_EXCLUSIVE);
+ err = wsrep_append_foreign_key(trx, foreign, cascade->pcur->old_rec,
+ clust_index,
+ FALSE, WSREP_SERVICE_KEY_EXCLUSIVE);
if (err != DB_SUCCESS) {
fprintf(stderr,
"WSREP: foreign key append failed: %d\n", err);
@@ -1512,7 +1512,7 @@ row_ins_set_exclusive_rec_lock(
/***************************************************************//**
Checks if foreign key constraint fails for an index entry. Sets shared locks
which lock either the success or the failure of the constraint. NOTE that
-the caller must have a shared latch on dict_operation_lock.
+the caller must have a shared latch on dict_sys.latch.
@return DB_SUCCESS, DB_NO_REFERENCED_ROW, or DB_ROW_IS_REFERENCED */
dberr_t
row_ins_check_foreign_constraint(
@@ -1553,7 +1553,7 @@ row_ins_check_foreign_constraint(
upd_node= NULL;
#endif /* WITH_WSREP */
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_S));
+ ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S));
err = DB_SUCCESS;
@@ -1792,32 +1792,16 @@ row_ins_check_foreign_constraint(
if (check_ref) {
err = DB_SUCCESS;
#ifdef WITH_WSREP
- if (!wsrep_on(trx->mysql_thd)) {
- goto end_scan;
- }
- enum wsrep_key_type key_type;
- if (upd_node != NULL) {
- key_type = WSREP_KEY_SHARED;
- } else {
- switch (wsrep_certification_rules) {
- default:
- case WSREP_CERTIFICATION_RULES_STRICT:
- key_type = WSREP_KEY_EXCLUSIVE;
- break;
- case WSREP_CERTIFICATION_RULES_OPTIMIZED:
- key_type = WSREP_KEY_SEMI;
- break;
- }
- }
-
err = wsrep_append_foreign_key(
- trx,
+ thr_get_trx(thr),
foreign,
rec,
check_index,
check_ref,
- key_type);
-
+ (upd_node != NULL
+ && wsrep_protocol_version < 4)
+ ? WSREP_SERVICE_KEY_SHARED
+ : WSREP_SERVICE_KEY_REFERENCE);
if (err != DB_SUCCESS) {
fprintf(stderr,
"WSREP: foreign key append failed: %d\n", err);
@@ -2000,7 +1984,7 @@ row_ins_check_foreign_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
- we will release dict_operation_lock temporarily!
+ we will release dict_sys.latch temporarily!
But the counter on the table protects the referenced
table from being dropped while the check is running. */
@@ -2600,25 +2584,32 @@ row_ins_clust_index_entry_low(
} else {
index->set_modified(mtr);
- if (mode == BTR_MODIFY_LEAF
- && dict_index_is_online_ddl(index)) {
- mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
- mtr_s_lock_index(index, &mtr);
- }
+ if (UNIV_UNLIKELY(entry->is_metadata())) {
+ ut_ad(index->is_instant());
+ ut_ad(!dict_index_is_online_ddl(index));
+ ut_ad(mode == BTR_MODIFY_TREE);
+ } else {
+ if (mode == BTR_MODIFY_LEAF
+ && dict_index_is_online_ddl(index)) {
+ mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
+ mtr_s_lock_index(index, &mtr);
+ }
- if (unsigned ai = index->table->persistent_autoinc) {
- /* Prepare to persist the AUTO_INCREMENT value
- from the index entry to PAGE_ROOT_AUTO_INC. */
- const dfield_t* dfield = dtuple_get_nth_field(
- entry, ai - 1);
- auto_inc = dfield_is_null(dfield)
- ? 0
- : row_parse_int(static_cast<const byte*>(
+ if (unsigned ai = index->table->persistent_autoinc) {
+ /* Prepare to persist the AUTO_INCREMENT value
+ from the index entry to PAGE_ROOT_AUTO_INC. */
+ const dfield_t* dfield = dtuple_get_nth_field(
+ entry, ai - 1);
+ if (!dfield_is_null(dfield)) {
+ auto_inc = row_parse_int(
+ static_cast<const byte*>(
dfield->data),
dfield->len,
dfield->type.mtype,
dfield->type.prtype
& DATA_UNSIGNED);
+ }
+ }
}
}
@@ -2648,35 +2639,25 @@ row_ins_clust_index_entry_low(
#endif /* UNIV_DEBUG */
if (UNIV_UNLIKELY(entry->info_bits != 0)) {
- ut_ad(entry->info_bits == REC_INFO_METADATA);
+ ut_ad(entry->is_metadata());
ut_ad(flags == BTR_NO_LOCKING_FLAG);
ut_ad(index->is_instant());
ut_ad(!dict_index_is_online_ddl(index));
const rec_t* rec = btr_cur_get_rec(cursor);
- switch (rec_get_info_bits(rec, page_rec_is_comp(rec))
- & (REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG)) {
- case REC_INFO_MIN_REC_FLAG:
+ if (rec_get_info_bits(rec, page_rec_is_comp(rec))
+ & REC_INFO_MIN_REC_FLAG) {
thr_get_trx(thr)->error_info = index;
err = DB_DUPLICATE_KEY;
goto err_exit;
- case REC_INFO_MIN_REC_FLAG | REC_INFO_DELETED_FLAG:
- /* The metadata record never carries the delete-mark
- in MariaDB Server 10.3.
- If a table loses its 'instantness', it happens
- by the rollback of this first-time insert, or
- by a call to btr_page_empty() on the root page
- when the table becomes empty. */
- err = DB_CORRUPTION;
- goto err_exit;
- default:
- ut_ad(!row_ins_must_modify_rec(cursor));
- goto do_insert;
}
+
+ ut_ad(!row_ins_must_modify_rec(cursor));
+ goto do_insert;
}
- if (rec_is_metadata(btr_cur_get_rec(cursor), index)) {
+ if (rec_is_metadata(btr_cur_get_rec(cursor), *index)) {
goto do_insert;
}
@@ -3036,9 +3017,9 @@ row_ins_sec_index_entry_low(
if (!index->is_committed()) {
ut_ad(!thr_get_trx(thr)
->dict_operation_lock_mode);
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
dict_set_corrupted_index_cache_only(index);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
/* Do not return any error to the
caller. The duplicate will be reported
by ALTER TABLE or CREATE UNIQUE INDEX.
@@ -3181,9 +3162,27 @@ row_ins_clust_index_entry(
n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0;
+#ifdef WITH_WSREP
+ const bool skip_locking
+ = wsrep_thd_skip_locking(thr_get_trx(thr)->mysql_thd);
+ ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
+ : (index->table->is_temporary() || skip_locking)
+ ? BTR_NO_LOCKING_FLAG : 0;
+#ifdef UNIV_DEBUG
+ if (skip_locking && strcmp(wsrep_get_sr_table_name(),
+ index->table->name.m_name)) {
+ WSREP_ERROR("Record locking is disabled in this thread, "
+ "but the table being modified is not "
+ "`%s`: `%s`.", wsrep_get_sr_table_name(),
+ index->table->name.m_name);
+ ut_error;
+ }
+#endif /* UNIV_DEBUG */
+#else
ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK
: index->table->is_temporary()
? BTR_NO_LOCKING_FLAG : 0;
+#endif /* WITH_WSREP */
const ulint orig_n_fields = entry->n_fields;
/* Try first optimistic descent to the B-tree */
@@ -3404,6 +3403,24 @@ row_ins_index_entry_set_vals(
ut_ad(dtuple_get_n_fields(row)
== dict_table_get_n_cols(index->table));
row_field = dtuple_get_nth_v_field(row, v_col->v_pos);
+ } else if (col->is_dropped()) {
+ ut_ad(index->is_primary());
+
+ if (!(col->prtype & DATA_NOT_NULL)) {
+ field->data = NULL;
+ field->len = UNIV_SQL_NULL;
+ field->type.prtype = DATA_BINARY_TYPE;
+ } else {
+ ut_ad(col->len <= sizeof field_ref_zero);
+ ut_ad(ind_field->fixed_len <= col->len);
+ dfield_set_data(field, field_ref_zero,
+ ind_field->fixed_len);
+ field->type.prtype = DATA_NOT_NULL;
+ }
+
+ field->type.mtype = col->len
+ ? DATA_FIXBINARY : DATA_BINARY;
+ continue;
} else {
row_field = dtuple_get_nth_field(
row, ind_field->col->ind);
@@ -3413,7 +3430,7 @@ row_ins_index_entry_set_vals(
/* Check column prefix indexes */
if (ind_field != NULL && ind_field->prefix_len > 0
- && dfield_get_len(row_field) != UNIV_SQL_NULL) {
+ && len != UNIV_SQL_NULL) {
const dict_col_t* col
= dict_field_get_col(ind_field);
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index f6d0657ad5a..0fd3f840fcf 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -42,7 +42,7 @@ Created 2011-05-26 Marko Makela
#include <algorithm>
#include <map>
-ulint onlineddl_rowlog_rows;
+Atomic_counter<ulint> onlineddl_rowlog_rows;
ulint onlineddl_rowlog_pct_used;
ulint onlineddl_pct_progress;
@@ -293,7 +293,8 @@ row_log_block_allocate(
);
log_buf.block = ut_allocator<byte>(mem_key_row_log_buf)
- .allocate_large(srv_sort_buf_size, &log_buf.block_pfx);
+ .allocate_large(srv_sort_buf_size,
+ &log_buf.block_pfx);
if (log_buf.block == NULL) {
DBUG_RETURN(false);
@@ -313,7 +314,8 @@ row_log_block_free(
DBUG_ENTER("row_log_block_free");
if (log_buf.block != NULL) {
ut_allocator<byte>(mem_key_row_log_buf).deallocate_large(
- log_buf.block, &log_buf.block_pfx, log_buf.size);
+ log_buf.block, &log_buf.block_pfx,
+ log_buf.size);
log_buf.block = NULL;
}
DBUG_VOID_RETURN;
@@ -606,7 +608,7 @@ write_failed:
err_exit:
mutex_exit(&log->mutex);
- my_atomic_addlint(&onlineddl_rowlog_rows, 1);
+ onlineddl_rowlog_rows++;
/* 10000 means 100.00%, 4525 means 45.25% */
onlineddl_rowlog_pct_used = static_cast<ulint>((log->tail.total * 10000) / srv_online_max_size);
}
@@ -684,9 +686,9 @@ row_log_table_delete(
fields of the record. */
heap = mem_heap_create(
DATA_TRX_ID_LEN
- + DTUPLE_EST_ALLOC(unsigned(new_index->n_uniq) + 2));
- old_pk = tuple = dtuple_create(
- heap, unsigned(new_index->n_uniq) + 2);
+ + DTUPLE_EST_ALLOC(new_index->first_user_field()));
+ old_pk = tuple = dtuple_create(heap,
+ new_index->first_user_field());
dict_index_copy_types(tuple, new_index, tuple->n_fields);
dtuple_set_n_fields_cmp(tuple, new_index->n_uniq);
@@ -851,7 +853,7 @@ row_log_table_low_redundant(
const bool is_instant = index->online_log->is_instant(index);
rec_comp_status_t status = is_instant
- ? REC_STATUS_COLUMNS_ADDED : REC_STATUS_ORDINARY;
+ ? REC_STATUS_INSTANT : REC_STATUS_ORDINARY;
size = rec_get_converted_size_temp(
index, tuple->fields, tuple->n_fields, &extra_size, status);
@@ -905,7 +907,7 @@ row_log_table_low_redundant(
*b++ = static_cast<byte>(extra_size);
}
- if (status == REC_STATUS_COLUMNS_ADDED) {
+ if (status == REC_STATUS_INSTANT) {
ut_ad(is_instant);
if (n_fields <= index->online_log->n_core_fields) {
status = REC_STATUS_ORDINARY;
@@ -971,7 +973,7 @@ row_log_table_low(
ut_ad(!"wrong page type");
}
#endif /* UNIV_DEBUG */
- ut_ad(!rec_is_metadata(rec, index));
+ ut_ad(!rec_is_metadata(rec, *index));
ut_ad(page_rec_is_leaf(rec));
ut_ad(!page_is_comp(page_align(rec)) == !rec_offs_comp(offsets));
/* old_pk=row_log_table_get_pk() [not needed in INSERT] is a prefix
@@ -994,7 +996,7 @@ row_log_table_low(
ut_ad(page_is_comp(page_align(rec)));
ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY
- || rec_get_status(rec) == REC_STATUS_COLUMNS_ADDED);
+ || rec_get_status(rec) == REC_STATUS_INSTANT);
const ulint omit_size = REC_N_NEW_EXTRA_BYTES;
@@ -1068,7 +1070,7 @@ row_log_table_low(
if (is_instant) {
*b++ = fake_extra_size
- ? REC_STATUS_COLUMNS_ADDED
+ ? REC_STATUS_INSTANT
: rec_get_status(rec);
} else {
ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
@@ -1135,13 +1137,14 @@ row_log_table_get_pk_old_col(
/** Maps an old table column of a PRIMARY KEY column.
@param[in] ifield clustered index field in the new table (after
ALTER TABLE)
+@param[in] index the clustered index of ifield
@param[in,out] dfield clustered index tuple field in the new table
@param[in,out] heap memory heap for allocating dfield contents
@param[in] rec clustered index leaf page record in the old
table
@param[in] offsets rec_get_offsets(rec)
@param[in] i rec field corresponding to col
-@param[in] page_size page size of the old table
+@param[in] zip_size ROW_FORMAT=COMPRESSED size of the old table
@param[in] max_len maximum length of dfield
@param[in] log row log for the table
@retval DB_INVALID_NULL if a NULL value is encountered
@@ -1150,12 +1153,13 @@ static
dberr_t
row_log_table_get_pk_col(
const dict_field_t* ifield,
+ const dict_index_t* index,
dfield_t* dfield,
mem_heap_t* heap,
const rec_t* rec,
const offset_t* offsets,
ulint i,
- const page_size_t& page_size,
+ ulint zip_size,
ulint max_len,
const row_log_t* log)
{
@@ -1173,14 +1177,19 @@ row_log_table_get_pk_col(
return(DB_INVALID_NULL);
}
- ulint n_default_cols = i - DATA_N_SYS_COLS;
+ ulint new_i = dict_col_get_clust_pos(ifield->col, index);
+
+ if (UNIV_UNLIKELY(new_i >= log->defaults->n_fields)) {
+ ut_ad(0);
+ return DB_INVALID_NULL;
+ }
field = static_cast<const byte*>(
- log->defaults->fields[n_default_cols].data);
+ log->defaults->fields[new_i].data);
if (!field) {
return(DB_INVALID_NULL);
}
- len = log->defaults->fields[i - DATA_N_SYS_COLS].len;
+ len = log->defaults->fields[new_i].len;
}
if (rec_offs_nth_extern(offsets, i)) {
@@ -1198,7 +1207,7 @@ row_log_table_get_pk_col(
mem_heap_alloc(heap, field_len));
len = btr_copy_externally_stored_field_prefix(
- blob_field, field_len, page_size, field, len);
+ blob_field, field_len, zip_size, field, len);
if (len >= max_len + 1) {
return(DB_TOO_BIG_INDEX_COL);
}
@@ -1249,19 +1258,16 @@ row_log_table_get_pk(
ulint trx_id_offs = index->trx_id_offset;
if (!trx_id_offs) {
- ulint pos = dict_index_get_sys_col_pos(
- index, DATA_TRX_ID);
ulint len;
- ut_ad(pos > 0);
if (!offsets) {
offsets = rec_get_offsets(
rec, index, NULL, true,
- pos + 1, heap);
+ index->db_trx_id() + 1, heap);
}
trx_id_offs = rec_get_nth_field_offs(
- offsets, pos, &len);
+ offsets, index->db_trx_id(), &len);
ut_ad(len == DATA_TRX_ID_LEN);
}
@@ -1316,8 +1322,7 @@ row_log_table_get_pk(
const ulint max_len = DICT_MAX_FIELD_LEN_BY_FORMAT(new_table);
- const page_size_t& page_size
- = dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
for (ulint new_i = 0; new_i < new_n_uniq; new_i++) {
dict_field_t* ifield;
@@ -1343,8 +1348,9 @@ row_log_table_get_pk(
}
log->error = row_log_table_get_pk_col(
- ifield, dfield, *heap,
- rec, offsets, i, page_size, max_len, log);
+ ifield, new_index, dfield, *heap,
+ rec, offsets, i, zip_size, max_len,
+ log);
if (log->error != DB_SUCCESS) {
err_exit:
@@ -1564,11 +1570,17 @@ row_log_table_apply_convert_mrec(
const dict_col_t* col
= dict_field_get_col(ind_field);
+ if (col->is_dropped()) {
+ /* the column was instantly dropped earlier */
+ ut_ad(index->table->instant);
+ continue;
+ }
+
ulint col_no
= log->col_map[dict_col_get_no(col)];
if (col_no == ULINT_UNDEFINED) {
- /* dropped column */
+ /* the column is being dropped now */
continue;
}
@@ -1605,7 +1617,7 @@ row_log_table_apply_convert_mrec(
data = btr_rec_copy_externally_stored_field(
mrec, offsets,
- dict_table_page_size(index->table),
+ index->table->space->zip_size(),
i, &len, heap);
ut_a(data);
dfield_set_data(dfield, data, len);
@@ -1643,12 +1655,12 @@ blob_done:
/* See if any columns were changed to NULL or NOT NULL. */
const dict_col_t* new_col
= dict_table_get_nth_col(log->table, col_no);
- ut_ad(new_col->mtype == col->mtype);
+ ut_ad(new_col->same_format(*col));
/* Assert that prtype matches except for nullability. */
- ut_ad(!((new_col->prtype ^ col->prtype) & ~DATA_NOT_NULL));
ut_ad(!((new_col->prtype ^ dfield_get_type(dfield)->prtype)
- & ~DATA_NOT_NULL));
+ & ~(DATA_NOT_NULL | DATA_VERSIONED
+ | CHAR_COLL_MASK << 16 | DATA_LONG_TRUE_VARCHAR)));
if (new_col->prtype == col->prtype) {
continue;
@@ -1925,8 +1937,7 @@ row_log_table_apply_delete(
btr_pcur_t pcur;
offset_t* offsets;
- ut_ad(rec_offs_n_fields(moffsets)
- == dict_index_get_n_unique(index) + 2);
+ ut_ad(rec_offs_n_fields(moffsets) == index->first_user_field());
ut_ad(!rec_offs_any_extern(moffsets));
/* Convert the row to a search tuple. */
@@ -2493,8 +2504,7 @@ row_log_table_apply_op(
/* The ROW_T_DELETE record was converted by
rec_convert_dtuple_to_temp() using new_index. */
ut_ad(!new_index->is_instant());
- rec_offs_set_n_fields(offsets,
- unsigned(new_index->n_uniq) + 2);
+ rec_offs_set_n_fields(offsets, new_index->first_user_field());
rec_init_offsets_temp(mrec, new_index, offsets);
next_mrec = mrec + rec_offs_data_size(offsets);
if (next_mrec > mrec_end) {
@@ -2586,7 +2596,7 @@ row_log_table_apply_op(
rec_convert_dtuple_to_temp() using new_index. */
ut_ad(!new_index->is_instant());
rec_offs_set_n_fields(offsets,
- unsigned(new_index->n_uniq) + 2);
+ new_index->first_user_field());
rec_init_offsets_temp(mrec, new_index, offsets);
next_mrec = mrec + rec_offs_data_size(offsets);
@@ -2596,13 +2606,12 @@ row_log_table_apply_op(
/* Copy the PRIMARY KEY fields and
DB_TRX_ID, DB_ROLL_PTR from mrec to old_pk. */
- old_pk = dtuple_create(
- heap, unsigned(new_index->n_uniq) + 2);
+ old_pk = dtuple_create(heap,
+ new_index->first_user_field());
dict_index_copy_types(old_pk, new_index,
old_pk->n_fields);
- for (ulint i = 0;
- i < dict_index_get_n_unique(new_index) + 2;
+ for (ulint i = 0; i < new_index->first_user_field();
i++) {
const void* field;
ulint len;
@@ -2684,8 +2693,8 @@ ulint
row_log_progress_inc_per_block()
{
/* We must increment the progress once per page (as in
- univ_page_size, usually 16KiB). One block here is srv_sort_buf_size
- (usually 1MiB). */
+ srv_page_size, default = innodb_page_size=16KiB).
+ One block here is srv_sort_buf_size (usually 1MiB). */
const ulint pages_per_block = std::max<ulint>(
ulint(srv_sort_buf_size >> srv_page_size_shift), 1);
@@ -2753,8 +2762,8 @@ row_log_table_apply_ops(
dict_index_t* new_index = dict_table_get_first_index(
new_table);
const ulint i = 1 + REC_OFFS_HEADER_SIZE
- + ut_max(dict_index_get_n_fields(index),
- dict_index_get_n_unique(new_index) + 2);
+ + std::max<ulint>(index->n_fields,
+ new_index->first_user_field());
const ulint new_trx_id_col = dict_col_get_clust_pos(
dict_table_get_sys_col(new_table, DATA_TRX_ID), new_index);
trx_t* trx = thr_get_trx(thr);
@@ -3115,7 +3124,7 @@ row_log_table_apply(
stage->begin_phase_log_table();
- ut_ad(!rw_lock_own(&dict_operation_lock, RW_LOCK_S));
+ ut_ad(!rw_lock_own(&dict_sys.latch, RW_LOCK_S));
clust_index = dict_table_get_first_index(old_table);
if (clust_index->online_log->n_rows == 0) {
@@ -3213,7 +3222,8 @@ row_log_allocate(
log->head.total = 0;
log->path = path;
log->n_core_fields = index->n_core_fields;
- ut_ad(!table || log->is_instant(index) == index->is_instant());
+ ut_ad(!table || log->is_instant(index)
+ == (index->n_core_fields < index->n_fields));
log->allow_not_null = allow_not_null;
log->old_table = old_table;
log->n_rows = 0;
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 1bca8a65532..3956eb40c5f 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -435,7 +435,7 @@ row_merge_buf_redundant_convert(
const dfield_t* row_field,
dfield_t* field,
ulint len,
- const page_size_t& page_size,
+ ulint zip_size,
mem_heap_t* heap)
{
ut_ad(field->type.mbminlen == 1);
@@ -455,7 +455,7 @@ row_merge_buf_redundant_convert(
field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE));
byte* data = btr_copy_externally_stored_field(
- &ext_len, field_data, page_size, field_len, heap);
+ &ext_len, field_data, zip_size, field_len, heap);
ut_ad(ext_len < len);
@@ -697,13 +697,13 @@ row_merge_buf_add(
if (conv_heap != NULL) {
row_merge_buf_redundant_convert(
row_field, field, col->len,
- dict_table_page_size(old_table),
+ old_table->space->zip_size(),
conv_heap);
} else {
/* Field length mismatch should not
happen when rebuilding redundant row
format table. */
- ut_ad(dict_table_is_comp(index->table));
+ ut_ad(index->table->not_redundant());
}
}
}
@@ -1853,7 +1853,7 @@ row_merge_read_clustered_index(
btr_pcur_open_at_index_side(
true, clust_index, BTR_SEARCH_LEAF, &pcur, true, 0, &mtr);
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
- if (rec_is_metadata(btr_pcur_get_rec(&pcur), clust_index)) {
+ if (rec_is_metadata(btr_pcur_get_rec(&pcur), *clust_index)) {
ut_ad(btr_pcur_is_on_user_rec(&pcur));
/* Skip the metadata pseudo-record. */
} else {
@@ -1968,8 +1968,8 @@ row_merge_read_clustered_index(
goto scan_next;
}
- if (my_atomic_load32_explicit(&clust_index->lock.waiters,
- MY_MEMORY_ORDER_RELAXED)) {
+ if (clust_index->lock.waiters.load(
+ std::memory_order_relaxed)) {
/* There are waiters on the clustered
index tree lock, likely the purge
thread. Store and restore the cursor
@@ -2027,7 +2027,7 @@ end_of_index:
block = btr_block_get(
page_id_t(block->page.id.space(),
next_page_no),
- block->page.size,
+ block->zip_size(),
BTR_SEARCH_LEAF,
clust_index, &mtr);
@@ -3419,7 +3419,7 @@ void
row_merge_copy_blobs(
const mrec_t* mrec,
const offset_t* offsets,
- const page_size_t& page_size,
+ ulint zip_size,
dtuple_t* tuple,
mem_heap_t* heap)
{
@@ -3457,10 +3457,10 @@ row_merge_copy_blobs(
BTR_EXTERN_FIELD_REF_SIZE));
data = btr_copy_externally_stored_field(
- &len, field_data, page_size, field_len, heap);
+ &len, field_data, zip_size, field_len, heap);
} else {
data = btr_rec_copy_externally_stored_field(
- mrec, offsets, page_size, i, &len, heap);
+ mrec, offsets, zip_size, i, &len, heap);
}
/* Because we have locked the table, any records
@@ -3652,8 +3652,7 @@ row_merge_insert_index_tuples(
row_log_table_blob_alloc() and
row_log_table_blob_free(). */
row_merge_copy_blobs(
- mrec, offsets,
- dict_table_page_size(old_table),
+ mrec, offsets, old_table->space->zip_size(),
dtuple, tuple_heap);
}
@@ -3736,10 +3735,9 @@ row_merge_drop_index_dict(
pars_info_t* info;
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
info = pars_info_create();
pars_info_add_ull_literal(info, "indexid", index_id);
@@ -3799,17 +3797,16 @@ row_merge_drop_indexes_dict(
pars_info_t* info;
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
/* It is possible that table->n_ref_count > 1 when
locked=TRUE. In this case, all code that should have an open
handle to the table be waiting for the next statement to execute,
or waiting for a meta-data lock.
- A concurrent purge will be prevented by dict_operation_lock. */
+ A concurrent purge will be prevented by dict_sys.latch. */
info = pars_info_create();
pars_info_add_ull_literal(info, "tableid", table_id);
@@ -3849,10 +3846,9 @@ row_merge_drop_indexes(
dict_index_t* next_index;
ut_ad(!srv_read_only_mode);
- ut_ad(mutex_own(&dict_sys->mutex));
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
index = dict_table_get_first_index(table);
ut_ad(dict_index_is_clust(index));
@@ -3866,7 +3862,7 @@ row_merge_drop_indexes(
handle to the table be waiting for the next statement to execute,
or waiting for a meta-data lock.
- A concurrent purge will be prevented by dict_operation_lock. */
+ A concurrent purge will be prevented by dict_sys.latch. */
if (!locked && (table->get_ref_count() > 1
|| UT_LIST_GET_FIRST(table->locks))) {
@@ -3933,7 +3929,7 @@ row_merge_drop_indexes(
rw_lock_x_unlock(dict_index_get_lock(index));
DEBUG_SYNC_C("merge_drop_index_after_abort");
- /* covered by dict_sys->mutex */
+ /* covered by dict_sys.mutex */
MONITOR_INC(MONITOR_BACKGROUND_DROP_INDEX);
/* fall through */
case ONLINE_INDEX_ABORTED:
@@ -3996,7 +3992,7 @@ row_merge_drop_indexes(
break;
case ONLINE_INDEX_ABORTED:
case ONLINE_INDEX_ABORTED_DROPPED:
- /* covered by dict_sys->mutex */
+ /* covered by dict_sys.mutex */
MONITOR_DEC(MONITOR_BACKGROUND_DROP_INDEX);
}
@@ -4302,7 +4298,7 @@ row_merge_rename_tables_dict(
ut_ad(!srv_read_only_mode);
ut_ad(old_table != new_table);
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
ut_ad(trx_get_dict_operation(trx) == TRX_DICT_OP_TABLE
|| trx_get_dict_operation(trx) == TRX_DICT_OP_INDEX);
@@ -4671,7 +4667,7 @@ row_merge_build_indexes(
created */
if (!row_fts_psort_info_init(
trx, dup, new_table, opt_doc_id_size,
- dict_table_page_size(old_table),
+ old_table->space->zip_size(),
&psort_info, &merge_info)) {
error = DB_CORRUPTION;
goto func_exit;
@@ -4986,7 +4982,8 @@ func_exit:
alloc.deallocate_large(block, &block_pfx, block_size);
if (crypt_block) {
- alloc.deallocate_large(crypt_block, &crypt_pfx, block_size);
+ alloc.deallocate_large(crypt_block, &crypt_pfx,
+ block_size);
}
DICT_TF2_FLAG_UNSET(new_table, DICT_TF2_FTS_ADD_DOC_ID);
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 51845e2ea47..65e34b317c3 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -34,7 +34,6 @@ Created 9/17/2000 Heikki Tuuri
#include "btr0sea.h"
#include "dict0boot.h"
#include "dict0crea.h"
-#include <sql_const.h>
#include "dict0dict.h"
#include "dict0load.h"
#include "dict0priv.h"
@@ -329,6 +328,7 @@ row_mysql_read_geometry(
ulint col_len) /*!< in: MySQL format length */
{
byte* data;
+ ut_ad(col_len > 8);
*len = mach_read_from_n_little_endian(ref, col_len - 8);
@@ -829,7 +829,8 @@ row_create_prebuilt(
clust_index = dict_table_get_first_index(table);
/* Make sure that search_tuple is long enough for clustered index */
- ut_a(2 * dict_table_get_n_cols(table) >= clust_index->n_fields);
+ ut_a(2 * unsigned(table->n_cols) >= unsigned(clust_index->n_fields)
+ - clust_index->table->n_dropped());
ref_len = dict_index_get_n_unique(clust_index);
@@ -2119,7 +2120,7 @@ row_mysql_freeze_data_dictionary_func(
{
ut_a(trx->dict_operation_lock_mode == 0);
- rw_lock_s_lock_inline(&dict_operation_lock, 0, file, line);
+ rw_lock_s_lock_inline(&dict_sys.latch, 0, file, line);
trx->dict_operation_lock_mode = RW_S_LATCH;
}
@@ -2135,7 +2136,7 @@ row_mysql_unfreeze_data_dictionary(
ut_a(trx->dict_operation_lock_mode == RW_S_LATCH);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
trx->dict_operation_lock_mode = 0;
}
@@ -2327,14 +2328,8 @@ row_mysql_lock_data_dictionary_func(
{
ut_a(trx->dict_operation_lock_mode == 0
|| trx->dict_operation_lock_mode == RW_X_LATCH);
-
- /* Serialize data dictionary operations with dictionary mutex:
- no deadlocks or lock waits can occur then in these operations */
-
- rw_lock_x_lock_inline(&dict_operation_lock, 0, file, line);
+ dict_sys.lock(file, line);
trx->dict_operation_lock_mode = RW_X_LATCH;
-
- mutex_enter(&dict_sys->mutex);
}
/*********************************************************************//**
@@ -2345,16 +2340,9 @@ row_mysql_unlock_data_dictionary(
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(lock_trx_has_sys_table_locks(trx) == NULL);
-
ut_a(trx->dict_operation_lock_mode == RW_X_LATCH);
-
- /* Serialize data dictionary operations with dictionary mutex:
- no deadlocks can occur then in these operations */
-
- mutex_exit(&dict_sys->mutex);
- rw_lock_x_unlock(&dict_operation_lock);
-
trx->dict_operation_lock_mode = 0;
+ dict_sys.unlock();
}
/*********************************************************************//**
@@ -2376,8 +2364,7 @@ row_create_table_for_mysql(
que_thr_t* thr;
dberr_t err;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
DBUG_EXECUTE_IF(
@@ -2517,8 +2504,7 @@ row_create_index_for_mysql(
ulint len;
dict_table_t* table = index->table;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
- ut_ad(mutex_own(&dict_sys->mutex));
+ ut_d(dict_sys.assert_locked());
for (i = 0; i < index->n_def; i++) {
/* Check that prefix_len and actual length
@@ -2743,7 +2729,7 @@ row_mysql_drop_garbage_tables()
mtr.start();
btr_pcur_open_at_index_side(
- true, dict_table_get_first_index(dict_sys->sys_tables),
+ true, dict_table_get_first_index(dict_sys.sys_tables),
BTR_SEARCH_LEAF, &pcur, true, 0, &mtr);
for (;;) {
@@ -2853,11 +2839,15 @@ row_mysql_table_id_reassign(
dberr_t err;
pars_info_t* info = pars_info_create();
- dict_hdr_get_new_id(new_id, NULL, NULL, table, false);
+ dict_hdr_get_new_id(new_id, NULL, NULL);
pars_info_add_ull_literal(info, "old_id", table->id);
pars_info_add_ull_literal(info, "new_id", *new_id);
+ /* Note: This cannot be rolled back. Rollback would see the
+ UPDATE SYS_INDEXES as two operations: DELETE and INSERT.
+ It would invoke btr_free_if_exists() when rolling back the
+ INSERT, effectively dropping all indexes of the table. */
err = que_eval_sql(
info,
"PROCEDURE RENUMBER_TABLE_PROC () IS\n"
@@ -3087,7 +3077,7 @@ row_discard_tablespace(
dict_table_change_id_in_cache(table, new_id);
dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
- if (index) index->remove_instant();
+ if (index) index->clear_instant_alter();
/* Reset the root page numbers. */
for (; index; index = UT_LIST_GET_NEXT(indexes, index)) {
@@ -3157,6 +3147,12 @@ row_discard_tablespace_for_mysql(
err = row_discard_tablespace_foreign_key_checks(trx, table);
if (err == DB_SUCCESS) {
+ /* Note: This cannot be rolled back.
+ Rollback would see the UPDATE SYS_INDEXES
+ as two operations: DELETE and INSERT.
+ It would invoke btr_free_if_exists()
+ when rolling back the INSERT, effectively
+ dropping all indexes of the table. */
err = row_discard_tablespace(trx, table);
}
@@ -3289,7 +3285,7 @@ row_drop_table_from_cache(
is going to be destroyed below. */
trx->mod_tables.erase(table);
- dict_table_remove_from_cache(table);
+ dict_sys.remove(table);
if (dict_load_table(tablename, DICT_ERR_IGNORE_FK_NOKEY)) {
ib::error() << "Not able to remove table "
@@ -3311,7 +3307,7 @@ will remain locked.
@param[in] create_failed true=create table failed
because e.g. foreign key column
@param[in] nonatomic Whether it is permitted to release
- and reacquire dict_operation_lock
+ and reacquire dict_sys.latch
@return error code or DB_SUCCESS */
dberr_t
row_drop_table_for_mysql(
@@ -3350,8 +3346,7 @@ row_drop_table_for_mysql(
nonatomic = true;
}
- ut_ad(mutex_own(&dict_sys->mutex));
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_X));
+ ut_d(dict_sys.assert_locked());
table = dict_table_open_on_name(
name, TRUE, FALSE,
@@ -3375,15 +3370,14 @@ row_drop_table_for_mysql(
for (dict_index_t* index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
- btr_free(page_id_t(SRV_TMP_SPACE_ID, index->page),
- univ_page_size);
+ btr_free(page_id_t(SRV_TMP_SPACE_ID, index->page));
}
/* Remove the pointer to this table object from the list
of modified tables by the transaction because the object
is going to be destroyed below. */
trx->mod_tables.erase(table);
table->release();
- dict_table_remove_from_cache(table);
+ dict_sys.remove(table);
err = DB_SUCCESS;
goto funct_exit_all_freed;
}
@@ -4034,8 +4028,8 @@ loop:
/* The dict_table_t object must not be accessed before
dict_table_open() or after dict_table_close(). But this is OK
- if we are holding, the dict_sys->mutex. */
- ut_ad(mutex_own(&dict_sys->mutex));
+ if we are holding, the dict_sys.mutex. */
+ ut_ad(mutex_own(&dict_sys.mutex));
/* Disable statistics on the found table. */
if (!dict_stats_stop_bg(table)) {
diff --git a/storage/innobase/row/row0purge.cc b/storage/innobase/row/row0purge.cc
index bca6d802a53..61920532c29 100644
--- a/storage/innobase/row/row0purge.cc
+++ b/storage/innobase/row/row0purge.cc
@@ -103,33 +103,32 @@ row_purge_remove_clust_if_poss_low(
purge_node_t* node, /*!< in/out: row purge node */
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
{
- dict_index_t* index;
- bool success = true;
- mtr_t mtr;
- rec_t* rec;
- mem_heap_t* heap = NULL;
- offset_t* offsets;
- offset_t offsets_[REC_OFFS_NORMAL_SIZE];
- rec_offs_init(offsets_);
-
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_S)
+ ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S)
|| node->vcol_info.is_used());
- index = dict_table_get_first_index(node->table);
+ dict_index_t* index = dict_table_get_first_index(node->table);
log_free_check();
- mtr_start(&mtr);
- index->set_modified(mtr);
+
+ mtr_t mtr;
+ mtr.start();
if (!row_purge_reposition_pcur(mode, node, &mtr)) {
/* The record was already removed. */
- goto func_exit;
+ mtr.commit();
+ return true;
}
- rec = btr_pcur_get_rec(&node->pcur);
+ ut_d(const bool was_instant = !!index->table->instant);
+ index->set_modified(mtr);
- offsets = rec_get_offsets(
+ rec_t* rec = btr_pcur_get_rec(&node->pcur);
+ offset_t offsets_[REC_OFFS_NORMAL_SIZE];
+ rec_offs_init(offsets_);
+ mem_heap_t* heap = NULL;
+ offset_t* offsets = rec_get_offsets(
rec, index, offsets_, true, ULINT_UNDEFINED, &heap);
+ bool success = true;
if (node->roll_ptr != row_get_rec_roll_ptr(rec, index, offsets)) {
/* Someone else has modified the record later: do not remove */
@@ -162,6 +161,10 @@ row_purge_remove_clust_if_poss_low(
}
}
+ /* Prove that dict_index_t::clear_instant_alter() was
+ not called with index->table->instant != NULL. */
+ ut_ad(!was_instant || index->table->instant);
+
func_exit:
if (heap) {
mem_heap_free(heap);
@@ -788,7 +791,7 @@ whose old history can no longer be observed.
@param[in,out] mtr mini-transaction (will be started and committed) */
static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
{
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_S)
+ ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S)
|| node->vcol_info.is_used());
/* Reset DB_TRX_ID, DB_ROLL_PTR for old records. */
mtr->start();
@@ -821,8 +824,9 @@ static void row_purge_reset_trx_id(purge_node_t* node, mtr_t* mtr)
became purgeable) */
if (node->roll_ptr
== row_get_rec_roll_ptr(rec, index, offsets)) {
- ut_ad(!rec_get_deleted_flag(rec,
- rec_offs_comp(offsets)));
+ ut_ad(!rec_get_deleted_flag(
+ rec, rec_offs_comp(offsets))
+ || rec_is_alter_metadata(rec, *index));
DBUG_LOG("purge", "reset DB_TRX_ID="
<< ib::hex(row_get_rec_trx_id(
rec, index, offsets)));
@@ -864,7 +868,7 @@ row_purge_upd_exist_or_extern_func(
{
mem_heap_t* heap;
- ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_S)
+ ut_ad(rw_lock_own(&dict_sys.latch, RW_LOCK_S)
|| node->vcol_info.is_used());
ut_ad(!node->table->skip_alter_undo);
@@ -972,7 +976,7 @@ skip_secondaries:
block = buf_page_get(
page_id_t(rseg->space->id, page_no),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
@@ -1063,7 +1067,7 @@ row_purge_parse_undo_rec(
for this row */
try_again:
- rw_lock_s_lock_inline(&dict_operation_lock, 0, __FILE__, __LINE__);
+ rw_lock_s_lock_inline(&dict_sys.latch, 0, __FILE__, __LINE__);
node->table = dict_table_open_on_id(
table_id, FALSE, DICT_TABLE_OP_NORMAL);
@@ -1094,7 +1098,7 @@ try_again:
if (!mysqld_server_started) {
dict_table_close(node->table, FALSE, FALSE);
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
return(false);
}
@@ -1124,7 +1128,7 @@ inaccessible:
dict_table_close(node->table, FALSE, FALSE);
node->table = NULL;
err_exit:
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
node->skip(table_id, trx_id);
return(false);
}
@@ -1260,10 +1264,10 @@ row_purge(
node, undo_rec, thr, updated_extern);
if (!node->vcol_info.is_used()) {
- rw_lock_s_unlock(&dict_operation_lock);
+ rw_lock_s_unlock(&dict_sys.latch);
}
- ut_ad(!rw_lock_own(&dict_operation_lock, RW_LOCK_S));
+ ut_ad(!rw_lock_own(&dict_sys.latch, RW_LOCK_S));
if (purged
|| srv_shutdown_state != SRV_SHUTDOWN_NONE
diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc
index 94a372bd046..02c8c495e88 100644
--- a/storage/innobase/row/row0quiesce.cc
+++ b/storage/innobase/row/row0quiesce.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2012, 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
@@ -70,17 +70,16 @@ row_quiesce_write_index_fields(
return(DB_IO_ERROR);
}
+ const char* field_name = field->name ? field->name : "";
/* Include the NUL byte in the length. */
- ib_uint32_t len = static_cast<ib_uint32_t>(strlen(field->name) + 1);
- ut_a(len > 1);
-
+ ib_uint32_t len = static_cast<ib_uint32_t>(strlen(field_name) + 1);
mach_write_to_4(row, len);
DBUG_EXECUTE_IF("ib_export_io_write_failure_10",
close(fileno(file)););
if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
- || fwrite(field->name, 1, len, file) != len) {
+ || fwrite(field_name, 1, len, file) != len) {
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
@@ -670,8 +669,11 @@ row_quiesce_set_state(
}
row_mysql_lock_data_dictionary(trx);
-
- dict_table_x_lock_indexes(table);
+ for (dict_index_t* index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ rw_lock_x_lock(&index->lock);
+ }
switch (state) {
case QUIESCE_START:
@@ -688,7 +690,11 @@ row_quiesce_set_state(
table->quiesce = state;
- dict_table_x_unlock_indexes(table);
+ for (dict_index_t* index = dict_table_get_first_index(table);
+ index != NULL;
+ index = dict_table_get_next_index(index)) {
+ rw_lock_x_unlock(&index->lock);
+ }
row_mysql_unlock_data_dictionary(trx);
diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc
index c19aa42b48e..83add52dd88 100644
--- a/storage/innobase/row/row0row.cc
+++ b/storage/innobase/row/row0row.cc
@@ -62,6 +62,10 @@ static bool row_build_spatial_index_key(
ulint flag,
mem_heap_t* heap)
{
+ if (dfield2->type.mtype == DATA_MISSING) {
+ return false;
+ }
+
double* mbr;
dfield_copy(dfield, dfield2);
@@ -92,6 +96,7 @@ static bool row_build_spatial_index_key(
if (!dfield_is_ext(dfield2)) {
dptr = static_cast<const byte*>(dfield_get_data(dfield2));
dlen = dfield_get_len(dfield2);
+ ut_ad(dptr != &data_error);
goto write_mbr;
}
@@ -152,7 +157,7 @@ static bool row_build_spatial_index_key(
temp_heap = mem_heap_create(1000);
dptr = btr_copy_externally_stored_field(
- &dlen, dptr, ext ? ext->page_size : page_size_t(space->flags),
+ &dlen, dptr, ext ? ext->zip_size : space->zip_size(),
flen, temp_heap);
write_mbr:
@@ -198,7 +203,7 @@ row_build_index_entry_low(
{
dtuple_t* entry;
ulint entry_len;
- ulint i;
+ ulint i = 0;
ulint num_v = 0;
entry_len = dict_index_get_n_fields(index);
@@ -218,90 +223,87 @@ row_build_index_entry_low(
} else {
dtuple_set_n_fields_cmp(
entry, dict_index_get_n_unique_in_tree(index));
- }
+ if (dict_index_is_spatial(index)) {
+ /* Set the MBR field */
+ if (!row_build_spatial_index_key(
+ index, ext,
+ dtuple_get_nth_field(entry, 0),
+ dtuple_get_nth_field(
+ row,
+ dict_index_get_nth_field(index, i)
+ ->col->ind), flag, heap)) {
+ return NULL;
+ }
- for (i = 0; i < entry_len + num_v; i++) {
- const dict_field_t* ind_field = NULL;
- const dict_col_t* col;
- ulint col_no = 0;
- dfield_t* dfield;
- const dfield_t* dfield2;
- ulint len;
-
- if (i >= entry_len) {
- /* This is to insert new rows to cluster index */
- ut_ad(dict_index_is_clust(index)
- && flag == ROW_BUILD_FOR_INSERT);
- dfield = dtuple_get_nth_v_field(entry, i - entry_len);
- col = &dict_table_get_nth_v_col(
- index->table, i - entry_len)->m_col;
+ i = 1;
+ }
+ }
- } else {
- ind_field = dict_index_get_nth_field(index, i);
- col = ind_field->col;
- col_no = dict_col_get_no(col);
- dfield = dtuple_get_nth_field(entry, i);
+ for (; i < entry_len; i++) {
+ const dict_field_t& f = index->fields[i];
+ dfield_t* dfield = dtuple_get_nth_field(entry, i);
+
+ if (f.col->is_dropped()) {
+ ut_ad(index->is_primary());
+ ut_ad(index->is_instant());
+ ut_ad(!f.col->is_virtual());
+ dict_col_copy_type(f.col, &dfield->type);
+ if (f.col->is_nullable()) {
+ dfield_set_null(dfield);
+ } else {
+ dfield_set_data(dfield, field_ref_zero,
+ f.fixed_len);
+ }
+ continue;
}
- compile_time_assert(DATA_MISSING == 0);
+ const dfield_t* dfield2;
- if (col->is_virtual()) {
- const dict_v_col_t* v_col
- = reinterpret_cast<const dict_v_col_t*>(col);
+ if (f.col->is_virtual()) {
+ const dict_v_col_t* v_col
+ = reinterpret_cast<const dict_v_col_t*>(f.col);
ut_ad(v_col->v_pos < dtuple_get_n_v_fields(row));
dfield2 = dtuple_get_nth_v_field(row, v_col->v_pos);
ut_ad(dfield_is_null(dfield2) ||
dfield_get_len(dfield2) == 0 || dfield2->data);
+ ut_ad(!dfield_is_ext(dfield2));
+ if (UNIV_UNLIKELY(dfield2->type.mtype
+ == DATA_MISSING)) {
+ ut_ad(flag == ROW_BUILD_FOR_PURGE);
+ return(NULL);
+ }
} else {
- dfield2 = dtuple_get_nth_field(row, col_no);
- ut_ad(dfield_get_type(dfield2)->mtype == DATA_MISSING
- || (!(dfield_get_type(dfield2)->prtype
- & DATA_VIRTUAL)));
- }
-
- if (UNIV_UNLIKELY(dfield_get_type(dfield2)->mtype
- == DATA_MISSING)) {
- /* The field has not been initialized in the row.
- This should be from trx_undo_rec_get_partial_row(). */
- return(NULL);
- }
-
-#ifdef UNIV_DEBUG
- if (dfield_get_type(dfield2)->prtype & DATA_VIRTUAL
- && dict_index_is_clust(index)) {
- ut_ad(flag == ROW_BUILD_FOR_INSERT);
- }
-#endif /* UNIV_DEBUG */
-
- /* Special handle spatial index, set the first field
- which is for store MBR. */
- if (dict_index_is_spatial(index) && i == 0) {
- if (!row_build_spatial_index_key(
- index, ext, dfield, dfield2, flag, heap)) {
- return NULL;
+ dfield2 = dtuple_get_nth_field(row, f.col->ind);
+ if (UNIV_UNLIKELY(dfield2->type.mtype
+ == DATA_MISSING)) {
+ /* The field has not been initialized in
+ the row. This should be from
+ trx_undo_rec_get_partial_row(). */
+ return(NULL);
}
- continue;
+ ut_ad(!(dfield2->type.prtype & DATA_VIRTUAL));
}
- len = dfield_get_len(dfield2);
+ compile_time_assert(DATA_MISSING == 0);
- dfield_copy(dfield, dfield2);
+ *dfield = *dfield2;
if (dfield_is_null(dfield)) {
continue;
}
- if ((!ind_field || ind_field->prefix_len == 0)
+ ulint len = dfield_get_len(dfield);
+
+ if (f.prefix_len == 0
&& (!dfield_is_ext(dfield)
|| dict_index_is_clust(index))) {
/* The dfield_copy() above suffices for
columns that are stored in-page, or for
clustered index record columns that are not
- part of a column prefix in the PRIMARY KEY,
- or for virtaul columns in cluster index record. */
+ part of a column prefix in the PRIMARY KEY. */
continue;
}
@@ -312,11 +314,11 @@ row_build_index_entry_low(
index record with an off-page column is when it is a
column prefix index. If atomic_blobs, also fully
indexed long columns may be stored off-page. */
- ut_ad(col->ord_part);
+ ut_ad(f.col->ord_part);
- if (ext && !col->is_virtual()) {
+ if (ext && !f.col->is_virtual()) {
/* See if the column is stored externally. */
- const byte* buf = row_ext_lookup(ext, col_no,
+ const byte* buf = row_ext_lookup(ext, f.col->ind,
&len);
if (UNIV_LIKELY_NULL(buf)) {
if (UNIV_UNLIKELY(buf == field_ref_zero)) {
@@ -325,7 +327,7 @@ row_build_index_entry_low(
dfield_set_data(dfield, buf, len);
}
- if (ind_field->prefix_len == 0) {
+ if (f.prefix_len == 0) {
/* If ROW_FORMAT=DYNAMIC or
ROW_FORMAT=COMPRESSED, we can have a
secondary index on an entire column
@@ -352,16 +354,33 @@ row_build_index_entry_low(
}
/* If a column prefix index, take only the prefix. */
- if (ind_field->prefix_len) {
+ if (f.prefix_len) {
len = dtype_get_at_most_n_mbchars(
- col->prtype, col->mbminlen, col->mbmaxlen,
- ind_field->prefix_len, len,
+ f.col->prtype,
+ f.col->mbminlen, f.col->mbmaxlen,
+ f.prefix_len, len,
static_cast<char*>(dfield_get_data(dfield)));
dfield_set_len(dfield, len);
}
}
- return(entry);
+ for (i = num_v; i--; ) {
+ ut_ad(index->is_primary());
+ ut_ad(flag == ROW_BUILD_FOR_INSERT);
+ dfield_t* dfield = dtuple_get_nth_v_field(entry, i);
+ const dict_v_col_t* v_col = dict_table_get_nth_v_col(
+ index->table, i);
+ ut_ad(!v_col->m_col.is_dropped());
+ ut_ad(v_col->v_pos < dtuple_get_n_v_fields(row));
+ const dfield_t* dfield2 = dtuple_get_nth_v_field(
+ row, v_col->v_pos);
+ ut_ad(dfield_is_null(dfield2) ||
+ dfield_get_len(dfield2) == 0 || dfield2->data);
+ ut_ad(dfield2->type.mtype != DATA_MISSING);
+ *dfield = *dfield2;
+ }
+
+ return entry;
}
/** An inverse function to row_build_index_entry. Builds a row from a
@@ -498,11 +517,23 @@ row_build_low(
j = 0;
+ const dict_field_t* ind_field = index->fields;
+
for (ulint i = 0; i < rec_offs_n_fields(offsets); i++) {
- const dict_field_t* ind_field
- = dict_index_get_nth_field(index, i);
+ if (i == index->first_user_field()
+ && rec_is_alter_metadata(rec, *index)) {
+ ut_ad(rec_offs_nth_extern(offsets, i));
+ ut_d(ulint len);
+ ut_d(rec_get_nth_field_offs(offsets, i, &len));
+ ut_ad(len == FIELD_REF_SIZE);
+ continue;
+ }
+
+ ut_ad(ind_field < &index->fields[index->n_fields]);
+
+ const dict_col_t* col = dict_field_get_col(ind_field);
- if (ind_field->prefix_len) {
+ if ((ind_field++)->prefix_len) {
/* Column prefixes can only occur in key
fields, which cannot be stored externally. For
a column prefix, there should also be the full
@@ -512,10 +543,11 @@ row_build_low(
continue;
}
- const dict_col_t* col
- = dict_field_get_col(ind_field);
- ulint col_no
- = dict_col_get_no(col);
+ if (col->is_dropped()) {
+ continue;
+ }
+
+ ulint col_no = dict_col_get_no(col);
if (col_map) {
col_no = col_map[col_no];
@@ -527,6 +559,7 @@ row_build_low(
}
dfield_t* dfield = dtuple_get_nth_field(row, col_no);
+
const void* field = rec_get_nth_field(
copy, offsets, i, &len);
if (len == UNIV_SQL_DEFAULT) {
@@ -566,7 +599,7 @@ row_build_low(
row_log_table_delete(). */
} else if (j) {
- *ext = row_ext_create(j, ext_cols, index->table->flags, row,
+ *ext = row_ext_create(j, ext_cols, *index->table, row,
heap);
} else {
*ext = NULL;
@@ -670,57 +703,83 @@ row_build_w_add_vcol(
}
/** Convert an index record to a data tuple.
-@tparam def whether the index->instant_field_value() needs to be accessed
-@param[in] rec index record
-@param[in] index index
-@param[in] offsets rec_get_offsets(rec, index)
-@param[out] n_ext number of externally stored columns
-@param[in,out] heap memory heap for allocations
+@tparam metadata whether the index->instant_field_value() needs to be accessed
+@tparam mblob 1 if rec_is_alter_metadata();
+2 if we want converted metadata corresponding to info_bits
+@param[in] rec index record
+@param[in] index index
+@param[in] offsets rec_get_offsets(rec, index)
+@param[out] n_ext number of externally stored columns
+@param[in,out] heap memory heap for allocations
+@param[in] info_bits (only used if mblob=2)
+@param[in] pad (only used if mblob=2)
@return index entry built; does not set info_bits, and the data fields
in the entry will point directly to rec */
-template<bool def>
+template<bool metadata, int mblob = 0>
static inline
dtuple_t*
row_rec_to_index_entry_impl(
const rec_t* rec,
const dict_index_t* index,
const offset_t* offsets,
- mem_heap_t* heap)
+ mem_heap_t* heap,
+ ulint info_bits = 0,
+ bool pad = false)
{
- dtuple_t* entry;
- dfield_t* dfield;
- ulint i;
- const byte* field;
- ulint len;
- ulint rec_len;
-
ut_ad(rec != NULL);
ut_ad(heap != NULL);
ut_ad(index != NULL);
- ut_ad(def || !rec_offs_any_default(offsets));
-
+ ut_ad(!mblob || index->is_primary());
+ ut_ad(!mblob || !index->table->is_temporary());
+ ut_ad(!mblob || !dict_index_is_spatial(index));
+ compile_time_assert(!mblob || metadata);
+ compile_time_assert(mblob <= 2);
/* Because this function may be invoked by row0merge.cc
on a record whose header is in different format, the check
rec_offs_validate(rec, index, offsets) must be avoided here. */
- rec_len = rec_offs_n_fields(offsets);
-
- entry = dtuple_create(heap, rec_len);
+ const bool got = mblob == 2 && rec_is_alter_metadata(rec, *index);
+ ulint rec_len = rec_offs_n_fields(offsets);
+ if (mblob == 2) {
+ ut_ad(info_bits == REC_INFO_METADATA_ALTER
+ || info_bits == REC_INFO_METADATA_ADD);
+ ut_ad(rec_len <= ulint(index->n_fields + got));
+ if (pad) {
+ rec_len = ulint(index->n_fields)
+ + (info_bits == REC_INFO_METADATA_ALTER);
+ } else if (!got && info_bits == REC_INFO_METADATA_ALTER) {
+ rec_len++;
+ }
+ } else {
+ ut_ad(info_bits == 0);
+ ut_ad(!pad);
+ }
+ dtuple_t* entry = dtuple_create(heap, rec_len);
+ dfield_t* dfield = entry->fields;
dtuple_set_n_fields_cmp(entry,
dict_index_get_n_unique_in_tree(index));
- ut_ad(rec_len == dict_index_get_n_fields(index)
+ ut_ad(mblob == 2
+ || rec_len == dict_index_get_n_fields(index) + uint(mblob == 1)
/* a record for older SYS_INDEXES table
(missing merge_threshold column) is acceptable. */
- || (index->table->id == DICT_INDEXES_ID
+ || (!index->table->is_temporary()
+ && index->table->id == DICT_INDEXES_ID
&& rec_len == dict_index_get_n_fields(index) - 1));
- dict_index_copy_types(entry, index, rec_len);
-
- for (i = 0; i < rec_len; i++) {
+ ulint i;
+ for (i = 0; i < (mblob ? index->first_user_field() : rec_len);
+ i++, dfield++) {
+ dict_col_copy_type(dict_index_get_nth_col(index, i),
+ &dfield->type);
+ if (!mblob
+ && dict_index_is_spatial(index)
+ && DATA_GEOMETRY_MTYPE(dfield->type.mtype)) {
+ dfield->type.prtype |= DATA_GIS_MBR;
+ }
- dfield = dtuple_get_nth_field(entry, i);
- field = def
+ ulint len;
+ const byte* field = metadata
? rec_get_nth_cfield(rec, index, offsets, i, &len)
: rec_get_nth_field(rec, offsets, i, &len);
@@ -731,8 +790,74 @@ row_rec_to_index_entry_impl(
}
}
+ if (mblob) {
+ ulint len;
+ const byte* field;
+ ulint j = i;
+
+ if (mblob == 2) {
+ const bool want = info_bits == REC_INFO_METADATA_ALTER;
+ if (got == want) {
+ if (got) {
+ goto copy_metadata;
+ }
+ } else {
+ if (want) {
+ /* Allocate a placeholder for
+ adding metadata in an update. */
+ len = FIELD_REF_SIZE;
+ field = static_cast<byte*>(
+ mem_heap_zalloc(heap, len));
+ /* In reality there is one fewer
+ field present in the record. */
+ rec_len--;
+ goto init_metadata;
+ }
+
+ /* Skip the undesired metadata blob
+ (for example, when rolling back an
+ instant ALTER TABLE). */
+ i++;
+ }
+ goto copy_user_fields;
+ }
+copy_metadata:
+ ut_ad(rec_offs_nth_extern(offsets, i));
+ field = rec_get_nth_field(rec, offsets, i++, &len);
+init_metadata:
+ dfield->type.metadata_blob_init();
+ ut_ad(len == FIELD_REF_SIZE);
+ dfield_set_data(dfield, field, len);
+ dfield_set_ext(dfield++);
+copy_user_fields:
+ for (; i < rec_len; i++, dfield++) {
+ dict_col_copy_type(dict_index_get_nth_col(index, j++),
+ &dfield->type);
+ if (mblob == 2 && pad
+ && i >= rec_offs_n_fields(offsets)) {
+ field = index->instant_field_value(j - 1,
+ &len);
+ dfield_set_data(dfield, field, len);
+ continue;
+ }
+
+ field = rec_get_nth_field(rec, offsets, i, &len);
+ dfield_set_data(dfield, field, len);
+
+ if (rec_offs_nth_extern(offsets, i)) {
+ dfield_set_ext(dfield);
+ }
+ }
+ }
+
+ if (mblob == 2) {
+ ulint n_fields = ulint(dfield - entry->fields);
+ ut_ad(entry->n_fields >= n_fields);
+ entry->n_fields = n_fields;
+ }
+ ut_ad(dfield == entry->fields + entry->n_fields);
ut_ad(dtuple_check_typed(entry));
- return(entry);
+ return entry;
}
/** Convert an index record to a data tuple.
@@ -763,25 +888,26 @@ row_rec_to_index_entry(
mem_heap_t* heap) /*!< in: memory heap from which
the memory needed is allocated */
{
- dtuple_t* entry;
- byte* buf;
- const rec_t* copy_rec;
-
ut_ad(rec != NULL);
ut_ad(heap != NULL);
ut_ad(index != NULL);
ut_ad(rec_offs_validate(rec, index, offsets));
/* Take a copy of rec to heap */
- buf = static_cast<byte*>(
- mem_heap_alloc(heap, rec_offs_size(offsets)));
-
- copy_rec = rec_copy(buf, rec, offsets);
+ const rec_t* copy_rec = rec_copy(
+ static_cast<byte*>(mem_heap_alloc(heap,
+ rec_offs_size(offsets))),
+ rec, offsets);
rec_offs_make_valid(copy_rec, index, true,
const_cast<offset_t*>(offsets));
- entry = row_rec_to_index_entry_impl<true>(
- copy_rec, index, offsets, heap);
+
+ dtuple_t* entry = rec_is_alter_metadata(copy_rec, *index)
+ ? row_rec_to_index_entry_impl<true,1>(
+ copy_rec, index, offsets, heap)
+ : row_rec_to_index_entry_impl<true>(
+ copy_rec, index, offsets, heap);
+
rec_offs_make_valid(rec, index, true,
const_cast<offset_t*>(offsets));
@@ -791,6 +917,49 @@ row_rec_to_index_entry(
return(entry);
}
+/** Convert a metadata record to a data tuple.
+@param[in] rec metadata record
+@param[in] index clustered index after instant ALTER TABLE
+@param[in] offsets rec_get_offsets(rec)
+@param[in,out] heap memory heap for allocations
+@param[in] info_bits the info_bits after an update
+@param[in] pad whether to pad to index->n_fields */
+dtuple_t*
+row_metadata_to_tuple(
+ const rec_t* rec,
+ const dict_index_t* index,
+ const offset_t* offsets,
+ mem_heap_t* heap,
+ ulint info_bits,
+ bool pad)
+{
+ ut_ad(info_bits == REC_INFO_METADATA_ALTER
+ || info_bits == REC_INFO_METADATA_ADD);
+ ut_ad(rec_is_metadata(rec, *index));
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
+ const rec_t* copy_rec = rec_copy(
+ static_cast<byte*>(mem_heap_alloc(heap,
+ rec_offs_size(offsets))),
+ rec, offsets);
+
+ rec_offs_make_valid(copy_rec, index, true,
+ const_cast<offset_t*>(offsets));
+
+ dtuple_t* entry = info_bits == REC_INFO_METADATA_ALTER
+ || rec_is_alter_metadata(copy_rec, *index)
+ ? row_rec_to_index_entry_impl<true,2>(
+ copy_rec, index, offsets, heap, info_bits, pad)
+ : row_rec_to_index_entry_impl<true>(
+ copy_rec, index, offsets, heap);
+
+ rec_offs_make_valid(rec, index, true,
+ const_cast<offset_t*>(offsets));
+
+ dtuple_set_info_bits(entry, info_bits);
+ return entry;
+}
+
/*******************************************************************//**
Builds from a secondary index record a row reference with which we can
search the clustered index record.
@@ -1022,7 +1191,7 @@ row_search_on_row_ref(
index = dict_table_get_first_index(table);
if (UNIV_UNLIKELY(ref->info_bits != 0)) {
- ut_ad(ref->info_bits == REC_INFO_METADATA);
+ ut_ad(ref->is_metadata());
ut_ad(ref->n_fields <= index->n_uniq);
if (btr_pcur_open_at_index_side(
true, index, mode, pcur, true, 0, mtr)
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index c2b23caa513..7b6df752043 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -54,6 +54,9 @@ Created 12/19/1997 Heikki Tuuri
#include "buf0lru.h"
#include "srv0srv.h"
#include "srv0mon.h"
+#ifdef WITH_WSREP
+#include "mysql/service_wsrep.h" /* For wsrep_thd_skip_locking */
+#endif
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
@@ -124,7 +127,7 @@ row_sel_sec_rec_is_for_blob(
}
len = btr_copy_externally_stored_field_prefix(
- buf, prefix_len, page_size_t(table->space->flags),
+ buf, prefix_len, table->space->zip_size(),
clust_field, clust_len);
if (len == 0) {
@@ -305,8 +308,7 @@ row_sel_sec_rec_is_for_clust_rec(
if (rec_offs_nth_extern(clust_offs, clust_pos)) {
dptr = btr_copy_externally_stored_field(
&clust_len, dptr,
- page_size_t(clust_index->table->space
- ->flags),
+ clust_index->table->space->zip_size(),
len, heap);
}
@@ -529,7 +531,7 @@ row_sel_fetch_columns(
data = btr_rec_copy_externally_stored_field(
rec, offsets,
- dict_table_page_size(index->table),
+ index->table->space->zip_size(),
field_no, &len, heap);
/* data == NULL means that the
@@ -1132,7 +1134,7 @@ re_scan:
cur_block = buf_page_get_gen(
page_id_t(index->table->space_id, page_no),
- page_size_t(index->table->space->flags),
+ index->table->space->zip_size(),
RW_X_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, mtr, &err);
} else {
@@ -1487,7 +1489,7 @@ row_sel_try_search_shortcut(
const rec_t* rec = btr_pcur_get_rec(&(plan->pcur));
- if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) {
+ if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) {
retry:
rw_lock_s_unlock(ahi_latch);
return(SEL_RETRY);
@@ -1787,7 +1789,7 @@ skip_lock:
goto next_rec;
}
- if (rec_is_metadata(rec, index)) {
+ if (rec_is_metadata(rec, *index)) {
/* Skip the metadata pseudo-record. */
cost_counter++;
goto next_rec;
@@ -2693,44 +2695,6 @@ row_sel_convert_mysql_key_to_innobase(
}
/**************************************************************//**
-Stores the row id to the prebuilt struct. */
-static
-void
-row_sel_store_row_id_to_prebuilt(
-/*=============================*/
- row_prebuilt_t* prebuilt, /*!< in/out: prebuilt */
- const rec_t* index_rec, /*!< in: record */
- const dict_index_t* index, /*!< in: index of the record */
- const offset_t* offsets) /*!< in: rec_get_offsets
- (index_rec, index) */
-{
- const byte* data;
- ulint len;
-
- ut_ad(rec_offs_validate(index_rec, index, offsets));
-
- data = rec_get_nth_field(
- index_rec, offsets,
- dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
-
- if (UNIV_UNLIKELY(len != DATA_ROW_ID_LEN)) {
-
- ib::error() << "Row id field is wrong length " << len << " in"
- " index " << index->name
- << " of table " << index->table->name
- << ", Field number "
- << dict_index_get_sys_col_pos(index, DATA_ROW_ID)
- << ", record:";
-
- rec_print_new(stderr, index_rec, offsets);
- putc('\n', stderr);
- ut_error;
- }
-
- ut_memcpy(prebuilt->row_id, data, len);
-}
-
-/**************************************************************//**
Stores a non-SQL-NULL field in the MySQL format. The counterpart of this
function is row_mysql_store_col_in_innobase_format() in row0mysql.cc. */
void
@@ -2744,7 +2708,6 @@ row_sel_field_store_in_mysql_format_func(
const byte* data,
ulint len)
{
- byte* ptr;
#ifdef UNIV_DEBUG
const dict_field_t* field
= templ->is_virtual
@@ -2756,31 +2719,10 @@ row_sel_field_store_in_mysql_format_func(
UNIV_MEM_ASSERT_W(dest, templ->mysql_col_len);
UNIV_MEM_INVALID(dest, templ->mysql_col_len);
+ byte* pad = dest + len;
+
switch (templ->type) {
const byte* field_end;
- byte* pad;
- case DATA_INT:
- /* Convert integer data from Innobase to a little-endian
- format, sign bit restored to normal */
-
- ptr = dest + len;
-
- for (;;) {
- ptr--;
- *ptr = *data;
- if (ptr == dest) {
- break;
- }
- data++;
- }
-
- if (!templ->is_unsigned) {
- dest[len - 1] = (byte) (dest[len - 1] ^ 128);
- }
-
- ut_ad(templ->mysql_col_len == len);
- break;
-
case DATA_VARCHAR:
case DATA_VARMYSQL:
case DATA_BINARY:
@@ -2804,7 +2746,14 @@ row_sel_field_store_in_mysql_format_func(
/* Pad with trailing spaces. */
- pad = dest + len;
+ if (pad == field_end) {
+ break;
+ }
+
+ if (UNIV_UNLIKELY(templ->type == DATA_FIXBINARY)) {
+ memset(pad, 0, field_end - pad);
+ break;
+ }
ut_ad(templ->mbminlen <= templ->mbmaxlen);
@@ -2881,7 +2830,7 @@ row_sel_field_store_in_mysql_format_func(
done in row0mysql.cc, function
row_mysql_store_col_in_innobase_format(). */
- memset(dest + len, 0x20, templ->mysql_col_len - len);
+ memset(pad, 0x20, templ->mysql_col_len - len);
}
break;
@@ -2898,13 +2847,24 @@ row_sel_field_store_in_mysql_format_func(
case DATA_FLOAT:
case DATA_DOUBLE:
case DATA_DECIMAL:
- /* Above are the valid column types for MySQL data. */
#endif /* UNIV_DEBUG */
ut_ad((templ->is_virtual && !field)
|| (field && field->prefix_len
? field->prefix_len == len
: templ->mysql_col_len == len));
memcpy(dest, data, len);
+ break;
+
+ case DATA_INT:
+ /* Convert InnoDB big-endian integer to little-endian
+ format, sign bit restored to 2's complement form */
+ DBUG_ASSERT(templ->mysql_col_len == len);
+
+ byte* ptr = pad;
+ do *--ptr = *data++; while (ptr != dest);
+ if (!templ->is_unsigned) {
+ pad[-1] ^= 0x80;
+ }
}
}
@@ -2968,8 +2928,7 @@ row_sel_store_mysql_field(
causes an assert */
data = btr_rec_copy_externally_stored_field(
- rec, offsets,
- dict_table_page_size(prebuilt->table),
+ rec, offsets, prebuilt->table->space->zip_size(),
field_no, &len, heap);
if (UNIV_UNLIKELY(!data)) {
@@ -3098,9 +3057,6 @@ static bool row_sel_store_mysql_rec(
const mysql_row_templ_t*templ = &prebuilt->mysql_template[i];
if (templ->is_virtual && dict_index_is_clust(index)) {
- /* Virtual columns are never declared NOT NULL. */
- ut_ad(templ->mysql_null_bit_mask);
-
/* Skip virtual columns if it is not a covered
search or virtual key read is not requested. */
if (!rec_clust
@@ -3108,8 +3064,10 @@ static bool row_sel_store_mysql_rec(
|| (!prebuilt->read_just_key
&& !prebuilt->m_read_virtual_key)) {
/* Initialize the NULL bit. */
- mysql_rec[templ->mysql_null_byte_offset]
- |= (byte) templ->mysql_null_bit_mask;
+ if (templ->mysql_null_bit_mask) {
+ mysql_rec[templ->mysql_null_byte_offset]
+ |= (byte) templ->mysql_null_bit_mask;
+ }
continue;
}
@@ -3169,8 +3127,9 @@ static bool row_sel_store_mysql_rec(
= rec_clust
? templ->clust_rec_field_no
: templ->rec_field_no;
- /* We should never deliver column prefixes to MySQL,
- except for evaluating innobase_index_cond(). */
+ /* We should never deliver column prefixes to the SQL layer,
+ except for evaluating handler_index_cond_check()
+ or handler_rowid_filter_check(). */
/* ...actually, we do want to do this in order to
support the prefix query optimization.
@@ -3196,7 +3155,7 @@ static bool row_sel_store_mysql_rec(
if (dict_index_is_clust(index)
|| prebuilt->fts_doc_id_in_read_set) {
prebuilt->fts_doc_id = fts_get_doc_id_from_rec(
- prebuilt->table, rec, index, NULL);
+ rec, index, offsets);
}
}
@@ -3363,7 +3322,7 @@ Row_sel_get_clust_rec_for_mysql::operator()(
and is it not unsafe to use RW_NO_LATCH here? */
buf_block_t* block = buf_page_get_gen(
btr_pcur_get_block(prebuilt->pcur)->page.id,
- dict_table_page_size(sec_index->table),
+ btr_pcur_get_block(prebuilt->pcur)->zip_size(),
RW_NO_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, mtr, &err);
mem_heap_t* heap = mem_heap_create(256);
@@ -3582,7 +3541,7 @@ sel_restore_position_for_mysql(
next:
if (btr_pcur_move_to_next(pcur, mtr)
&& rec_is_metadata(btr_pcur_get_rec(pcur),
- pcur->btr_cur.index)) {
+ *pcur->btr_cur.index)) {
btr_pcur_move_to_next(pcur, mtr);
}
@@ -3598,7 +3557,7 @@ next:
prev:
if (btr_pcur_is_on_user_rec(pcur) && !moves_up
&& !rec_is_metadata(btr_pcur_get_rec(pcur),
- pcur->btr_cur.index)) {
+ *pcur->btr_cur.index)) {
btr_pcur_move_to_prev(pcur, mtr);
}
return true;
@@ -3834,7 +3793,7 @@ row_sel_enqueue_cache_row_for_mysql(
/* For non ICP code path the row should already exist in the
next fetch cache slot. */
- if (prebuilt->idx_cond != NULL) {
+ if (prebuilt->pk_filter || prebuilt->idx_cond) {
byte* dest = row_sel_fetch_last_buf(prebuilt);
ut_memcpy(dest, mysql_rec, prebuilt->mysql_row_len);
@@ -3875,7 +3834,7 @@ row_sel_try_search_shortcut_for_mysql(
BTR_SEARCH_LEAF, pcur, ahi_latch, mtr);
rec = btr_pcur_get_rec(pcur);
- if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, index)) {
+ if (!page_rec_is_user_rec(rec) || rec_is_metadata(rec, *index)) {
retry:
rw_lock_s_unlock(ahi_latch);
return(SEL_RETRY);
@@ -3932,17 +3891,18 @@ row_search_idx_cond_check(
const rec_t* rec, /*!< in: InnoDB record */
const offset_t* offsets) /*!< in: rec_get_offsets() */
{
- ICP_RESULT result;
ulint i;
ut_ad(rec_offs_validate(rec, prebuilt->index, offsets));
if (!prebuilt->idx_cond) {
- return(ICP_MATCH);
+ if (!handler_rowid_filter_is_active(prebuilt->pk_filter)) {
+ return(ICP_MATCH);
+ }
+ } else {
+ MONITOR_INC(MONITOR_ICP_ATTEMPTS);
}
- MONITOR_INC(MONITOR_ICP_ATTEMPTS);
-
/* Convert to MySQL format those fields that are needed for
evaluating the index condition. */
@@ -3972,9 +3932,31 @@ row_search_idx_cond_check(
index, if the case of the column has been updated in
the past, or a record has been deleted and a record
inserted in a different case. */
- result = innobase_index_cond(prebuilt->idx_cond);
+ ICP_RESULT result = prebuilt->idx_cond
+ ? handler_index_cond_check(prebuilt->idx_cond)
+ : ICP_MATCH;
+
switch (result) {
case ICP_MATCH:
+ if (handler_rowid_filter_is_active(prebuilt->pk_filter)) {
+ ut_ad(!prebuilt->index->is_primary());
+ if (prebuilt->clust_index_was_generated) {
+ ulint len;
+ dict_index_t* index = prebuilt->index;
+ const byte* data = rec_get_nth_field(
+ rec, offsets, index->n_fields - 1,
+ &len);
+ ut_ad(dict_index_get_nth_col(index,
+ index->n_fields - 1)
+ ->prtype == (DATA_ROW_ID | DATA_NOT_NULL));
+ ut_ad(len == DATA_ROW_ID_LEN);
+ memcpy(prebuilt->row_id, data, DATA_ROW_ID_LEN);
+ }
+ if (!handler_rowid_filter_check(prebuilt->pk_filter)) {
+ MONITOR_INC(MONITOR_ICP_MATCH);
+ return(ICP_NO_MATCH);
+ }
+ }
/* Convert the remaining fields to MySQL format.
If this is a secondary index record, we must defer
this until we have fetched the clustered index record. */
@@ -4428,7 +4410,7 @@ row_search_mvcc(
mtr.commit(). */
ut_ad(!rec_get_deleted_flag(rec, comp));
- if (prebuilt->idx_cond) {
+ if (prebuilt->pk_filter || prebuilt->idx_cond) {
switch (row_search_idx_cond_check(
buf, prebuilt,
rec, offsets)) {
@@ -4522,6 +4504,13 @@ row_search_mvcc(
set_also_gap_locks = FALSE;
}
+#ifdef WITH_WSREP
+ else if (wsrep_thd_skip_locking(trx->mysql_thd)) {
+ ut_ad(!strcmp(wsrep_get_sr_table_name(),
+ prebuilt->table->name.m_name));
+ set_also_gap_locks = FALSE;
+ }
+#endif /* WITH_WSREP */
/* Note that if the search mode was GE or G, then the cursor
naturally moves upward (in fetch next) in alphabetical order,
@@ -5361,7 +5350,7 @@ requires_clust_rec:
result_rec = clust_rec;
ut_ad(rec_offs_validate(result_rec, clust_index, offsets));
- if (prebuilt->idx_cond) {
+ if (prebuilt->pk_filter || prebuilt->idx_cond) {
/* Convert the record to MySQL format. We were
unable to do this in row_search_idx_cond_check(),
because the condition is on the secondary index
@@ -5422,8 +5411,7 @@ use_covering_index:
/* We only convert from InnoDB row format to MySQL row
format when ICP is disabled. */
- if (!prebuilt->idx_cond) {
-
+ if (!prebuilt->pk_filter && !prebuilt->idx_cond) {
/* We use next_buf to track the allocation of buffers
where we store and enqueue the buffers for our
pre-fetch optimisation.
@@ -5495,7 +5483,7 @@ use_covering_index:
rec_offs_size(offsets));
mach_write_to_4(buf,
rec_offs_extra_size(offsets) + 4);
- } else if (!prebuilt->idx_cond) {
+ } else if (!prebuilt->pk_filter && !prebuilt->idx_cond) {
/* The record was not yet converted to MySQL format. */
if (!row_sel_store_mysql_rec(
buf, prebuilt, result_rec, vrow,
@@ -5514,11 +5502,19 @@ use_covering_index:
}
}
- if (prebuilt->clust_index_was_generated) {
- row_sel_store_row_id_to_prebuilt(
- prebuilt, result_rec,
- result_rec == rec ? index : clust_index,
- offsets);
+ if (!prebuilt->clust_index_was_generated) {
+ } else if (result_rec != rec || index->is_primary()) {
+ memcpy(prebuilt->row_id, result_rec, DATA_ROW_ID_LEN);
+ } else {
+ ulint len;
+ const byte* data = rec_get_nth_field(
+ result_rec, offsets, index->n_fields - 1,
+ &len);
+ ut_ad(dict_index_get_nth_col(index,
+ index->n_fields - 1)
+ ->prtype == (DATA_ROW_ID | DATA_NOT_NULL));
+ ut_ad(len == DATA_ROW_ID_LEN);
+ memcpy(prebuilt->row_id, data, DATA_ROW_ID_LEN);
}
}
@@ -5737,8 +5733,7 @@ normal_return:
DEBUG_SYNC_C("row_search_for_mysql_before_return");
- if (prebuilt->idx_cond != 0) {
-
+ if (prebuilt->pk_filter || prebuilt->idx_cond) {
/* When ICP is active we don't write to the MySQL buffer
directly, only to buffers that are enqueued in the pre-fetch
queue. We need to dequeue the first buffer and copy the contents
diff --git a/storage/innobase/row/row0trunc.cc b/storage/innobase/row/row0trunc.cc
deleted file mode 100644
index a696d0c56ef..00000000000
--- a/storage/innobase/row/row0trunc.cc
+++ /dev/null
@@ -1,1742 +0,0 @@
-/*****************************************************************************
-
-Copyright (c) 2013, 2018, Oracle and/or its affiliates. All Rights Reserved.
-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
-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 Street, Fifth Floor, Boston, MA 02110-1335 USA
-
-*****************************************************************************/
-
-/**************************************************//**
-@file row/row0trunc.cc
-TRUNCATE implementation
-
-Created 2013-04-12 Sunny Bains
-*******************************************************/
-
-#include "row0trunc.h"
-#include "btr0sea.h"
-#include "pars0pars.h"
-#include "btr0pcur.h"
-#include "dict0crea.h"
-#include "dict0stats.h"
-#include "dict0stats_bg.h"
-#include "lock0lock.h"
-#include "fts0fts.h"
-#include "ibuf0ibuf.h"
-#include "os0file.h"
-#include "que0que.h"
-#include "trx0undo.h"
-
-/* FIXME: For temporary tables, use a simple approach of btr_free()
-and btr_create() of each index tree. */
-
-/* FIXME: For persistent tables, remove this code in MDEV-11655
-and use a combination of the transactional DDL log to make atomic the
-low-level operations ha_innobase::delete_table(), ha_innobase::create(). */
-
-bool truncate_t::s_fix_up_active = false;
-truncate_t::tables_t truncate_t::s_tables;
-truncate_t::truncated_tables_t truncate_t::s_truncated_tables;
-
-/**
-Iterator over the the raw records in an index, doesn't support MVCC. */
-class IndexIterator {
-
-public:
- /**
- Iterate over an indexes records
- @param index index to iterate over */
- explicit IndexIterator(dict_index_t* index)
- :
- m_index(index)
- {
- /* Do nothing */
- }
-
- /**
- Search for key. Position the cursor on a record GE key.
- @return DB_SUCCESS or error code. */
- dberr_t search(dtuple_t& key, bool noredo)
- {
- mtr_start(&m_mtr);
-
- if (noredo) {
- mtr_set_log_mode(&m_mtr, MTR_LOG_NO_REDO);
- }
-
- btr_pcur_open_on_user_rec(
- m_index,
- &key,
- PAGE_CUR_GE,
- BTR_MODIFY_LEAF,
- &m_pcur, &m_mtr);
-
- return(DB_SUCCESS);
- }
-
- /**
- Iterate over all the records
- @return DB_SUCCESS or error code */
- template <typename Callback>
- dberr_t for_each(Callback& callback)
- {
- dberr_t err = DB_SUCCESS;
-
- for (;;) {
-
- if (!btr_pcur_is_on_user_rec(&m_pcur)
- || !callback.match(&m_pcur)) {
-
- /* The end of of the index has been reached. */
- err = DB_END_OF_INDEX;
- break;
- }
-
- rec_t* rec = btr_pcur_get_rec(&m_pcur);
-
- if (!rec_get_deleted_flag(rec, FALSE)) {
-
- err = callback(&m_mtr, &m_pcur);
-
- if (err != DB_SUCCESS) {
- break;
- }
- }
-
- btr_pcur_move_to_next_user_rec(&m_pcur, &m_mtr);
- }
-
- btr_pcur_close(&m_pcur);
- mtr_commit(&m_mtr);
-
- return(err == DB_END_OF_INDEX ? DB_SUCCESS : err);
- }
-
-private:
- // Disable copying
- IndexIterator(const IndexIterator&);
- IndexIterator& operator=(const IndexIterator&);
-
-private:
- mtr_t m_mtr;
- btr_pcur_t m_pcur;
- dict_index_t* m_index;
-};
-
-/** SysIndex table iterator, iterate over records for a table. */
-class SysIndexIterator {
-
-public:
- /**
- Iterate over all the records that match the table id.
- @return DB_SUCCESS or error code */
- template <typename Callback>
- dberr_t for_each(Callback& callback) const
- {
- dict_index_t* sys_index;
- byte buf[DTUPLE_EST_ALLOC(1)];
- dtuple_t* tuple =
- dtuple_create_from_mem(buf, sizeof(buf), 1, 0);
- dfield_t* dfield = dtuple_get_nth_field(tuple, 0);
-
- dfield_set_data(
- dfield,
- callback.table_id(),
- sizeof(*callback.table_id()));
-
- sys_index = dict_table_get_first_index(dict_sys->sys_indexes);
-
- dict_index_copy_types(tuple, sys_index, 1);
-
- IndexIterator iterator(sys_index);
-
- /* Search on the table id and position the cursor
- on GE table_id. */
- iterator.search(*tuple, callback.get_logging_status());
-
- return(iterator.for_each(callback));
- }
-};
-
-/** Generic callback abstract class. */
-class Callback
-{
-
-public:
- /**
- Constructor
- @param table_id id of the table being operated.
- @param noredo if true turn off logging. */
- Callback(table_id_t table_id, bool noredo)
- :
- m_id(),
- m_noredo(noredo)
- {
- /* Convert to storage byte order. */
- mach_write_to_8(&m_id, table_id);
- }
-
- /**
- Destructor */
- virtual ~Callback()
- {
- /* Do nothing */
- }
-
- /**
- @param pcur persistent cursor used for iteration
- @return true if the table id column matches. */
- bool match(btr_pcur_t* pcur) const
- {
- ulint len;
- const byte* field;
- rec_t* rec = btr_pcur_get_rec(pcur);
-
- field = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_INDEXES__TABLE_ID, &len);
-
- ut_ad(len == 8);
-
- return(memcmp(&m_id, field, len) == 0);
- }
-
- /**
- @return pointer to table id storage format buffer */
- const table_id_t* table_id() const
- {
- return(&m_id);
- }
-
- /**
- @return return if logging needs to be turned off. */
- bool get_logging_status() const
- {
- return(m_noredo);
- }
-
-protected:
- // Disably copying
- Callback(const Callback&);
- Callback& operator=(const Callback&);
-
-protected:
- /** Table id in storage format */
- table_id_t m_id;
-
- /** Turn off logging. */
- const bool m_noredo;
-};
-
-/**
-Scan to find out truncate log file from the given directory path.
-
-@param dir_path look for log directory in following path.
-@param log_files cache to hold truncate log file name found.
-@return DB_SUCCESS or error code. */
-dberr_t
-TruncateLogParser::scan(
- const char* dir_path,
- trunc_log_files_t& log_files)
-{
- os_file_dir_t dir;
- os_file_stat_t fileinfo;
- dberr_t err = DB_SUCCESS;
- const ulint dir_len = strlen(dir_path);
-
- /* Scan and look out for the truncate log files. */
- dir = os_file_opendir(dir_path, true);
- if (dir == NULL) {
- return(DB_IO_ERROR);
- }
-
- while (fil_file_readdir_next_file(
- &err, dir_path, dir, &fileinfo) == 0) {
-
- const size_t nm_len = strlen(fileinfo.name);
-
- if (fileinfo.type == OS_FILE_TYPE_FILE
- && nm_len > sizeof "ib_trunc.log"
- && (0 == strncmp(fileinfo.name + nm_len
- - ((sizeof "trunc.log") - 1),
- "trunc.log", (sizeof "trunc.log") - 1))
- && (0 == strncmp(fileinfo.name, "ib_", 3))) {
-
- if (fileinfo.size == 0) {
- /* Truncate log not written. Remove the file. */
- os_file_delete(
- innodb_log_file_key, fileinfo.name);
- continue;
- }
-
- /* Construct file name by appending directory path */
- ulint sz = dir_len + 22 + 22 + sizeof "ib_trunc.log";
- char* log_file_name = UT_NEW_ARRAY_NOKEY(char, sz);
- if (log_file_name == NULL) {
- err = DB_OUT_OF_MEMORY;
- break;
- }
-
- memcpy(log_file_name, dir_path, dir_len);
- char* e = log_file_name + dir_len;
- if (e[-1] != OS_PATH_SEPARATOR) {
- *e++ = OS_PATH_SEPARATOR;
- }
- strcpy(e, fileinfo.name);
- log_files.push_back(log_file_name);
- }
- }
-
- os_file_closedir(dir);
-
- return(err);
-}
-
-/**
-Parse the log file and populate table to truncate information.
-(Add this table to truncate information to central vector that is then
- used by truncate fix-up routine to fix-up truncate action of the table.)
-
-@param log_file_name log file to parse
-@return DB_SUCCESS or error code. */
-dberr_t
-TruncateLogParser::parse(
- const char* log_file_name)
-{
- dberr_t err = DB_SUCCESS;
- truncate_t* truncate = NULL;
-
- /* Open the file and read magic-number to findout if truncate action
- was completed. */
- bool ret;
- os_file_t handle = os_file_create_simple(
- innodb_log_file_key, log_file_name,
- OS_FILE_OPEN, OS_FILE_READ_ONLY, srv_read_only_mode, &ret);
- if (!ret) {
- ib::error() << "Error opening truncate log file: "
- << log_file_name;
- return(DB_IO_ERROR);
- }
-
- ulint sz = srv_page_size;
- void* buf = ut_zalloc_nokey(sz + srv_page_size);
- if (buf == 0) {
- os_file_close(handle);
- return(DB_OUT_OF_MEMORY);
- }
-
- IORequest request(IORequest::READ);
-
- /* Align the memory for file i/o if we might have O_DIRECT set*/
- byte* log_buf = static_cast<byte*>(ut_align(buf, srv_page_size));
-
- do {
- err = os_file_read(request, handle, log_buf, 0, sz);
-
- if (err != DB_SUCCESS) {
- os_file_close(handle);
- break;
- }
-
- if (mach_read_from_4(log_buf) == 32743712) {
-
- /* Truncate action completed. Avoid parsing the file. */
- os_file_close(handle);
-
- os_file_delete(innodb_log_file_key, log_file_name);
- break;
- }
-
- if (truncate == NULL) {
- truncate = UT_NEW_NOKEY(truncate_t(log_file_name));
- if (truncate == NULL) {
- os_file_close(handle);
- err = DB_OUT_OF_MEMORY;
- break;
- }
- }
-
- err = truncate->parse(log_buf + 4, log_buf + sz - 4);
-
- if (err != DB_SUCCESS) {
-
- ut_ad(err == DB_FAIL);
-
- ut_free(buf);
- buf = 0;
-
- sz *= 2;
-
- buf = ut_zalloc_nokey(sz + srv_page_size);
-
- if (buf == 0) {
- os_file_close(handle);
- err = DB_OUT_OF_MEMORY;
- UT_DELETE(truncate);
- truncate = NULL;
- break;
- }
-
- log_buf = static_cast<byte*>(
- ut_align(buf, srv_page_size));
- }
- } while (err != DB_SUCCESS);
-
- ut_free(buf);
-
- if (err == DB_SUCCESS && truncate != NULL) {
- truncate_t::add(truncate);
- os_file_close(handle);
- }
-
- return(err);
-}
-
-/**
-Scan and Parse truncate log files.
-
-@param dir_path look for log directory in following path
-@return DB_SUCCESS or error code. */
-dberr_t
-TruncateLogParser::scan_and_parse(
- const char* dir_path)
-{
- dberr_t err;
- trunc_log_files_t log_files;
-
- /* Scan and trace all the truncate log files. */
- err = TruncateLogParser::scan(dir_path, log_files);
-
- /* Parse truncate lof files if scan was successful. */
- if (err == DB_SUCCESS) {
-
- for (ulint i = 0;
- i < log_files.size() && err == DB_SUCCESS;
- i++) {
- err = TruncateLogParser::parse(log_files[i]);
- }
- }
-
- trunc_log_files_t::const_iterator end = log_files.end();
- for (trunc_log_files_t::const_iterator it = log_files.begin();
- it != end;
- ++it) {
- if (*it != NULL) {
- UT_DELETE_ARRAY(*it);
- }
- }
- log_files.clear();
-
- return(err);
-}
-
-/** Check for presence of table-id in SYS_XXXX tables. */
-class TableLocator : public Callback {
-
-public:
- /**
- Constructor
- @param table_id table_id to look for */
- explicit TableLocator(table_id_t table_id)
- :
- Callback(table_id, false),
- m_table_found()
- {
- /* No op */
- }
-
- /**
- @return true if table is found */
- bool is_table_found() const
- {
- return(m_table_found);
- }
-
- /**
- Look for table-id in SYS_XXXX tables without loading the table.
-
- @param pcur persistent cursor used for reading
- @return DB_SUCCESS */
- dberr_t operator()(mtr_t*, btr_pcur_t*)
- {
- m_table_found = true;
- return(DB_SUCCESS);
- }
-
-private:
- /** Set to true if table is present */
- bool m_table_found;
-};
-
-/**
-Update system table to reflect new table id.
-@param old_table_id old table id
-@param new_table_id new table id
-@param reserve_dict_mutex if TRUE, acquire/release
- dict_sys->mutex around call to pars_sql.
-@param trx transaction
-@return error code or DB_SUCCESS */
-static MY_ATTRIBUTE((warn_unused_result))
-dberr_t
-row_truncate_update_table_id(
- table_id_t old_table_id,
- table_id_t new_table_id,
- ibool reserve_dict_mutex,
- trx_t* trx)
-{
- pars_info_t* info = NULL;
- dberr_t err = DB_SUCCESS;
-
- /* Scan the SYS_XXXX table and update to reflect new table-id. */
- info = pars_info_create();
- pars_info_add_ull_literal(info, "old_id", old_table_id);
- pars_info_add_ull_literal(info, "new_id", new_table_id);
-
- err = que_eval_sql(
- info,
- "PROCEDURE RENUMBER_TABLE_ID_PROC () IS\n"
- "BEGIN\n"
- "UPDATE SYS_TABLES"
- " SET ID = :new_id\n"
- " WHERE ID = :old_id;\n"
- "UPDATE SYS_COLUMNS SET TABLE_ID = :new_id\n"
- " WHERE TABLE_ID = :old_id;\n"
- "UPDATE SYS_INDEXES"
- " SET TABLE_ID = :new_id\n"
- " WHERE TABLE_ID = :old_id;\n"
- "UPDATE SYS_VIRTUAL"
- " SET TABLE_ID = :new_id\n"
- " WHERE TABLE_ID = :old_id;\n"
- "END;\n", reserve_dict_mutex, trx);
-
- return(err);
-}
-
-/**
-Get the table id to truncate.
-@param truncate_t old/new table id of table to truncate
-@return table_id_t table_id to use in SYS_XXXX table update. */
-static MY_ATTRIBUTE((warn_unused_result))
-table_id_t
-row_truncate_get_trunc_table_id(
- const truncate_t& truncate)
-{
- TableLocator tableLocator(truncate.old_table_id());
-
- SysIndexIterator().for_each(tableLocator);
-
- return(tableLocator.is_table_found() ?
- truncate.old_table_id(): truncate.new_table_id());
-}
-
-/**
-Update system table to reflect new table id and root page number.
-@param truncate_t old/new table id of table to truncate
- and updated root_page_no of indexes.
-@param new_table_id new table id
-@param reserve_dict_mutex if TRUE, acquire/release
- dict_sys->mutex around call to pars_sql.
-@param mark_index_corrupted if true, then mark index corrupted.
-@return error code or DB_SUCCESS */
-static MY_ATTRIBUTE((warn_unused_result))
-dberr_t
-row_truncate_update_sys_tables_during_fix_up(
- const truncate_t& truncate,
- table_id_t new_table_id,
- ibool reserve_dict_mutex,
- bool mark_index_corrupted)
-{
- trx_t* trx = trx_create();
-
- trx_set_dict_operation(trx, TRX_DICT_OP_TABLE);
-
- table_id_t table_id = row_truncate_get_trunc_table_id(truncate);
-
- /* Step-1: Update the root-page-no */
-
- dberr_t err;
-
- err = truncate.update_root_page_no(
- trx, table_id, reserve_dict_mutex, mark_index_corrupted);
-
- if (err != DB_SUCCESS) {
- return(err);
- }
-
- /* Step-2: Update table-id. */
-
- err = row_truncate_update_table_id(
- table_id, new_table_id, reserve_dict_mutex, trx);
-
- if (err == DB_SUCCESS) {
- dict_mutex_enter_for_mysql();
-
- /* Remove the table with old table_id from cache. */
- dict_table_t* old_table = dict_table_open_on_id(
- table_id, true, DICT_TABLE_OP_NORMAL);
-
- if (old_table != NULL) {
- dict_table_close(old_table, true, false);
- dict_table_remove_from_cache(old_table);
- }
-
- /* Open table with new table_id and set table as
- corrupted if it has FTS index. */
-
- dict_table_t* table = dict_table_open_on_id(
- new_table_id, true, DICT_TABLE_OP_NORMAL);
- ut_ad(table->id == new_table_id);
-
- bool has_internal_doc_id =
- dict_table_has_fts_index(table)
- || DICT_TF2_FLAG_IS_SET(
- table, DICT_TF2_FTS_HAS_DOC_ID);
-
- if (has_internal_doc_id) {
- trx->dict_operation_lock_mode = RW_X_LATCH;
- fts_check_corrupt(table, trx);
- trx->dict_operation_lock_mode = 0;
- }
-
- dict_table_close(table, true, false);
- dict_mutex_exit_for_mysql();
- }
-
- trx_commit_for_mysql(trx);
- trx_free(trx);
-
- return(err);
-}
-
-/********************************************************//**
-Recreates table indexes by applying
-TRUNCATE log record during recovery.
-@return DB_SUCCESS or error code */
-static
-dberr_t
-fil_recreate_table(
-/*===============*/
- ulint format_flags, /*!< in: page format */
- const char* name, /*!< in: table name */
- truncate_t& truncate) /*!< in: The information of
- TRUNCATE log record */
-{
- ut_ad(!truncate_t::s_fix_up_active);
- truncate_t::s_fix_up_active = true;
-
- /* Step-1: Scan for active indexes from REDO logs and drop
- all the indexes using low level function that take root_page_no
- and space-id. */
- truncate.drop_indexes(fil_system.sys_space);
-
- /* Step-2: Scan for active indexes and re-create them. */
- dberr_t err = truncate.create_indexes(
- name, fil_system.sys_space, format_flags);
- if (err != DB_SUCCESS) {
- ib::info() << "Recovery failed for TRUNCATE TABLE '"
- << name << "' within the system tablespace";
- }
-
- truncate_t::s_fix_up_active = false;
-
- return(err);
-}
-
-/********************************************************//**
-Recreates the tablespace and table indexes by applying
-TRUNCATE log record during recovery.
-@return DB_SUCCESS or error code */
-static
-dberr_t
-fil_recreate_tablespace(
-/*====================*/
- ulint space_id, /*!< in: space id */
- ulint format_flags, /*!< in: page format */
- ulint flags, /*!< in: tablespace flags */
- const char* name, /*!< in: table name */
- truncate_t& truncate, /*!< in: The information of
- TRUNCATE log record */
- lsn_t recv_lsn) /*!< in: the end LSN of
- the log record */
-{
- dberr_t err = DB_SUCCESS;
- mtr_t mtr;
-
- ut_ad(!truncate_t::s_fix_up_active);
- truncate_t::s_fix_up_active = true;
-
- /* Step-1: Invalidate buffer pool pages belonging to the tablespace
- to re-create. */
- buf_LRU_flush_or_remove_pages(space_id, NULL);
-
- /* Remove all insert buffer entries for the tablespace */
- ibuf_delete_for_discarded_space(space_id);
-
- /* Step-2: truncate tablespace (reset the size back to original or
- default size) of tablespace. */
- err = truncate.truncate(
- space_id, truncate.get_dir_path(), name, flags, true);
-
- if (err != DB_SUCCESS) {
-
- ib::info() << "Cannot access .ibd file for table '"
- << name << "' with tablespace " << space_id
- << " while truncating";
- return(DB_ERROR);
- }
-
- fil_space_t* space = fil_space_acquire(space_id);
- if (!space) {
- ib::info() << "Missing .ibd file for table '" << name
- << "' with tablespace " << space_id;
- return(DB_ERROR);
- }
-
- const page_size_t page_size(space->flags);
-
- /* Step-3: Initialize Header. */
- if (page_size.is_compressed()) {
- byte* buf;
- page_t* page;
-
- buf = static_cast<byte*>(
- ut_zalloc_nokey(3U << srv_page_size_shift));
-
- /* Align the memory for file i/o */
- page = static_cast<byte*>(ut_align(buf, srv_page_size));
-
- flags |= FSP_FLAGS_PAGE_SSIZE();
-
- fsp_header_init_fields(page, space_id, flags);
-
- mach_write_to_4(
- page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space_id);
-
- page_zip_des_t page_zip;
- page_zip_set_size(&page_zip, page_size.physical());
- page_zip.data = page + srv_page_size;
-
-#ifdef UNIV_DEBUG
- page_zip.m_start =
-#endif /* UNIV_DEBUG */
- page_zip.m_end = page_zip.m_nonempty = page_zip.n_blobs = 0;
- buf_flush_init_for_writing(NULL, page, &page_zip, 0);
-
- err = fil_io(IORequestWrite, true, page_id_t(space_id, 0),
- page_size, 0, page_size.physical(), page_zip.data,
- NULL);
-
- ut_free(buf);
-
- if (err != DB_SUCCESS) {
- ib::info() << "Failed to clean header of the"
- " table '" << name << "' with tablespace "
- << space_id;
- goto func_exit;
- }
- }
-
- mtr_start(&mtr);
- /* Don't log the operation while fixing up table truncate operation
- as crash at this level can still be sustained with recovery restarting
- from last checkpoint. */
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
-
- /* Initialize the first extent descriptor page and
- the second bitmap page for the new tablespace. */
- fsp_header_init(space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
- mtr_commit(&mtr);
-
- /* Step-4: Re-Create Indexes to newly re-created tablespace.
- This operation will restore tablespace back to what it was
- when it was created during CREATE TABLE. */
- err = truncate.create_indexes(name, space, format_flags);
- if (err != DB_SUCCESS) {
- goto func_exit;
- }
-
- /* Step-5: Write new created pages into ibd file handle and
- flush it to disk for the tablespace, in case i/o-handler thread
- deletes the bitmap page from buffer. */
- mtr_start(&mtr);
-
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
-
- for (ulint page_no = 0;
- page_no < UT_LIST_GET_FIRST(space->chain)->size; ++page_no) {
-
- const page_id_t cur_page_id(space_id, page_no);
-
- buf_block_t* block = buf_page_get(cur_page_id, page_size,
- RW_X_LATCH, &mtr);
-
- byte* page = buf_block_get_frame(block);
-
- if (!FSP_FLAGS_GET_ZIP_SSIZE(flags)) {
- ut_ad(!page_size.is_compressed());
-
- buf_flush_init_for_writing(
- block, page, NULL, recv_lsn);
-
- err = fil_io(IORequestWrite, true, cur_page_id,
- page_size, 0, srv_page_size, page, NULL);
- } else {
- ut_ad(page_size.is_compressed());
-
- /* We don't want to rewrite empty pages. */
-
- if (fil_page_get_type(page) != 0) {
- page_zip_des_t* page_zip =
- buf_block_get_page_zip(block);
-
- buf_flush_init_for_writing(
- block, page, page_zip, recv_lsn);
-
- err = fil_io(IORequestWrite, true,
- cur_page_id,
- page_size, 0,
- page_size.physical(),
- page_zip->data, NULL);
- } else {
-#ifdef UNIV_DEBUG
- const byte* data = block->page.zip.data;
-
- /* Make sure that the page is really empty */
- for (ulint i = 0;
- i < page_size.physical();
- ++i) {
-
- ut_a(data[i] == 0);
- }
-#endif /* UNIV_DEBUG */
- }
- }
-
- if (err != DB_SUCCESS) {
- ib::info() << "Cannot write page " << page_no
- << " into a .ibd file for table '"
- << name << "' with tablespace " << space_id;
- }
- }
-
- mtr_commit(&mtr);
-
- truncate_t::s_fix_up_active = false;
-func_exit:
- space->release();
- return(err);
-}
-
-/**
-Fix the table truncate by applying information parsed from TRUNCATE log.
-Fix-up includes re-creating table (drop and re-create indexes)
-@return error code or DB_SUCCESS */
-dberr_t
-truncate_t::fixup_tables_in_system_tablespace()
-{
- dberr_t err = DB_SUCCESS;
-
- /* Using the info cached during REDO log scan phase fix the
- table truncate. */
-
- for (tables_t::iterator it = s_tables.begin();
- it != s_tables.end();) {
-
- if ((*it)->m_space_id == TRX_SYS_SPACE) {
- /* Step-1: Drop and re-create indexes. */
- ib::info() << "Completing truncate for table with "
- "id (" << (*it)->m_old_table_id << ") "
- "residing in the system tablespace.";
-
- err = fil_recreate_table(
- (*it)->m_format_flags,
- (*it)->m_tablename,
- **it);
-
- /* Step-2: Update the SYS_XXXX tables to reflect
- this new table_id and root_page_no. */
- table_id_t new_id;
-
- dict_hdr_get_new_id(&new_id, NULL, NULL, NULL, true);
-
- err = row_truncate_update_sys_tables_during_fix_up(
- **it, new_id, TRUE,
- (err == DB_SUCCESS) ? false : true);
-
- if (err != DB_SUCCESS) {
- break;
- }
-
- os_file_delete(
- innodb_log_file_key, (*it)->m_log_file_name);
- UT_DELETE(*it);
- it = s_tables.erase(it);
- } else {
- ++it;
- }
- }
-
- /* Also clear the map used to track tablespace truncated. */
- s_truncated_tables.clear();
-
- return(err);
-}
-
-/**
-Fix the table truncate by applying information parsed from TRUNCATE log.
-Fix-up includes re-creating tablespace.
-@return error code or DB_SUCCESS */
-dberr_t
-truncate_t::fixup_tables_in_non_system_tablespace()
-{
- dberr_t err = DB_SUCCESS;
-
- /* Using the info cached during REDO log scan phase fix the
- table truncate. */
- tables_t::iterator end = s_tables.end();
-
- for (tables_t::iterator it = s_tables.begin(); it != end; ++it) {
-
- /* All tables in the system tablespace have already been
- done and erased from this list. */
- ut_a((*it)->m_space_id != TRX_SYS_SPACE);
-
- /* Drop tablespace, drop indexes and re-create indexes. */
-
- ib::info() << "Completing truncate for table with "
- "id (" << (*it)->m_old_table_id << ") "
- "residing in file-per-table tablespace with "
- "id (" << (*it)->m_space_id << ")";
-
- fil_space_t* space = fil_space_get((*it)->m_space_id);
-
- if (!space) {
- /* Create the database directory for name,
- if it does not exist yet */
- fil_create_directory_for_tablename(
- (*it)->m_tablename);
-
- space = fil_ibd_create((*it)->m_space_id,
- (*it)->m_tablename,
- (*it)->m_dir_path,
- (*it)->m_tablespace_flags,
- FIL_IBD_FILE_INITIAL_SIZE,
- (*it)->m_encryption,
- (*it)->m_key_id, &err);
- if (!space) {
- /* If checkpoint is not yet done
- and table is dropped and then we might
- still have REDO entries for this table
- which are INVALID. Ignore them. */
- ib::warn() << "Failed to create"
- " tablespace for "
- << (*it)->m_space_id
- << " space-id";
- err = DB_ERROR;
- break;
- }
- }
-
- err = fil_recreate_tablespace(
- (*it)->m_space_id,
- (*it)->m_format_flags,
- (*it)->m_tablespace_flags,
- (*it)->m_tablename,
- **it, log_get_lsn());
-
- /* Step-2: Update the SYS_XXXX tables to reflect new
- table-id and root_page_no. */
- table_id_t new_id;
-
- dict_hdr_get_new_id(&new_id, NULL, NULL, NULL, true);
-
- err = row_truncate_update_sys_tables_during_fix_up(
- **it, new_id, TRUE, (err == DB_SUCCESS) ? false : true);
-
- if (err != DB_SUCCESS) {
- break;
- }
- }
-
- if (err == DB_SUCCESS && s_tables.size() > 0) {
-
- log_make_checkpoint();
- }
-
- for (ulint i = 0; i < s_tables.size(); ++i) {
- os_file_delete(
- innodb_log_file_key, s_tables[i]->m_log_file_name);
- UT_DELETE(s_tables[i]);
- }
-
- s_tables.clear();
-
- return(err);
-}
-
-/**
-Constructor
-
-@param old_table_id old table id assigned to table before truncate
-@param new_table_id new table id that will be assigned to table
- after truncate
-@param dir_path directory path */
-
-truncate_t::truncate_t(
- table_id_t old_table_id,
- table_id_t new_table_id,
- const char* dir_path)
- :
- m_space_id(),
- m_old_table_id(old_table_id),
- m_new_table_id(new_table_id),
- m_dir_path(),
- m_tablename(),
- m_tablespace_flags(),
- m_format_flags(),
- m_indexes(),
- m_log_lsn(),
- m_log_file_name(),
- /* JAN: TODO: Encryption */
- m_encryption(FIL_ENCRYPTION_DEFAULT),
- m_key_id(FIL_DEFAULT_ENCRYPTION_KEY)
-{
- if (dir_path != NULL) {
- m_dir_path = mem_strdup(dir_path);
- }
-}
-
-/**
-Consturctor
-
-@param log_file_name parse the log file during recovery to populate
- information related to table to truncate */
-truncate_t::truncate_t(
- const char* log_file_name)
- :
- m_space_id(),
- m_old_table_id(),
- m_new_table_id(),
- m_dir_path(),
- m_tablename(),
- m_tablespace_flags(),
- m_format_flags(),
- m_indexes(),
- m_log_lsn(),
- m_log_file_name(),
- /* JAN: TODO: Encryption */
- m_encryption(FIL_ENCRYPTION_DEFAULT),
- m_key_id(FIL_DEFAULT_ENCRYPTION_KEY)
-
-{
- m_log_file_name = mem_strdup(log_file_name);
- if (m_log_file_name == NULL) {
- ib::fatal() << "Failed creating truncate_t; out of memory";
- }
-}
-
-/** Constructor */
-
-truncate_t::index_t::index_t()
- :
- m_id(),
- m_type(),
- m_root_page_no(FIL_NULL),
- m_new_root_page_no(FIL_NULL),
- m_n_fields(),
- m_trx_id_pos(ULINT_UNDEFINED),
- m_fields()
-{
- /* Do nothing */
-}
-
-/** Destructor */
-
-truncate_t::~truncate_t()
-{
- if (m_dir_path != NULL) {
- ut_free(m_dir_path);
- m_dir_path = NULL;
- }
-
- if (m_tablename != NULL) {
- ut_free(m_tablename);
- m_tablename = NULL;
- }
-
- if (m_log_file_name != NULL) {
- ut_free(m_log_file_name);
- m_log_file_name = NULL;
- }
-
- m_indexes.clear();
-}
-
-/**
-@return number of indexes parsed from the log record */
-
-size_t
-truncate_t::indexes() const
-{
- return(m_indexes.size());
-}
-
-/**
-Update root page number in SYS_XXXX tables.
-
-@param trx transaction object
-@param table_id table id for which information needs to
- be updated.
-@param reserve_dict_mutex if TRUE, acquire/release
- dict_sys->mutex around call to pars_sql.
-@param mark_index_corrupted if true, then mark index corrupted.
-@return DB_SUCCESS or error code */
-
-dberr_t
-truncate_t::update_root_page_no(
- trx_t* trx,
- table_id_t table_id,
- ibool reserve_dict_mutex,
- bool mark_index_corrupted) const
-{
- indexes_t::const_iterator end = m_indexes.end();
-
- dberr_t err = DB_SUCCESS;
-
- for (indexes_t::const_iterator it = m_indexes.begin();
- it != end;
- ++it) {
-
- pars_info_t* info = pars_info_create();
-
- pars_info_add_int4_literal(
- info, "page_no", it->m_new_root_page_no);
-
- pars_info_add_ull_literal(info, "table_id", table_id);
-
- pars_info_add_ull_literal(
- info, "index_id",
- (mark_index_corrupted ? IB_ID_MAX : it->m_id));
-
- err = que_eval_sql(
- info,
- "PROCEDURE RENUMBER_IDX_PAGE_NO_PROC () IS\n"
- "BEGIN\n"
- "UPDATE SYS_INDEXES"
- " SET PAGE_NO = :page_no\n"
- " WHERE TABLE_ID = :table_id"
- " AND ID = :index_id;\n"
- "END;\n", reserve_dict_mutex, trx);
-
- if (err != DB_SUCCESS) {
- break;
- }
- }
-
- return(err);
-}
-
-/**
-Check whether a tablespace was truncated during recovery
-@param space_id tablespace id to check
-@return true if the tablespace was truncated */
-
-bool
-truncate_t::is_tablespace_truncated(ulint space_id)
-{
- tables_t::iterator end = s_tables.end();
-
- for (tables_t::iterator it = s_tables.begin(); it != end; ++it) {
-
- if ((*it)->m_space_id == space_id) {
-
- return(true);
- }
- }
-
- return(false);
-}
-
-/** Was tablespace truncated (on crash before checkpoint).
-If the MLOG_TRUNCATE redo-record is still available then tablespace
-was truncated and checkpoint is yet to happen.
-@param[in] space_id tablespace id to check.
-@return true if tablespace is was truncated. */
-bool
-truncate_t::was_tablespace_truncated(ulint space_id)
-{
- return(s_truncated_tables.find(space_id) != s_truncated_tables.end());
-}
-
-/** Get the lsn associated with space.
-@param[in] space_id tablespace id to check.
-@return associated lsn. */
-lsn_t
-truncate_t::get_truncated_tablespace_init_lsn(ulint space_id)
-{
- ut_ad(was_tablespace_truncated(space_id));
-
- return(s_truncated_tables.find(space_id)->second);
-}
-
-/**
-Parses log record during recovery
-@param start_ptr buffer containing log body to parse
-@param end_ptr buffer end
-
-@return DB_SUCCESS or error code */
-
-dberr_t
-truncate_t::parse(
- byte* start_ptr,
- const byte* end_ptr)
-{
- /* Parse lsn, space-id, format-flags and tablespace-flags. */
- if (end_ptr < start_ptr + (8 + 4 + 4 + 4)) {
- return(DB_FAIL);
- }
-
- m_log_lsn = mach_read_from_8(start_ptr);
- start_ptr += 8;
-
- m_space_id = mach_read_from_4(start_ptr);
- start_ptr += 4;
-
- m_format_flags = mach_read_from_4(start_ptr);
- start_ptr += 4;
-
- m_tablespace_flags = mach_read_from_4(start_ptr);
- start_ptr += 4;
-
- /* Parse table-name. */
- if (end_ptr < start_ptr + (2)) {
- return(DB_FAIL);
- }
-
- ulint n_tablename_len = mach_read_from_2(start_ptr);
- start_ptr += 2;
-
- if (n_tablename_len > 0) {
- if (end_ptr < start_ptr + n_tablename_len) {
- return(DB_FAIL);
- }
- m_tablename = mem_strdup(reinterpret_cast<char*>(start_ptr));
- ut_ad(m_tablename[n_tablename_len - 1] == 0);
- start_ptr += n_tablename_len;
- }
-
-
- /* Parse and read old/new table-id, number of indexes */
- if (end_ptr < start_ptr + (8 + 8 + 2 + 2)) {
- return(DB_FAIL);
- }
-
- ut_ad(m_indexes.empty());
-
- m_old_table_id = mach_read_from_8(start_ptr);
- start_ptr += 8;
-
- m_new_table_id = mach_read_from_8(start_ptr);
- start_ptr += 8;
-
- ulint n_indexes = mach_read_from_2(start_ptr);
- start_ptr += 2;
-
- /* Parse the remote directory from TRUNCATE log record */
- {
- ulint n_tabledirpath_len = mach_read_from_2(start_ptr);
- start_ptr += 2;
-
- if (end_ptr < start_ptr + n_tabledirpath_len) {
- return(DB_FAIL);
- }
-
- if (n_tabledirpath_len > 0) {
-
- m_dir_path = mem_strdup(reinterpret_cast<char*>(start_ptr));
- ut_ad(m_dir_path[n_tabledirpath_len - 1] == 0);
- start_ptr += n_tabledirpath_len;
- }
- }
-
- /* Parse index ids and types from TRUNCATE log record */
- for (ulint i = 0; i < n_indexes; ++i) {
- index_t index;
-
- if (end_ptr < start_ptr + (8 + 4 + 4 + 4)) {
- return(DB_FAIL);
- }
-
- index.m_id = mach_read_from_8(start_ptr);
- start_ptr += 8;
-
- index.m_type = mach_read_from_4(start_ptr);
- start_ptr += 4;
-
- index.m_root_page_no = mach_read_from_4(start_ptr);
- start_ptr += 4;
-
- index.m_trx_id_pos = mach_read_from_4(start_ptr);
- start_ptr += 4;
-
- if (!(index.m_type & DICT_FTS)) {
- m_indexes.push_back(index);
- }
- }
-
- ut_ad(!m_indexes.empty());
-
- if (FSP_FLAGS_GET_ZIP_SSIZE(m_tablespace_flags)) {
-
- /* Parse the number of index fields from TRUNCATE log record */
- for (ulint i = 0; i < m_indexes.size(); ++i) {
-
- if (end_ptr < start_ptr + (2 + 2)) {
- return(DB_FAIL);
- }
-
- m_indexes[i].m_n_fields = mach_read_from_2(start_ptr);
- start_ptr += 2;
-
- ulint len = mach_read_from_2(start_ptr);
- start_ptr += 2;
-
- if (end_ptr < start_ptr + len) {
- return(DB_FAIL);
- }
-
- index_t& index = m_indexes[i];
-
- /* Should be NUL terminated. */
- ut_ad((start_ptr)[len - 1] == 0);
-
- index_t::fields_t::iterator end;
-
- end = index.m_fields.end();
-
- index.m_fields.insert(
- end, start_ptr, &(start_ptr)[len]);
-
- start_ptr += len;
- }
- }
-
- return(DB_SUCCESS);
-}
-
-/** Parse log record from REDO log file during recovery.
-@param[in,out] start_ptr buffer containing log body to parse
-@param[in] end_ptr buffer end
-@param[in] space_id tablespace identifier
-@return parsed upto or NULL. */
-byte*
-truncate_t::parse_redo_entry(
- byte* start_ptr,
- const byte* end_ptr,
- ulint space_id)
-{
- lsn_t lsn;
-
- /* Parse space-id, lsn */
- if (end_ptr < (start_ptr + 8)) {
- return(NULL);
- }
-
- lsn = mach_read_from_8(start_ptr);
- start_ptr += 8;
-
- /* Tablespace can't exist in both state.
- (scheduled-for-truncate, was-truncated). */
- if (!is_tablespace_truncated(space_id)) {
-
- truncated_tables_t::iterator it =
- s_truncated_tables.find(space_id);
-
- if (it == s_truncated_tables.end()) {
- s_truncated_tables.insert(
- std::pair<ulint, lsn_t>(space_id, lsn));
- } else {
- it->second = lsn;
- }
- }
-
- return(start_ptr);
-}
-
-/**
-Set the truncate log values for a compressed table.
-@param index index from which recreate infoormation needs to be extracted
-@return DB_SUCCESS or error code */
-
-dberr_t
-truncate_t::index_t::set(
- const dict_index_t* index)
-{
- /* Get trx-id column position (set only for clustered index) */
- if (dict_index_is_clust(index)) {
- m_trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
- ut_ad(m_trx_id_pos > 0);
- ut_ad(m_trx_id_pos != ULINT_UNDEFINED);
- } else {
- m_trx_id_pos = 0;
- }
-
- /* Original logic set this field differently if page is not leaf.
- For truncate case this being first page to get created it is
- always a leaf page and so we don't need that condition here. */
- m_n_fields = dict_index_get_n_fields(index);
-
- /* See requirements of page_zip_fields_encode for size. */
- ulint encoded_buf_size = (m_n_fields + 1) * 2;
- byte* encoded_buf = UT_NEW_ARRAY_NOKEY(byte, encoded_buf_size);
-
- if (encoded_buf == NULL) {
- return(DB_OUT_OF_MEMORY);
- }
-
- ulint len = page_zip_fields_encode(
- m_n_fields, index, m_trx_id_pos, encoded_buf);
- ut_a(len <= encoded_buf_size);
-
- /* Append the encoded fields data. */
- m_fields.insert(m_fields.end(), &encoded_buf[0], &encoded_buf[len]);
-
- /* NUL terminate the encoded data */
- m_fields.push_back(0);
-
- UT_DELETE_ARRAY(encoded_buf);
-
- return(DB_SUCCESS);
-}
-
-/** Create an index for a table.
-@param[in] table_name table name, for which to create
-the index
-@param[in] space tablespace
-@param[in] page_size page size of the .ibd file
-@param[in] index_type type of index to truncate
-@param[in] index_id id of index to truncate
-@param[in] btr_redo_create_info control info for ::btr_create()
-@param[in,out] mtr mini-transaction covering the
-create index
-@return root page no or FIL_NULL on failure */
-inline ulint
-truncate_t::create_index(
- const char* table_name,
- fil_space_t* space,
- ulint index_type,
- index_id_t index_id,
- const btr_create_t& btr_redo_create_info,
- mtr_t* mtr) const
-{
- ulint root_page_no = btr_create(
- index_type, space, index_id,
- NULL, &btr_redo_create_info, mtr);
-
- if (root_page_no == FIL_NULL) {
-
- ib::info() << "innodb_force_recovery was set to "
- << srv_force_recovery << ". Continuing crash recovery"
- " even though we failed to create index " << index_id
- << " for compressed table '" << table_name << "' with"
- " file " << space->chain.start->name;
- }
-
- return(root_page_no);
-}
-
-/** Check if index has been modified since TRUNCATE log snapshot
-was recorded.
-@param[in] space tablespace
-@param[in] root_page_no index root page number
-@return true if modified else false */
-inline
-bool
-truncate_t::is_index_modified_since_logged(
- const fil_space_t* space,
- ulint root_page_no) const
-{
- dberr_t err;
- mtr_t mtr;
-
- mtr_start(&mtr);
-
- /* Root page could be in free state if truncate crashed after drop_index
- and page was not allocated for any other object. */
- buf_block_t* block= buf_page_get_gen(
- page_id_t(space->id, root_page_no), page_size_t(space->flags),
- RW_X_LATCH, NULL,
- BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr, &err);
- if (!block) return true;
-
- page_t* root = buf_block_get_frame(block);
-
-#ifdef UNIV_DEBUG
- /* If the root page has been freed as part of truncate drop_index action
- and not yet allocated for any object still the pagelsn > snapshot lsn */
- if (block->page.file_page_was_freed) {
- ut_ad(mach_read_from_8(root + FIL_PAGE_LSN) > m_log_lsn);
- }
-#endif /* UNIV_DEBUG */
-
- lsn_t page_lsn = mach_read_from_8(root + FIL_PAGE_LSN);
-
- mtr_commit(&mtr);
-
- if (page_lsn > m_log_lsn) {
- return(true);
- }
-
- return(false);
-}
-
-/** Drop indexes for a table.
-@param[in,out] space tablespace */
-void truncate_t::drop_indexes(fil_space_t* space) const
-{
- mtr_t mtr;
-
- indexes_t::const_iterator end = m_indexes.end();
- const page_size_t page_size(space->flags);
-
- for (indexes_t::const_iterator it = m_indexes.begin();
- it != end;
- ++it) {
-
- ulint root_page_no = it->m_root_page_no;
-
- if (is_index_modified_since_logged(space, root_page_no)) {
- /* Page has been modified since TRUNCATE log snapshot
- was recorded so not safe to drop the index. */
- continue;
- }
-
- mtr_start(&mtr);
-
- if (space->id != TRX_SYS_SPACE) {
- /* Do not log changes for single-table
- tablespaces, we are in recovery mode. */
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
- }
-
- if (root_page_no != FIL_NULL) {
- const page_id_t root_page_id(space->id, root_page_no);
-
- btr_free_if_exists(
- root_page_id, page_size, it->m_id, &mtr);
- }
-
- /* If tree is already freed then we might return immediately
- in which case we need to release the lock we have acquired
- on root_page. */
- mtr_commit(&mtr);
- }
-}
-
-
-/** Create the indexes for a table
-@param[in] table_name table name, for which to create the indexes
-@param[in,out] space tablespace
-@param[in] format_flags page format flags
-@return DB_SUCCESS or error code. */
-inline dberr_t
-truncate_t::create_indexes(
- const char* table_name,
- fil_space_t* space,
- ulint format_flags)
-{
- mtr_t mtr;
-
- mtr_start(&mtr);
-
- if (space->id != TRX_SYS_SPACE) {
- /* Do not log changes for single-table tablespaces, we
- are in recovery mode. */
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
- }
-
- /* Create all new index trees with table format, index ids, index
- types, number of index fields and index field information taken
- out from the TRUNCATE log record. */
-
- ulint root_page_no = FIL_NULL;
- indexes_t::iterator end = m_indexes.end();
- for (indexes_t::iterator it = m_indexes.begin();
- it != end;
- ++it) {
-
- btr_create_t btr_redo_create_info(
- FSP_FLAGS_GET_ZIP_SSIZE(space->flags)
- ? &it->m_fields[0] : NULL);
-
- btr_redo_create_info.format_flags = format_flags;
-
- if (FSP_FLAGS_GET_ZIP_SSIZE(space->flags)) {
-
- btr_redo_create_info.n_fields = it->m_n_fields;
- /* Skip the NUL appended field */
- btr_redo_create_info.field_len =
- it->m_fields.size() - 1;
- btr_redo_create_info.trx_id_pos = it->m_trx_id_pos;
- }
-
- root_page_no = create_index(
- table_name, space, it->m_type, it->m_id,
- btr_redo_create_info, &mtr);
-
- if (root_page_no == FIL_NULL) {
- break;
- }
-
- it->m_new_root_page_no = root_page_no;
- }
-
- mtr_commit(&mtr);
-
- return(root_page_no == FIL_NULL ? DB_ERROR : DB_SUCCESS);
-}
-
-/**
-Write a TRUNCATE log record for fixing up table if truncate crashes.
-@param start_ptr buffer to write log record
-@param end_ptr buffer end
-@param space_id space id
-@param tablename the table name in the usual databasename/tablename
- format of InnoDB
-@param flags tablespace flags
-@param format_flags page format
-@param lsn lsn while logging
-@return DB_SUCCESS or error code */
-
-dberr_t
-truncate_t::write(
- byte* start_ptr,
- byte* end_ptr,
- ulint space_id,
- const char* tablename,
- ulint flags,
- ulint format_flags,
- lsn_t lsn) const
-{
- if (end_ptr < start_ptr) {
- return(DB_FAIL);
- }
-
- /* LSN, Type, Space-ID, format-flag (also know as log_flag.
- Stored in page_no field), tablespace flags */
- if (end_ptr < (start_ptr + (8 + 4 + 4 + 4))) {
- return(DB_FAIL);
- }
-
- mach_write_to_8(start_ptr, lsn);
- start_ptr += 8;
-
- mach_write_to_4(start_ptr, space_id);
- start_ptr += 4;
-
- mach_write_to_4(start_ptr, format_flags);
- start_ptr += 4;
-
- mach_write_to_4(start_ptr, flags);
- start_ptr += 4;
-
- /* Name of the table. */
- /* Include the NUL in the log record. */
- ulint len = strlen(tablename) + 1;
- if (end_ptr < (start_ptr + (len + 2))) {
- return(DB_FAIL);
- }
-
- mach_write_to_2(start_ptr, len);
- start_ptr += 2;
-
- memcpy(start_ptr, tablename, len - 1);
- start_ptr += len;
-
- DBUG_EXECUTE_IF("ib_trunc_crash_while_writing_redo_log",
- DBUG_SUICIDE(););
-
- /* Old/New Table-ID, Number of Indexes and Tablespace dir-path-name. */
- /* Write the remote directory of the table into mtr log */
- len = m_dir_path != NULL ? strlen(m_dir_path) + 1 : 0;
- if (end_ptr < (start_ptr + (len + 8 + 8 + 2 + 2))) {
- return(DB_FAIL);
- }
-
- /* Write out old-table-id. */
- mach_write_to_8(start_ptr, m_old_table_id);
- start_ptr += 8;
-
- /* Write out new-table-id. */
- mach_write_to_8(start_ptr, m_new_table_id);
- start_ptr += 8;
-
- /* Write out the number of indexes. */
- mach_write_to_2(start_ptr, m_indexes.size());
- start_ptr += 2;
-
- /* Write the length (NUL included) of the .ibd path. */
- mach_write_to_2(start_ptr, len);
- start_ptr += 2;
-
- if (m_dir_path != NULL) {
- memcpy(start_ptr, m_dir_path, len - 1);
- start_ptr += len;
- }
-
- /* Indexes information (id, type) */
- /* Write index ids, type, root-page-no into mtr log */
- for (ulint i = 0; i < m_indexes.size(); ++i) {
-
- if (end_ptr < (start_ptr + (8 + 4 + 4 + 4))) {
- return(DB_FAIL);
- }
-
- mach_write_to_8(start_ptr, m_indexes[i].m_id);
- start_ptr += 8;
-
- mach_write_to_4(start_ptr, m_indexes[i].m_type);
- start_ptr += 4;
-
- mach_write_to_4(start_ptr, m_indexes[i].m_root_page_no);
- start_ptr += 4;
-
- mach_write_to_4(start_ptr, m_indexes[i].m_trx_id_pos);
- start_ptr += 4;
- }
-
- /* If tablespace compressed then field info of each index. */
- if (FSP_FLAGS_GET_ZIP_SSIZE(flags)) {
-
- for (ulint i = 0; i < m_indexes.size(); ++i) {
-
- ulint len = m_indexes[i].m_fields.size();
- if (end_ptr < (start_ptr + (len + 2 + 2))) {
- return(DB_FAIL);
- }
-
- mach_write_to_2(
- start_ptr, m_indexes[i].m_n_fields);
- start_ptr += 2;
-
- mach_write_to_2(start_ptr, len);
- start_ptr += 2;
-
- const byte* ptr = &m_indexes[i].m_fields[0];
- memcpy(start_ptr, ptr, len - 1);
- start_ptr += len;
- }
- }
-
- return(DB_SUCCESS);
-}
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 1c24e7bd177..5ba9de18ae9 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -65,7 +65,6 @@ row_undo_ins_remove_clust_rec(
/*==========================*/
undo_node_t* node) /*!< in: undo node */
{
- btr_cur_t* btr_cur;
ibool success;
dberr_t err;
ulint n_tries = 0;
@@ -73,15 +72,27 @@ row_undo_ins_remove_clust_rec(
dict_index_t* index = node->pcur.btr_cur.index;
bool online;
- ut_ad(dict_index_is_clust(index));
+ ut_ad(index->is_primary());
ut_ad(node->trx->in_rollback);
mtr.start();
if (index->table->is_temporary()) {
ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
mtr.set_log_mode(MTR_LOG_NO_REDO);
+ ut_ad(!dict_index_is_online_ddl(index));
+ ut_ad(index->table->id >= DICT_HDR_FIRST_ID);
+ online = false;
} else {
index->set_modified(mtr);
+ online = dict_index_is_online_ddl(index);
+ if (online) {
+ ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
+ ut_ad(node->trx->dict_operation_lock_mode
+ != RW_X_LATCH);
+ ut_ad(node->table->id != DICT_INDEXES_ID);
+ ut_ad(node->table->id != DICT_COLUMNS_ID);
+ mtr_s_lock_index(index, &mtr);
+ }
}
/* This is similar to row_undo_mod_clust(). The DDL thread may
@@ -90,105 +101,70 @@ row_undo_ins_remove_clust_rec(
purged. However, we can log the removal out of sync with the
B-tree modification. */
- online = dict_index_is_online_ddl(index);
- if (online) {
- ut_ad(node->trx->dict_operation_lock_mode
- != RW_X_LATCH);
- ut_ad(node->table->id != DICT_INDEXES_ID);
- mtr_s_lock_index(index, &mtr);
- }
-
success = btr_pcur_restore_position(
online
? BTR_MODIFY_LEAF | BTR_ALREADY_S_LATCHED
- : BTR_MODIFY_LEAF, &node->pcur, &mtr);
+ : (node->rec_type == TRX_UNDO_INSERT_METADATA)
+ ? BTR_MODIFY_TREE : BTR_MODIFY_LEAF, &node->pcur, &mtr);
ut_a(success);
- btr_cur = btr_pcur_get_btr_cur(&node->pcur);
+ rec_t* rec = btr_pcur_get_rec(&node->pcur);
- ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur), btr_cur->index)
- == node->trx->id);
- ut_ad(!rec_get_deleted_flag(
- btr_cur_get_rec(btr_cur),
- dict_table_is_comp(btr_cur->index->table)));
+ ut_ad(rec_get_trx_id(rec, index) == node->trx->id);
+ ut_ad(!rec_get_deleted_flag(rec, index->table->not_redundant())
+ || rec_is_alter_metadata(rec, index->table->not_redundant()));
+ ut_ad(rec_is_metadata(rec, index->table->not_redundant())
+ == (node->rec_type == TRX_UNDO_INSERT_METADATA));
if (online && dict_index_is_online_ddl(index)) {
- const rec_t* rec = btr_cur_get_rec(btr_cur);
mem_heap_t* heap = NULL;
const offset_t* offsets = rec_get_offsets(
rec, index, NULL, true, ULINT_UNDEFINED, &heap);
row_log_table_delete(rec, index, offsets, NULL);
mem_heap_free(heap);
- }
-
- switch (node->table->id) {
- case DICT_INDEXES_ID:
- ut_ad(!online);
- ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
-
- dict_drop_index_tree(
- btr_pcur_get_rec(&node->pcur), &node->pcur, node->trx,
- &mtr);
-
- mtr.commit();
+ } else {
+ switch (node->table->id) {
+ case DICT_INDEXES_ID:
+ ut_ad(!online);
+ ut_ad(node->trx->dict_operation_lock_mode
+ == RW_X_LATCH);
+ ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
- mtr.start();
+ dict_drop_index_tree(rec, &node->pcur, node->trx,
+ &mtr);
+ mtr.commit();
- success = btr_pcur_restore_position(
- BTR_MODIFY_LEAF, &node->pcur, &mtr);
- ut_a(success);
- break;
- case DICT_COLUMNS_ID:
- /* This is rolling back an INSERT into SYS_COLUMNS.
- If it was part of an instant ADD COLUMN operation, we
- must modify the table definition. At this point, any
- corresponding operation to the metadata record will have
- been rolled back. */
- ut_ad(!online);
- ut_ad(node->trx->dict_operation_lock_mode == RW_X_LATCH);
- ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
- const rec_t* rec = btr_pcur_get_rec(&node->pcur);
- if (rec_get_n_fields_old(rec)
- != DICT_NUM_FIELDS__SYS_COLUMNS) {
- break;
- }
- ulint len;
- const byte* data = rec_get_nth_field_old(
- rec, DICT_FLD__SYS_COLUMNS__TABLE_ID, &len);
- if (len != 8) {
+ mtr.start();
+ success = btr_pcur_restore_position(
+ BTR_MODIFY_LEAF, &node->pcur, &mtr);
+ ut_a(success);
break;
+ case DICT_COLUMNS_ID:
+ /* This is rolling back an INSERT into SYS_COLUMNS.
+ If it was part of an instant ALTER TABLE operation, we
+ must evict the table definition, so that it can be
+ reloaded after the dictionary operation has been
+ completed. At this point, any corresponding operation
+ to the metadata record will have been rolled back. */
+ ut_ad(!online);
+ ut_ad(node->trx->dict_operation_lock_mode
+ == RW_X_LATCH);
+ ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
+ if (rec_get_n_fields_old(rec)
+ != DICT_NUM_FIELDS__SYS_COLUMNS) {
+ break;
+ }
+ ulint len;
+ const byte* data = rec_get_nth_field_old(
+ rec, DICT_FLD__SYS_COLUMNS__TABLE_ID, &len);
+ if (len != 8) {
+ break;
+ }
+ node->trx->evict_table(mach_read_from_8(data));
}
- const table_id_t table_id = mach_read_from_8(data);
- data = rec_get_nth_field_old(rec, DICT_FLD__SYS_COLUMNS__POS,
- &len);
- if (len != 4) {
- break;
- }
- const unsigned pos = mach_read_from_4(data);
- if (pos == 0 || pos >= (1U << 16)) {
- break;
- }
- dict_table_t* table = dict_table_open_on_id(
- table_id, true, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED);
- if (!table) {
- break;
- }
-
- dict_index_t* index = dict_table_get_first_index(table);
-
- if (index && index->is_instant()
- && DATA_N_SYS_COLS + 1 + pos == table->n_cols) {
- /* This is the rollback of an instant ADD COLUMN.
- Remove the column from the dictionary cache,
- but keep the system columns. */
- table->rollback_instant(pos);
- }
-
- dict_table_close(table, true, false);
}
- if (btr_cur_optimistic_delete(btr_cur, 0, &mtr)) {
+ if (btr_cur_optimistic_delete(&node->pcur.btr_cur, 0, &mtr)) {
err = DB_SUCCESS;
goto func_exit;
}
@@ -208,7 +184,8 @@ retry:
&node->pcur, &mtr);
ut_a(success);
- btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 0, true, &mtr);
+ btr_cur_pessimistic_delete(&err, FALSE, &node->pcur.btr_cur, 0, true,
+ &mtr);
/* The delete operation may fail if we have little
file space left: TODO: easiest to crash the database
@@ -227,29 +204,34 @@ retry:
}
func_exit:
- btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_INSERT_METADATA) {
/* When rolling back the very first instant ADD COLUMN
operation, reset the root page to the basic state. */
ut_ad(!index->table->is_temporary());
- mtr.start();
if (page_t* root = btr_root_get(index, &mtr)) {
byte* page_type = root + FIL_PAGE_TYPE;
ut_ad(mach_read_from_2(page_type)
== FIL_PAGE_TYPE_INSTANT
|| mach_read_from_2(page_type)
== FIL_PAGE_INDEX);
- index->set_modified(mtr);
mlog_write_ulint(page_type, FIL_PAGE_INDEX,
MLOG_2BYTES, &mtr);
byte* instant = PAGE_INSTANT + PAGE_HEADER + root;
mlog_write_ulint(instant,
page_ptr_get_direction(instant + 1),
MLOG_2BYTES, &mtr);
+ rec_t* infimum = page_get_infimum_rec(root);
+ rec_t* supremum = page_get_supremum_rec(root);
+ static const byte str[8 + 8] = "supremuminfimum";
+ if (memcmp(infimum, str + 8, 8)
+ || memcmp(supremum, str, 8)) {
+ mlog_write_string(infimum, str + 8, 8, &mtr);
+ mlog_write_string(supremum, str, 8, &mtr);
+ }
}
- mtr.commit();
}
+ btr_pcur_commit_specify_mtr(&node->pcur, &mtr);
return(err);
}
@@ -381,14 +363,10 @@ retry:
return(err);
}
-/***********************************************************//**
-Parses the row reference and other info in a fresh insert undo record. */
-static
-void
-row_undo_ins_parse_undo_rec(
-/*========================*/
- undo_node_t* node, /*!< in/out: row undo node */
- ibool dict_locked) /*!< in: TRUE if own dict_sys->mutex */
+/** Parse an insert undo record.
+@param[in,out] node row rollback state
+@param[in] dict_locked whether the data dictionary cache is locked */
+static bool row_undo_ins_parse_undo_rec(undo_node_t* node, bool dict_locked)
{
dict_index_t* clust_index;
byte* ptr;
@@ -397,18 +375,28 @@ row_undo_ins_parse_undo_rec(
ulint dummy;
bool dummy_extern;
- ut_ad(node);
+ ut_ad(node->state == UNDO_INSERT_PERSISTENT
+ || node->state == UNDO_INSERT_TEMPORARY);
+ ut_ad(node->trx->in_rollback);
+ ut_ad(trx_undo_roll_ptr_is_insert(node->roll_ptr));
ptr = trx_undo_rec_get_pars(node->undo_rec, &node->rec_type, &dummy,
&dummy_extern, &undo_no, &table_id);
node->update = NULL;
- node->table = dict_table_open_on_id(
- table_id, dict_locked, DICT_TABLE_OP_NORMAL);
+ if (node->state == UNDO_INSERT_PERSISTENT) {
+ node->table = dict_table_open_on_id(table_id, dict_locked,
+ DICT_TABLE_OP_NORMAL);
+ } else if (!dict_locked) {
+ mutex_enter(&dict_sys.mutex);
+ node->table = dict_sys.get_temporary_table(table_id);
+ mutex_exit(&dict_sys.mutex);
+ } else {
+ node->table = dict_sys.get_temporary_table(table_id);
+ }
- /* Skip the UNDO if we can't find the table or the .ibd file. */
- if (UNIV_UNLIKELY(node->table == NULL)) {
- return;
+ if (!node->table) {
+ return false;
}
switch (node->rec_type) {
@@ -447,6 +435,7 @@ close_table:
connection, instead of doing this rollback. */
dict_table_close(node->table, dict_locked, FALSE);
node->table = NULL;
+ return false;
} else {
ut_ad(!node->table->skip_alter_undo);
clust_index = dict_table_get_first_index(node->table);
@@ -478,6 +467,8 @@ close_table:
goto close_table;
}
}
+
+ return true;
}
/***************************************************************//**
@@ -554,18 +545,10 @@ row_undo_ins(
que_thr_t* thr) /*!< in: query thread */
{
dberr_t err;
- ibool dict_locked;
+ bool dict_locked = node->trx->dict_operation_lock_mode == RW_X_LATCH;
- ut_ad(node->state == UNDO_NODE_INSERT);
- ut_ad(node->trx->in_rollback);
- ut_ad(trx_undo_roll_ptr_is_insert(node->roll_ptr));
-
- dict_locked = node->trx->dict_operation_lock_mode == RW_X_LATCH;
-
- row_undo_ins_parse_undo_rec(node, dict_locked);
-
- if (node->table == NULL) {
- return(DB_SUCCESS);
+ if (!row_undo_ins_parse_undo_rec(node, dict_locked)) {
+ return DB_SUCCESS;
}
/* Iterate over all the indexes and undo the insert.*/
@@ -589,26 +572,19 @@ row_undo_ins(
break;
}
- /* fall through */
- case TRX_UNDO_INSERT_METADATA:
log_free_check();
if (node->table->id == DICT_INDEXES_ID) {
- ut_ad(node->rec_type == TRX_UNDO_INSERT_REC);
-
+ ut_ad(!node->table->is_temporary());
if (!dict_locked) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
}
- }
-
- // FIXME: We need to update the dict_index_t::space and
- // page number fields too.
- err = row_undo_ins_remove_clust_rec(node);
-
- if (node->table->id == DICT_INDEXES_ID
- && !dict_locked) {
-
- mutex_exit(&dict_sys->mutex);
+ err = row_undo_ins_remove_clust_rec(node);
+ if (!dict_locked) {
+ mutex_exit(&dict_sys.mutex);
+ }
+ } else {
+ err = row_undo_ins_remove_clust_rec(node);
}
if (err == DB_SUCCESS && node->table->stat_initialized) {
@@ -621,13 +597,19 @@ row_undo_ins(
/* Do not attempt to update statistics when
executing ROLLBACK in the InnoDB SQL
interpreter, because in that case we would
- already be holding dict_sys->mutex, which
+ already be holding dict_sys.mutex, which
would be acquired when updating statistics. */
if (!dict_locked) {
dict_stats_update_if_needed(
node->table, node->trx->mysql_thd);
}
}
+ break;
+
+ case TRX_UNDO_INSERT_METADATA:
+ log_free_check();
+ ut_ad(!node->table->is_temporary());
+ err = row_undo_ins_remove_clust_rec(node);
}
dict_table_close(node->table, dict_locked, FALSE);
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 11de19ba62c..d2707130439 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -111,6 +111,9 @@ row_undo_mod_clust_low(
ut_ad(rec_get_trx_id(btr_cur_get_rec(btr_cur),
btr_cur_get_index(btr_cur))
== thr_get_trx(thr)->id);
+ ut_ad(node->ref != &trx_undo_metadata
+ || node->update->info_bits == REC_INFO_METADATA_ADD
+ || node->update->info_bits == REC_INFO_METADATA_ALTER);
if (mode != BTR_MODIFY_LEAF
&& dict_index_is_online_ddl(btr_cur_get_index(btr_cur))) {
@@ -131,6 +134,7 @@ row_undo_mod_clust_low(
btr_cur, offsets, offsets_heap,
node->update, node->cmpl_info,
thr, thr_get_trx(thr)->id, mtr);
+ ut_ad(err != DB_SUCCESS || node->ref != &trx_undo_metadata);
} else {
big_rec_t* dummy_big_rec;
@@ -143,6 +147,52 @@ row_undo_mod_clust_low(
node->cmpl_info, thr, thr_get_trx(thr)->id, mtr);
ut_a(!dummy_big_rec);
+
+ static const byte
+ INFIMUM[8] = {'i','n','f','i','m','u','m',0},
+ SUPREMUM[8] = {'s','u','p','r','e','m','u','m'};
+
+ if (err == DB_SUCCESS
+ && node->ref == &trx_undo_metadata
+ && btr_cur_get_index(btr_cur)->table->instant
+ && node->update->info_bits == REC_INFO_METADATA_ADD) {
+ if (page_t* root = btr_root_get(
+ btr_cur_get_index(btr_cur), mtr)) {
+ byte* infimum;
+ byte *supremum;
+ if (page_is_comp(root)) {
+ infimum = PAGE_NEW_INFIMUM + root;
+ supremum = PAGE_NEW_SUPREMUM + root;
+ } else {
+ infimum = PAGE_OLD_INFIMUM + root;
+ supremum = PAGE_OLD_SUPREMUM + root;
+ }
+
+ ut_ad(!memcmp(infimum, INFIMUM, 8)
+ == !memcmp(supremum, SUPREMUM, 8));
+
+ if (memcmp(infimum, INFIMUM, 8)) {
+ mlog_write_string(infimum, INFIMUM,
+ 8, mtr);
+ mlog_write_string(supremum, SUPREMUM,
+ 8, mtr);
+ }
+ }
+ }
+ }
+
+ if (err == DB_SUCCESS
+ && btr_cur_get_index(btr_cur)->table->id == DICT_COLUMNS_ID) {
+ /* This is rolling back an UPDATE or DELETE on SYS_COLUMNS.
+ If it was part of an instant ALTER TABLE operation, we
+ must evict the table definition, so that it can be
+ reloaded after the dictionary operation has been
+ completed. At this point, any corresponding operation
+ to the metadata record will have been rolled back. */
+ const dfield_t& table_id = *dtuple_get_nth_field(node->row, 0);
+ ut_ad(dfield_get_len(&table_id) == 8);
+ node->trx->evict_table(mach_read_from_8(static_cast<byte*>(
+ table_id.data)));
}
return(err);
@@ -221,7 +271,7 @@ row_undo_mod_clust(
ut_ad(thr_get_trx(thr) == node->trx);
ut_ad(node->trx->dict_operation_lock_mode);
ut_ad(node->trx->in_rollback);
- ut_ad(rw_lock_own_flagged(&dict_operation_lock,
+ ut_ad(rw_lock_own_flagged(&dict_sys.latch,
RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
log_free_check();
@@ -278,7 +328,7 @@ row_undo_mod_clust(
}
/* Online rebuild cannot be initiated while we are holding
- dict_operation_lock and index->lock. (It can be aborted.) */
+ dict_sys.latch and index->lock. (It can be aborted.) */
ut_ad(online || !dict_index_is_online_ddl(index));
if (err == DB_SUCCESS && online) {
@@ -401,22 +451,49 @@ row_undo_mod_clust(
goto mtr_commit_exit;
}
+ ulint trx_id_offset = index->trx_id_offset;
ulint trx_id_pos = index->n_uniq ? index->n_uniq : 1;
- ut_ad(index->n_uniq <= MAX_REF_PARTS);
- /* Reserve enough offsets for the PRIMARY KEY and 2 columns
- so that we can access DB_TRX_ID, DB_ROLL_PTR. */
+ /* Reserve enough offsets for the PRIMARY KEY and
+ 2 columns so that we can access DB_TRX_ID, DB_ROLL_PTR. */
offset_t offsets_[REC_OFFS_HEADER_SIZE + MAX_REF_PARTS + 2];
- rec_offs_init(offsets_);
- offsets = rec_get_offsets(
- rec, index, offsets_, true, trx_id_pos + 2, &heap);
- ulint len;
- ulint trx_id_offset = rec_get_nth_field_offs(
- offsets, trx_id_pos, &len);
- ut_ad(len == DATA_TRX_ID_LEN);
+ if (trx_id_offset) {
+#ifdef UNIV_DEBUG
+ ut_ad(rec_offs_validate(NULL, index, offsets));
+ if (buf_block_get_page_zip(
+ btr_pcur_get_block(&node->pcur))) {
+ /* Below, page_zip_write_trx_id_and_roll_ptr()
+ needs offsets to access DB_TRX_ID,DB_ROLL_PTR.
+ We already computed offsets for possibly
+ another record in the clustered index.
+ Because the PRIMARY KEY is fixed-length,
+ the offsets for the PRIMARY KEY and
+ DB_TRX_ID,DB_ROLL_PTR are still valid.
+ Silence the rec_offs_validate() assertion. */
+ rec_offs_make_valid(rec, index, true, offsets);
+ }
+#endif
+ } else if (rec_is_metadata(rec, *index)) {
+ ut_ad(!buf_block_get_page_zip(btr_pcur_get_block(
+ &node->pcur)));
+ for (unsigned i = index->first_user_field(); i--; ) {
+ trx_id_offset += index->fields[i].fixed_len;
+ }
+ } else {
+ ut_ad(index->n_uniq <= MAX_REF_PARTS);
+ rec_offs_init(offsets_);
+ offsets = rec_get_offsets(
+ rec, index, offsets_, true, trx_id_pos + 2,
+ &heap);
+ ulint len;
+ trx_id_offset = rec_get_nth_field_offs(
+ offsets, trx_id_pos, &len);
+ ut_ad(len == DATA_TRX_ID_LEN);
+ }
if (trx_read_trx_id(rec + trx_id_offset) == node->new_trx_id) {
ut_ad(!rec_get_deleted_flag(
- rec, dict_table_is_comp(node->table)));
+ rec, dict_table_is_comp(node->table))
+ || rec_is_alter_metadata(rec, *index));
index->set_modified(mtr);
if (page_zip_des_t* page_zip = buf_block_get_page_zip(
btr_pcur_get_block(&node->pcur))) {
@@ -438,8 +515,6 @@ mtr_commit_exit:
btr_pcur_commit_specify_mtr(pcur, &mtr);
func_exit:
- node->state = UNDO_NODE_FETCH_NEXT;
-
if (offsets_heap) {
mem_heap_free(offsets_heap);
}
@@ -852,9 +927,9 @@ row_undo_mod_sec_flag_corrupted(
on the data dictionary during normal rollback,
we can only mark the index corrupted in the
data dictionary cache. TODO: fix this somehow.*/
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
dict_set_corrupted_index_cache_only(index);
- mutex_exit(&dict_sys->mutex);
+ mutex_exit(&dict_sys.mutex);
break;
default:
ut_ad(0);
@@ -1141,14 +1216,10 @@ row_undo_mod_upd_exist_sec(
return(err);
}
-/***********************************************************//**
-Parses the row reference and other info in a modify undo log record. */
-static MY_ATTRIBUTE((nonnull))
-void
-row_undo_mod_parse_undo_rec(
-/*========================*/
- undo_node_t* node, /*!< in: row undo node */
- ibool dict_locked) /*!< in: TRUE if own dict_sys->mutex */
+/** Parse an update undo record.
+@param[in,out] node row rollback state
+@param[in] dict_locked whether the data dictionary cache is locked */
+static bool row_undo_mod_parse_undo_rec(undo_node_t* node, bool dict_locked)
{
dict_index_t* clust_index;
byte* ptr;
@@ -1161,19 +1232,28 @@ row_undo_mod_parse_undo_rec(
ulint cmpl_info;
bool dummy_extern;
+ ut_ad(node->state == UNDO_UPDATE_PERSISTENT
+ || node->state == UNDO_UPDATE_TEMPORARY);
+ ut_ad(node->trx->in_rollback);
+ ut_ad(!trx_undo_roll_ptr_is_insert(node->roll_ptr));
+
ptr = trx_undo_rec_get_pars(node->undo_rec, &type, &cmpl_info,
&dummy_extern, &undo_no, &table_id);
node->rec_type = type;
- node->table = dict_table_open_on_id(
- table_id, dict_locked, DICT_TABLE_OP_NORMAL);
-
- /* TODO: other fixes associated with DROP TABLE + rollback in the
- same table by another user */
+ if (node->state == UNDO_UPDATE_PERSISTENT) {
+ node->table = dict_table_open_on_id(table_id, dict_locked,
+ DICT_TABLE_OP_NORMAL);
+ } else if (!dict_locked) {
+ mutex_enter(&dict_sys.mutex);
+ node->table = dict_sys.get_temporary_table(table_id);
+ mutex_exit(&dict_sys.mutex);
+ } else {
+ node->table = dict_sys.get_temporary_table(table_id);
+ }
- if (node->table == NULL) {
- /* Table was dropped */
- return;
+ if (!node->table) {
+ return false;
}
ut_ad(!node->table->skip_alter_undo);
@@ -1191,7 +1271,7 @@ close_table:
connection, instead of doing this rollback. */
dict_table_close(node->table, dict_locked, FALSE);
node->table = NULL;
- return;
+ return false;
}
clust_index = dict_table_get_first_index(node->table);
@@ -1210,16 +1290,21 @@ close_table:
ut_ad(!node->ref->info_bits);
if (node->update->info_bits & REC_INFO_MIN_REC_FLAG) {
- /* This must be an undo log record for a subsequent
- instant ALTER TABLE, extending the metadata record. */
- ut_ad(clust_index->is_instant());
- if (node->update->info_bits != REC_INFO_MIN_REC_FLAG) {
+ if ((node->update->info_bits & ~REC_INFO_DELETED_FLAG)
+ != REC_INFO_MIN_REC_FLAG) {
ut_ad(!"wrong info_bits in undo log record");
goto close_table;
}
- node->update->info_bits = REC_INFO_METADATA;
- const_cast<dtuple_t*>(node->ref)->info_bits
- = REC_INFO_METADATA;
+ /* This must be an undo log record for a subsequent
+ instant ALTER TABLE, extending the metadata record. */
+ ut_ad(clust_index->is_instant());
+ ut_ad(clust_index->table->instant
+ || !(node->update->info_bits & REC_INFO_DELETED_FLAG));
+ node->ref = &trx_undo_metadata;
+ node->update->info_bits = (node->update->info_bits
+ & REC_INFO_DELETED_FLAG)
+ ? REC_INFO_METADATA_ALTER
+ : REC_INFO_METADATA_ADD;
}
if (!row_undo_search_clust_to_pcur(node)) {
@@ -1257,6 +1342,8 @@ close_table:
(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)
? NULL : ptr);
}
+
+ return true;
}
/***********************************************************//**
@@ -1269,34 +1356,19 @@ row_undo_mod(
que_thr_t* thr) /*!< in: query thread */
{
dberr_t err;
- ibool dict_locked;
-
- ut_ad(node != NULL);
- ut_ad(thr != NULL);
- ut_ad(node->state == UNDO_NODE_MODIFY);
- ut_ad(node->trx->in_rollback);
- ut_ad(!trx_undo_roll_ptr_is_insert(node->roll_ptr));
-
- dict_locked = thr_get_trx(thr)->dict_operation_lock_mode == RW_X_LATCH;
-
ut_ad(thr_get_trx(thr) == node->trx);
+ const bool dict_locked = node->trx->dict_operation_lock_mode
+ == RW_X_LATCH;
- row_undo_mod_parse_undo_rec(node, dict_locked);
-
- if (node->table == NULL) {
- /* It is already undone, or will be undone by another query
- thread, or table was dropped */
-
- node->state = UNDO_NODE_FETCH_NEXT;
-
- return(DB_SUCCESS);
+ if (!row_undo_mod_parse_undo_rec(node, dict_locked)) {
+ return DB_SUCCESS;
}
node->index = dict_table_get_first_index(node->table);
ut_ad(dict_index_is_clust(node->index));
if (node->ref->info_bits) {
- ut_ad(node->ref->info_bits == REC_INFO_METADATA);
+ ut_ad(node->ref->is_metadata());
goto rollback_clust;
}
@@ -1347,7 +1419,7 @@ rollback_clust:
/* Do not attempt to update statistics when
executing ROLLBACK in the InnoDB SQL
interpreter, because in that case we would
- already be holding dict_sys->mutex, which
+ already be holding dict_sys.mutex, which
would be acquired when updating statistics. */
if (update_statistics && !dict_locked) {
dict_stats_update_if_needed(
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index a8d09b71dc2..1cabeb3542b 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -218,7 +218,8 @@ row_undo_search_clust_to_pcur(
log, first mark them DATA_MISSING. So we will know if the
value gets updated */
if (node->table->n_v_cols
- && node->state != UNDO_NODE_INSERT
+ && (node->state == UNDO_UPDATE_PERSISTENT
+ || node->state == UNDO_UPDATE_TEMPORARY)
&& !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
for (ulint i = 0;
i < dict_table_get_n_v_cols(node->table); i++) {
@@ -228,13 +229,15 @@ row_undo_search_clust_to_pcur(
}
if (node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
- ut_ad(node->row->info_bits == REC_INFO_MIN_REC_FLAG
+ ut_ad((node->row->info_bits & ~REC_INFO_DELETED_FLAG)
+ == REC_INFO_MIN_REC_FLAG
|| node->row->info_bits == 0);
node->undo_row = dtuple_copy(node->row, node->heap);
row_upd_replace(node->undo_row, &node->undo_ext,
clust_index, node->update, node->heap);
} else {
- ut_ad((node->row->info_bits == REC_INFO_MIN_REC_FLAG)
+ ut_ad(((node->row->info_bits & ~REC_INFO_DELETED_FLAG)
+ == REC_INFO_MIN_REC_FLAG)
== (node->rec_type == TRX_UNDO_INSERT_METADATA));
node->undo_row = NULL;
node->undo_ext = NULL;
@@ -252,6 +255,149 @@ func_exit:
return(found);
}
+/** Try to truncate the undo logs.
+@param[in,out] trx transaction */
+static void row_undo_try_truncate(trx_t* trx)
+{
+ if (trx_undo_t* undo = trx->rsegs.m_redo.undo) {
+ ut_ad(undo->rseg == trx->rsegs.m_redo.rseg);
+ trx_undo_truncate_end(*undo, trx->undo_no, false);
+ }
+
+ if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) {
+ ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg);
+ trx_undo_truncate_end(*undo, trx->undo_no, true);
+ }
+}
+
+/** Get the latest undo log record for rollback.
+@param[in,out] node rollback context
+@return whether an undo log record was fetched */
+static bool row_undo_rec_get(undo_node_t* node)
+{
+ trx_t* trx = node->trx;
+
+ if (trx->pages_undone) {
+ trx->pages_undone = 0;
+ row_undo_try_truncate(trx);
+ }
+
+ trx_undo_t* undo = NULL;
+ trx_undo_t* insert = trx->rsegs.m_redo.old_insert;
+ trx_undo_t* update = trx->rsegs.m_redo.undo;
+ trx_undo_t* temp = trx->rsegs.m_noredo.undo;
+ const undo_no_t limit = trx->roll_limit;
+
+ ut_ad(!insert || !update || insert->empty() || update->empty()
+ || insert->top_undo_no != update->top_undo_no);
+ ut_ad(!insert || !temp || insert->empty() || temp->empty()
+ || insert->top_undo_no != temp->top_undo_no);
+ ut_ad(!update || !temp || update->empty() || temp->empty()
+ || update->top_undo_no != temp->top_undo_no);
+
+ if (UNIV_LIKELY_NULL(insert)
+ && !insert->empty() && limit <= insert->top_undo_no) {
+ undo = insert;
+ }
+
+ if (update && !update->empty() && update->top_undo_no >= limit) {
+ if (!undo) {
+ undo = update;
+ } else if (undo->top_undo_no < update->top_undo_no) {
+ undo = update;
+ }
+ }
+
+ if (temp && !temp->empty() && temp->top_undo_no >= limit) {
+ if (!undo) {
+ undo = temp;
+ } else if (undo->top_undo_no < temp->top_undo_no) {
+ undo = temp;
+ }
+ }
+
+ if (undo == NULL) {
+ row_undo_try_truncate(trx);
+ /* Mark any ROLLBACK TO SAVEPOINT completed, so that
+ if the transaction object is committed and reused
+ later, we will default to a full ROLLBACK. */
+ trx->roll_limit = 0;
+ trx->in_rollback = false;
+ return false;
+ }
+
+ ut_ad(!undo->empty());
+ ut_ad(limit <= undo->top_undo_no);
+
+ node->roll_ptr = trx_undo_build_roll_ptr(
+ false, undo->rseg->id, undo->top_page_no, undo->top_offset);
+
+ mtr_t mtr;
+ mtr.start();
+
+ page_t* undo_page = trx_undo_page_get_s_latched(
+ page_id_t(undo->rseg->space->id, undo->top_page_no), &mtr);
+
+ ulint offset = undo->top_offset;
+
+ trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec(
+ undo_page + offset, undo->hdr_page_no, undo->hdr_offset,
+ true, &mtr);
+
+ if (prev_rec == NULL) {
+ undo->top_undo_no = IB_ID_MAX;
+ ut_ad(undo->empty());
+ } else {
+ page_t* prev_rec_page = page_align(prev_rec);
+
+ if (prev_rec_page != undo_page) {
+
+ trx->pages_undone++;
+ }
+
+ undo->top_page_no = page_get_page_no(prev_rec_page);
+ undo->top_offset = ulint(prev_rec - prev_rec_page);
+ undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
+ ut_ad(!undo->empty());
+ }
+
+ {
+ const trx_undo_rec_t* undo_rec = undo_page + offset;
+ node->undo_rec = trx_undo_rec_copy(undo_rec, node->heap);
+ }
+
+ mtr.commit();
+
+ switch (trx_undo_rec_get_type(node->undo_rec)) {
+ case TRX_UNDO_INSERT_METADATA:
+ /* This record type was introduced in MDEV-11369
+ instant ADD COLUMN, which was implemented after
+ MDEV-12288 removed the insert_undo log. There is no
+ instant ADD COLUMN for temporary tables. Therefore,
+ this record can only be present in the main undo log. */
+ ut_ad(undo == update);
+ /* fall through */
+ case TRX_UNDO_RENAME_TABLE:
+ ut_ad(undo == insert || undo == update);
+ /* fall through */
+ case TRX_UNDO_INSERT_REC:
+ ut_ad(undo == insert || undo == update || undo == temp);
+ node->roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
+ node->state = undo == temp
+ ? UNDO_INSERT_TEMPORARY : UNDO_INSERT_PERSISTENT;
+ break;
+ default:
+ ut_ad(undo == update || undo == temp);
+ node->state = undo == temp
+ ? UNDO_UPDATE_TEMPORARY : UNDO_UPDATE_PERSISTENT;
+ break;
+ }
+
+ trx->undo_no = node->undo_no = trx_undo_rec_get_undo_no(
+ node->undo_rec);
+ return true;
+}
+
/***********************************************************//**
Fetches an undo log record and does the undo for the recorded operation.
If none left, or a partial rollback completed, returns control to the
@@ -264,55 +410,47 @@ row_undo(
undo_node_t* node, /*!< in: row undo node */
que_thr_t* thr) /*!< in: query thread */
{
- trx_t* trx = node->trx;
- ut_ad(trx->in_rollback);
-
- if (node->state == UNDO_NODE_FETCH_NEXT) {
-
- node->undo_rec = trx_roll_pop_top_rec_of_trx(
- trx, &node->roll_ptr, node->heap);
-
- if (!node->undo_rec) {
- /* Rollback completed for this query thread */
- thr->run_node = que_node_get_parent(node);
- return(DB_SUCCESS);
- }
+ ut_ad(node->trx->in_rollback);
- node->undo_no = trx_undo_rec_get_undo_no(node->undo_rec);
- node->state = trx_undo_roll_ptr_is_insert(node->roll_ptr)
- ? UNDO_NODE_INSERT : UNDO_NODE_MODIFY;
+ if (node->state == UNDO_NODE_FETCH_NEXT && !row_undo_rec_get(node)) {
+ /* Rollback completed for this query thread */
+ thr->run_node = que_node_get_parent(node);
+ return DB_SUCCESS;
}
/* Prevent DROP TABLE etc. while we are rolling back this row.
If we are doing a TABLE CREATE or some other dictionary operation,
- then we already have dict_operation_lock locked in x-mode. Do not
+ then we already have dict_sys.latch locked in x-mode. Do not
try to lock again, because that would cause a hang. */
+ trx_t* trx = node->trx;
const bool locked_data_dict = (trx->dict_operation_lock_mode == 0);
if (locked_data_dict) {
-
row_mysql_freeze_data_dictionary(trx);
}
dberr_t err;
- if (node->state == UNDO_NODE_INSERT) {
-
+ switch (node->state) {
+ case UNDO_INSERT_PERSISTENT:
+ case UNDO_INSERT_TEMPORARY:
err = row_undo_ins(node, thr);
-
- node->state = UNDO_NODE_FETCH_NEXT;
- } else {
- ut_ad(node->state == UNDO_NODE_MODIFY);
+ break;
+ case UNDO_UPDATE_PERSISTENT:
+ case UNDO_UPDATE_TEMPORARY:
err = row_undo_mod(node, thr);
+ break;
+ default:
+ ut_ad(!"wrong state");
+ err = DB_CORRUPTION;
}
if (locked_data_dict) {
-
row_mysql_unfreeze_data_dictionary(trx);
}
- /* Do some cleanup */
+ node->state = UNDO_NODE_FETCH_NEXT;
btr_pcur_close(&(node->pcur));
mem_heap_empty(node->heap);
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index aff8ae125b5..6ddd4046f09 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -122,7 +122,7 @@ row_upd_changes_first_fields_binary(
Checks if index currently is mentioned as a referenced index in a foreign
key constraint.
-NOTE that since we do not hold dict_operation_lock when leaving the
+NOTE that since we do not hold dict_sys.latch when leaving the
function, it may be that the referencing table has been dropped when
we leave this function: this function is only for heuristic use!
@@ -288,7 +288,7 @@ row_upd_check_references_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
- we will release dict_operation_lock temporarily!
+ we will release dict_sys.latch temporarily!
But the inc_fk_checks() protects foreign_table from
being dropped while the check is running. */
@@ -394,7 +394,7 @@ wsrep_row_upd_check_foreign_constraints(
}
/* NOTE that if the thread ends up waiting for a lock
- we will release dict_operation_lock temporarily!
+ we will release dict_sys.latch temporarily!
But the counter on the table protects 'foreign' from
being dropped while the check is running. */
@@ -492,39 +492,6 @@ row_upd_rec_sys_fields_in_recovery(
}
}
-/*********************************************************************//**
-Sets the trx id or roll ptr field of a clustered index entry. */
-void
-row_upd_index_entry_sys_field(
-/*==========================*/
- dtuple_t* entry, /*!< in/out: index entry, where the memory
- buffers for sys fields are already allocated:
- the function just copies the new values to
- them */
- dict_index_t* index, /*!< in: clustered index */
- ulint type, /*!< in: DATA_TRX_ID or DATA_ROLL_PTR */
- ib_uint64_t val) /*!< in: value to write */
-{
- dfield_t* dfield;
- byte* field;
- ulint pos;
-
- ut_ad(dict_index_is_clust(index));
-
- pos = dict_index_get_sys_col_pos(index, type);
-
- dfield = dtuple_get_nth_field(entry, pos);
- field = static_cast<byte*>(dfield_get_data(dfield));
-
- if (type == DATA_TRX_ID) {
- ut_ad(val > 0);
- trx_write_trx_id(field, val);
- } else {
- ut_ad(type == DATA_ROLL_PTR);
- trx_write_roll_ptr(field, val);
- }
-}
-
/***********************************************************//**
Returns TRUE if row update changes size of some field in index or if some
field to be updated is stored externally in rec or update.
@@ -677,7 +644,7 @@ row_upd_rec_in_place(
switch (rec_get_status(rec)) {
case REC_STATUS_ORDINARY:
break;
- case REC_STATUS_COLUMNS_ADDED:
+ case REC_STATUS_INSTANT:
ut_ad(index->is_instant());
break;
case REC_STATUS_NODE_PTR:
@@ -728,35 +695,6 @@ row_upd_rec_in_place(
}
/*********************************************************************//**
-Writes into the redo log the values of trx id and roll ptr and enough info
-to determine their positions within a clustered index record.
-@return new pointer to mlog */
-byte*
-row_upd_write_sys_vals_to_log(
-/*==========================*/
- dict_index_t* index, /*!< in: clustered index */
- trx_id_t trx_id, /*!< in: transaction id */
- roll_ptr_t roll_ptr,/*!< in: roll ptr of the undo log record */
- byte* log_ptr,/*!< pointer to a buffer of size > 20 opened
- in mlog */
- mtr_t* mtr MY_ATTRIBUTE((unused))) /*!< in: mtr */
-{
- ut_ad(dict_index_is_clust(index));
- ut_ad(mtr);
-
- log_ptr += mach_write_compressed(log_ptr,
- dict_index_get_sys_col_pos(
- index, DATA_TRX_ID));
-
- trx_write_roll_ptr(log_ptr, roll_ptr);
- log_ptr += DATA_ROLL_PTR_LEN;
-
- log_ptr += mach_u64_write_compressed(log_ptr, trx_id);
-
- return(log_ptr);
-}
-
-/*********************************************************************//**
Parses the log data of system field values.
@return log data end or NULL */
byte*
@@ -1049,7 +987,6 @@ row_upd_build_difference_binary(
ulint len;
upd_t* update;
ulint n_diff;
- ulint trx_id_pos;
offset_t offsets_[REC_OFFS_NORMAL_SIZE];
const ulint n_v_fld = dtuple_get_n_v_fields(entry);
rec_offs_init(offsets_);
@@ -1064,10 +1001,6 @@ row_upd_build_difference_binary(
n_diff = 0;
- trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
- ut_ad(dict_index_get_sys_col_pos(index, DATA_ROLL_PTR)
- == trx_id_pos + 1);
-
if (!offsets) {
offsets = rec_get_offsets(rec, index, offsets_, true,
ULINT_UNDEFINED, &heap);
@@ -1082,16 +1015,9 @@ row_upd_build_difference_binary(
/* NOTE: we compare the fields as binary strings!
(No collation) */
- if (no_sys) {
- /* TRX_ID */
- if (i == trx_id_pos) {
- continue;
- }
-
- /* DB_ROLL_PTR */
- if (i == trx_id_pos + 1) {
- continue;
- }
+ if (no_sys && (i == index->db_trx_id()
+ || i == index->db_roll_ptr())) {
+ continue;
}
if (!dfield_is_ext(dfield)
@@ -1197,7 +1123,7 @@ of the column and must not be poisoned with the new values.
@param[in] data 'internally' stored part of the field
containing also the reference to the external part
@param[in] local_len length of data, in bytes
-@param[in] page_size BLOB page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] len input - length of prefix to
fetch; output: fetched length of the prefix
@param[in,out] heap heap where to allocate
@@ -1207,14 +1133,14 @@ byte*
row_upd_ext_fetch(
const byte* data,
ulint local_len,
- const page_size_t& page_size,
+ ulint zip_size,
ulint* len,
mem_heap_t* heap)
{
byte* buf = static_cast<byte*>(mem_heap_alloc(heap, *len));
*len = btr_copy_externally_stored_field_prefix(
- buf, *len, page_size, data, local_len);
+ buf, *len, zip_size, data, local_len);
/* We should never update records containing a half-deleted BLOB. */
ut_a(*len);
@@ -1230,7 +1156,7 @@ the given index entry field.
@param[in] uf update field
@param[in,out] heap memory heap for allocating and copying
the new value
-@param[in] page_size page size */
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
static
void
row_upd_index_replace_new_col_val(
@@ -1239,7 +1165,7 @@ row_upd_index_replace_new_col_val(
const dict_col_t* col,
const upd_field_t* uf,
mem_heap_t* heap,
- const page_size_t& page_size)
+ ulint zip_size)
{
ulint len;
const byte* data;
@@ -1253,7 +1179,7 @@ row_upd_index_replace_new_col_val(
len = dfield_get_len(dfield);
data = static_cast<const byte*>(dfield_get_data(dfield));
- if (field->prefix_len > 0) {
+ if (field && field->prefix_len > 0) {
ibool fetch_ext = dfield_is_ext(dfield)
&& len < (ulint) field->prefix_len
+ BTR_EXTERN_FIELD_REF_SIZE;
@@ -1263,7 +1189,7 @@ row_upd_index_replace_new_col_val(
len = field->prefix_len;
- data = row_upd_ext_fetch(data, l, page_size,
+ data = row_upd_ext_fetch(data, l, zip_size,
&len, heap);
}
@@ -1319,6 +1245,57 @@ row_upd_index_replace_new_col_val(
}
}
+/** Apply an update vector to an metadata entry.
+@param[in,out] entry clustered index metadata record to be updated
+@param[in] index index of the entry
+@param[in] update update vector built for the entry
+@param[in,out] heap memory heap for copying off-page columns */
+static
+void
+row_upd_index_replace_metadata(
+ dtuple_t* entry,
+ const dict_index_t* index,
+ const upd_t* update,
+ mem_heap_t* heap)
+{
+ ut_ad(!index->table->skip_alter_undo);
+ ut_ad(update->is_alter_metadata());
+ ut_ad(entry->info_bits == update->info_bits);
+ ut_ad(entry->n_fields == ulint(index->n_fields) + 1);
+ const ulint zip_size = index->table->space->zip_size();
+ const ulint first = index->first_user_field();
+ ut_d(bool found_mblob = false);
+
+ for (ulint i = upd_get_n_fields(update); i--; ) {
+ const upd_field_t* uf = upd_get_nth_field(update, i);
+ ut_ad(!upd_fld_is_virtual_col(uf));
+ ut_ad(uf->field_no >= first - 2);
+ ulint f = uf->field_no;
+ dfield_t* dfield = dtuple_get_nth_field(entry, f);
+
+ if (f == first) {
+ ut_d(found_mblob = true);
+ ut_ad(!dfield_is_null(&uf->new_val));
+ ut_ad(dfield_is_ext(dfield));
+ ut_ad(dfield_get_len(dfield) == FIELD_REF_SIZE);
+ ut_ad(!dfield_is_null(dfield));
+ dfield_set_data(dfield, uf->new_val.data,
+ uf->new_val.len);
+ if (dfield_is_ext(&uf->new_val)) {
+ dfield_set_ext(dfield);
+ }
+ continue;
+ }
+
+ f -= f > first;
+ const dict_field_t* field = dict_index_get_nth_field(index, f);
+ row_upd_index_replace_new_col_val(dfield, field, field->col,
+ uf, heap, zip_size);
+ }
+
+ ut_ad(found_mblob);
+}
+
/** Apply an update vector to an index entry.
@param[in,out] entry index entry to be updated; the clustered index record
must be covered by a lock or a page latch to prevent
@@ -1334,8 +1311,14 @@ row_upd_index_replace_new_col_vals_index_pos(
mem_heap_t* heap)
{
ut_ad(!index->table->skip_alter_undo);
+ ut_ad(!entry->is_metadata() || entry->info_bits == update->info_bits);
- const page_size_t& page_size = dict_table_page_size(index->table);
+ if (UNIV_UNLIKELY(entry->is_alter_metadata())) {
+ row_upd_index_replace_metadata(entry, index, update, heap);
+ return;
+ }
+
+ const ulint zip_size = index->table->space->zip_size();
dtuple_set_info_bits(entry, update->info_bits);
@@ -1361,7 +1344,7 @@ row_upd_index_replace_new_col_vals_index_pos(
if (uf) {
row_upd_index_replace_new_col_val(
dtuple_get_nth_field(entry, i),
- field, col, uf, heap, page_size);
+ field, col, uf, heap, zip_size);
}
}
}
@@ -1387,7 +1370,7 @@ row_upd_index_replace_new_col_vals(
ulint i;
const dict_index_t* clust_index
= dict_table_get_first_index(index->table);
- const page_size_t& page_size = dict_table_page_size(index->table);
+ const ulint zip_size = index->table->space->zip_size();
ut_ad(!index->table->skip_alter_undo);
@@ -1417,7 +1400,7 @@ row_upd_index_replace_new_col_vals(
if (uf) {
row_upd_index_replace_new_col_val(
dtuple_get_nth_field(entry, i),
- field, col, uf, heap, page_size);
+ field, col, uf, heap, zip_size);
}
}
}
@@ -1641,8 +1624,7 @@ row_upd_replace(
}
if (n_ext_cols) {
- *ext = row_ext_create(n_ext_cols, ext_cols, table->flags, row,
- heap);
+ *ext = row_ext_create(n_ext_cols, ext_cols, *table, row, heap);
} else {
*ext = NULL;
}
@@ -1750,11 +1732,9 @@ row_upd_changes_ord_field_binary_func(
mem_heap_t* temp_heap = NULL;
const dfield_t* new_field = &upd_field->new_val;
- const page_size_t page_size
- = (ext != NULL)
- ? ext->page_size
- : dict_table_page_size(
- index->table);
+ const ulint zip_size = ext
+ ? ext->zip_size
+ : index->table->space->zip_size();
ut_ad(dfield->data != NULL
&& dfield->len > GEO_DATA_HEADER_SIZE);
@@ -1771,7 +1751,7 @@ row_upd_changes_ord_field_binary_func(
dptr = btr_copy_externally_stored_field(
&dlen, dptr,
- page_size,
+ zip_size,
flen,
temp_heap);
} else {
@@ -1834,7 +1814,7 @@ row_upd_changes_ord_field_binary_func(
dptr = btr_copy_externally_stored_field(
&dlen, dptr,
- page_size,
+ zip_size,
flen,
temp_heap);
} else {
@@ -2439,7 +2419,7 @@ row_upd_sec_index_entry(
#ifdef UNIV_DEBUG
mtr_commit(&mtr);
mtr_start(&mtr);
- ut_ad(btr_validate_index(index, 0, false));
+ ut_ad(btr_validate_index(index, 0));
ut_ad(0);
#endif /* UNIV_DEBUG */
break;
@@ -2483,7 +2463,7 @@ row_upd_sec_index_entry(
}
break;
case DB_DEADLOCK:
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::warn() << "WSREP: sec index FK check fail for deadlock"
<< " index " << index->name
<< " table " << index->table->name
@@ -2570,10 +2550,10 @@ row_upd_sec_step(
}
#ifdef UNIV_DEBUG
-# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
- row_upd_clust_rec_by_insert_inherit_func(rec,offsets,entry,update)
+# define row_upd_clust_rec_by_insert_inherit(rec,index,offsets,entry,update) \
+ row_upd_clust_rec_by_insert_inherit_func(rec,index,offsets,entry,update)
#else /* UNIV_DEBUG */
-# define row_upd_clust_rec_by_insert_inherit(rec,offsets,entry,update) \
+# define row_upd_clust_rec_by_insert_inherit(rec,index,offsets,entry,update) \
row_upd_clust_rec_by_insert_inherit_func(rec,entry,update)
#endif /* UNIV_DEBUG */
/*******************************************************************//**
@@ -2588,6 +2568,7 @@ row_upd_clust_rec_by_insert_inherit_func(
/*=====================================*/
const rec_t* rec, /*!< in: old record, or NULL */
#ifdef UNIV_DEBUG
+ dict_index_t* index, /*!< in: index, or NULL */
const offset_t* offsets,/*!< in: rec_get_offsets(rec), or NULL */
#endif /* UNIV_DEBUG */
dtuple_t* entry, /*!< in/out: updated entry to be
@@ -2598,6 +2579,8 @@ row_upd_clust_rec_by_insert_inherit_func(
ulint i;
ut_ad(!rec == !offsets);
+ ut_ad(!rec == !index);
+ ut_ad(!rec || rec_offs_validate(rec, index, offsets));
ut_ad(!rec || rec_offs_any_extern(offsets));
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
@@ -2608,6 +2591,9 @@ row_upd_clust_rec_by_insert_inherit_func(
ut_ad(!offsets
|| !rec_offs_nth_extern(offsets, i)
== !dfield_is_ext(dfield)
+ || (!dict_index_get_nth_field(index, i)->name
+ && !dfield_is_ext(dfield)
+ && (dfield_is_null(dfield) || dfield->len == 0))
|| upd_get_field_by_field_no(update, i, false));
if (!dfield_is_ext(dfield)
|| upd_get_field_by_field_no(update, i, false)) {
@@ -2708,7 +2694,11 @@ row_upd_clust_rec_by_insert(
if (index->is_instant()) entry->trim(*index);
ut_ad(dtuple_get_info_bits(entry) == 0);
- row_upd_index_entry_sys_field(entry, index, DATA_TRX_ID, trx->id);
+ {
+ dfield_t* t = dtuple_get_nth_field(entry, index->db_trx_id());
+ ut_ad(t->len == DATA_TRX_ID_LEN);
+ trx_write_trx_id(static_cast<byte*>(t->data), trx->id);
+ }
switch (node->state) {
default:
@@ -2717,7 +2707,7 @@ row_upd_clust_rec_by_insert(
/* A lock wait occurred in row_ins_clust_index_entry() in
the previous invocation of this function. */
row_upd_clust_rec_by_insert_inherit(
- NULL, NULL, entry, node->update);
+ NULL, NULL, NULL, entry, node->update);
break;
case UPD_NODE_UPDATE_CLUSTERED:
/* This is the first invocation of the function where
@@ -2758,7 +2748,8 @@ err_exit:
if (rec_offs_any_extern(offsets)) {
if (row_upd_clust_rec_by_insert_inherit(
- rec, offsets, entry, node->update)) {
+ rec, index, offsets,
+ entry, node->update)) {
/* The blobs are disowned here, expecting the
insert down below to inherit them. But if the
insert fails, then this disown will be undone
@@ -2791,7 +2782,7 @@ check_fk:
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::warn() << "WSREP: sec index FK check fail for deadlock"
<< " index " << index->name
<< " table " << index->table->name;
@@ -3018,7 +3009,7 @@ row_upd_del_mark_clust_rec(
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::warn() << "WSREP: sec index FK check fail for deadlock"
<< " index " << index->name
<< " table " << index->table->name;
diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc
index d2ad8751211..157c2688c33 100644
--- a/storage/innobase/srv/srv0conc.cc
+++ b/storage/innobase/srv/srv0conc.cc
@@ -67,14 +67,12 @@ ulong srv_thread_concurrency = 0;
/** Variables tracking the active and waiting threads. */
struct srv_conc_t {
- char pad[CACHE_LINE_SIZE - (sizeof(ulint) + sizeof(lint))];
-
/** Number of transactions that have declared_to_be_inside_innodb */
- ulint n_active;
+ MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) Atomic_counter<ulint> n_active;
/** Number of OS threads waiting in the FIFO for permission to
enter InnoDB */
- ulint n_waiting;
+ MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) Atomic_counter<ulint> n_waiting;
};
/* Control variables for tracking concurrency. */
@@ -121,8 +119,8 @@ srv_conc_enter_innodb_with_atomics(
ulint sleep_in_us;
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
- wsrep_trx_is_aborting(trx->mysql_thd)) {
- if (wsrep_debug) {
+ wsrep_thd_is_aborting(trx->mysql_thd)) {
+ if (wsrep_get_debug()) {
ib::info() <<
"srv_conc_enter due to MUST_ABORT";
}
@@ -133,8 +131,7 @@ srv_conc_enter_innodb_with_atomics(
if (srv_thread_concurrency == 0) {
if (notified_mysql) {
- my_atomic_addlint(&srv_conc.n_waiting,
- ulint(-1));
+ srv_conc.n_waiting--;
thd_wait_end(trx->mysql_thd);
}
@@ -142,19 +139,14 @@ srv_conc_enter_innodb_with_atomics(
}
if (srv_conc.n_active < srv_thread_concurrency) {
- ulint n_active;
/* Check if there are any free tickets. */
- n_active = my_atomic_addlint(
- &srv_conc.n_active, 1) + 1;
-
- if (n_active <= srv_thread_concurrency) {
+ if (srv_conc.n_active++ < srv_thread_concurrency) {
srv_enter_innodb_with_tickets(trx);
if (notified_mysql) {
- my_atomic_addlint(&srv_conc.n_waiting,
- ulint(-1));
+ srv_conc.n_waiting--;
thd_wait_end(trx->mysql_thd);
}
@@ -176,11 +168,11 @@ srv_conc_enter_innodb_with_atomics(
/* Since there were no free seats, we relinquish
the overbooked ticket. */
- my_atomic_addlint(&srv_conc.n_active, ulint(-1));
+ srv_conc.n_active--;
}
if (!notified_mysql) {
- my_atomic_addlint(&srv_conc.n_waiting, 1);
+ srv_conc.n_waiting++;
thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK);
@@ -224,7 +216,7 @@ srv_conc_exit_innodb_with_atomics(
trx->n_tickets_to_enter_innodb = 0;
trx->declared_to_be_inside_innodb = FALSE;
- my_atomic_addlint(&srv_conc.n_active, ulint(-1));
+ srv_conc.n_active--;
}
/*********************************************************************//**
@@ -258,7 +250,7 @@ srv_conc_force_enter_innodb(
return;
}
- (void) my_atomic_addlint(&srv_conc.n_active, 1);
+ srv_conc.n_active++;
trx->n_tickets_to_enter_innodb = 1;
trx->declared_to_be_inside_innodb = TRUE;
@@ -316,14 +308,14 @@ wsrep_srv_conc_cancel_wait(
srv_conc_enter_innodb_with_atomics(). No need to cancel here,
thr will wake up after os_sleep and let to enter innodb
*/
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::info() << "WSREP: conc slot cancel, no atomics";
}
#else
// JAN: TODO: MySQL 5.7
//os_fast_mutex_lock(&srv_conc_mutex);
if (trx->wsrep_event) {
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::info() << "WSREP: conc slot cancel";
}
os_event_set(trx->wsrep_event);
diff --git a/storage/innobase/srv/srv0mon.cc b/storage/innobase/srv/srv0mon.cc
index 0404335574a..c759a5b75fe 100644
--- a/storage/innobase/srv/srv0mon.cc
+++ b/storage/innobase/srv/srv0mon.cc
@@ -298,12 +298,6 @@ static monitor_info_t innodb_counter_info[] =
MONITOR_EXISTING | MONITOR_DEFAULT_ON),
MONITOR_DEFAULT_START, MONITOR_OVLD_PAGES_READ},
- {"buffer_pages0_read", "buffer",
- "Number of page 0 read (innodb_pages0_read)",
- static_cast<monitor_type_t>(
- MONITOR_EXISTING | MONITOR_DEFAULT_ON),
- MONITOR_DEFAULT_START, MONITOR_OVLD_PAGES0_READ},
-
{"buffer_index_sec_rec_cluster_reads", "buffer",
"Number of secondary record reads triggered cluster read",
static_cast<monitor_type_t>(
@@ -802,11 +796,6 @@ static monitor_info_t innodb_counter_info[] =
MONITOR_NONE,
MONITOR_DEFAULT_START, MONITOR_TRX_ROLLBACK_SAVEPOINT},
- {"trx_rollback_active", "transaction",
- "Number of resurrected active transactions rolled back",
- MONITOR_NONE,
- MONITOR_DEFAULT_START, MONITOR_TRX_ROLLBACK_ACTIVE},
-
{"trx_active_transactions", "transaction",
"Number of active transactions",
MONITOR_NONE,
@@ -1748,11 +1737,6 @@ srv_mon_process_existing_counter(
value = stat.n_pages_read;
break;
- /* innodb_pages0_read */
- case MONITOR_OVLD_PAGES0_READ:
- value = srv_stats.page0_read;
- break;
-
/* Number of times secondary index lookup triggered cluster lookup */
case MONITOR_OVLD_INDEX_SEC_REC_CLUSTER_READS:
value = srv_stats.n_sec_rec_cluster_reads;
@@ -1955,7 +1939,7 @@ srv_mon_process_existing_counter(
break;
case MONITOR_RSEG_HISTORY_LEN:
- value = trx_sys.history_size();
+ value = trx_sys.rseg_history_len;
break;
case MONITOR_RSEG_CUR_SIZE:
@@ -2052,7 +2036,7 @@ srv_mon_process_existing_counter(
#endif /* BTR_CUR_HASH_ADAPT */
case MONITOR_OVLD_ADAPTIVE_HASH_SEARCH_BTREE:
- value = my_atomic_loadlint(&btr_cur_n_non_sea);
+ value = btr_cur_n_non_sea;
break;
case MONITOR_OVLD_PAGE_COMPRESS_SAVED:
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 6e7b3e5939f..d7f7e127fea 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -59,7 +59,6 @@ Created 10/8/1995 Heikki Tuuri
#include "pars0pars.h"
#include "que0que.h"
#include "row0mysql.h"
-#include "row0trunc.h"
#include "row0log.h"
#include "srv0mon.h"
#include "srv0srv.h"
@@ -77,10 +76,6 @@ Created 10/8/1995 Heikki Tuuri
#include <my_service_manager.h>
-#ifdef WITH_WSREP
-extern int wsrep_debug;
-extern int wsrep_trx_is_aborting(void *thd_ptr);
-#endif
/* The following is the maximum allowed duration of a lock wait. */
UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT;
@@ -199,8 +194,6 @@ ulong srv_page_size_shift;
/** innodb_log_write_ahead_size */
ulong srv_log_write_ahead_size;
-page_size_t univ_page_size(0, 0, false);
-
/** innodb_adaptive_flushing; try to flush dirty pages so as to avoid
IO bursts at the checkpoints. */
my_bool srv_adaptive_flushing;
@@ -503,10 +496,6 @@ UNIV_INTERN ulong srv_buf_dump_status_frequency;
mutex_enter(&srv_sys.mutex); \
} while (0)
-/** Test if the system mutex is owned. */
-#define srv_sys_mutex_own() (mutex_own(&srv_sys.mutex) \
- && !srv_read_only_mode)
-
/** Release the system mutex. */
#define srv_sys_mutex_exit() do { \
mutex_exit(&srv_sys.mutex); \
@@ -603,11 +592,12 @@ struct srv_sys_t{
sys_threads[]->event are
covered by srv_sys_t::mutex */
- ulint n_threads_active[SRV_MASTER + 1];
+ Atomic_counter<ulint>
+ n_threads_active[SRV_MASTER + 1];
/*!< number of threads active
in a thread class; protected
- by both my_atomic_addlint()
- and mutex */
+ by both std::atomic and
+ mutex */
srv_stats_t::ulint_ctr_1_t
activity_count; /*!< For tracking server
@@ -619,7 +609,7 @@ static srv_sys_t srv_sys;
/** @return whether the purge coordinator thread is active */
bool purge_sys_t::running()
{
- return my_atomic_loadlint(&srv_sys.n_threads_active[SRV_PURGE]);
+ return srv_sys.n_threads_active[SRV_PURGE];
}
/** Event to signal srv_monitor_thread. Not protected by a mutex.
@@ -822,7 +812,7 @@ srv_reserve_slot(
ut_ad(srv_slot_get_type(slot) == type);
- my_atomic_addlint(&srv_sys.n_threads_active[type], 1);
+ srv_sys.n_threads_active[type]++;
srv_sys_mutex_exit();
@@ -839,7 +829,7 @@ srv_suspend_thread_low(
srv_slot_t* slot) /*!< in/out: thread slot */
{
ut_ad(!srv_read_only_mode);
- ut_ad(srv_sys_mutex_own());
+ ut_ad(mutex_own(&srv_sys.mutex));
ut_ad(slot->in_use);
@@ -869,8 +859,7 @@ srv_suspend_thread_low(
ut_a(!slot->suspended);
slot->suspended = TRUE;
- if (lint(my_atomic_addlint(&srv_sys.n_threads_active[type], ulint(-1)))
- < 0) {
+ if (srv_sys.n_threads_active[type]-- == 0) {
ut_error;
}
@@ -927,7 +916,7 @@ srv_resume_thread(srv_slot_t* slot, int64_t sig_count = 0, bool wait = true,
ut_ad(slot->suspended);
slot->suspended = FALSE;
- my_atomic_addlint(&srv_sys.n_threads_active[slot->type], 1);
+ srv_sys.n_threads_active[slot->type]++;
srv_sys_mutex_exit();
return(timeout);
}
@@ -1157,7 +1146,7 @@ srv_refresh_innodb_monitor_stats(void)
#ifdef BTR_CUR_HASH_ADAPT
btr_cur_n_sea_old = btr_cur_n_sea;
#endif /* BTR_CUR_HASH_ADAPT */
- btr_cur_n_non_sea_old = my_atomic_loadlint(&btr_cur_n_non_sea);
+ btr_cur_n_non_sea_old = btr_cur_n_non_sea;
log_refresh_stats();
@@ -1316,16 +1305,16 @@ srv_printf_innodb_monitor(
"%.2f hash searches/s, %.2f non-hash searches/s\n",
(btr_cur_n_sea - btr_cur_n_sea_old)
/ time_elapsed,
- (my_atomic_loadlint(&btr_cur_n_non_sea) - btr_cur_n_non_sea_old)
+ (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
/ time_elapsed);
btr_cur_n_sea_old = btr_cur_n_sea;
#else /* BTR_CUR_HASH_ADAPT */
fprintf(file,
"%.2f non-hash searches/s\n",
- (my_atomic_loadlint(&btr_cur_n_non_sea) - btr_cur_n_non_sea_old)
+ (btr_cur_n_non_sea - btr_cur_n_non_sea_old)
/ time_elapsed);
#endif /* BTR_CUR_HASH_ADAPT */
- btr_cur_n_non_sea_old = my_atomic_loadlint(&btr_cur_n_non_sea);
+ btr_cur_n_non_sea_old = btr_cur_n_non_sea;
fputs("---\n"
"LOG\n"
@@ -1338,7 +1327,7 @@ srv_printf_innodb_monitor(
fprintf(file,
"Total large memory allocated " ULINTPF "\n"
"Dictionary memory allocated " ULINTPF "\n",
- os_total_large_mem_allocated,
+ ulint{os_total_large_mem_allocated},
dict_sys_get_size());
buf_print_io(file);
@@ -1545,7 +1534,6 @@ srv_export_innodb_status(void)
export_vars.innodb_pages_created = stat.n_pages_created;
export_vars.innodb_pages_read = stat.n_pages_read;
- export_vars.innodb_page0_read = srv_stats.page0_read;
export_vars.innodb_pages_written = stat.n_pages_written;
@@ -1926,11 +1914,11 @@ void
srv_active_wake_master_thread_low()
{
ut_ad(!srv_read_only_mode);
- ut_ad(!srv_sys_mutex_own());
+ ut_ad(!mutex_own(&srv_sys.mutex));
srv_inc_activity_count();
- if (my_atomic_loadlint(&srv_sys.n_threads_active[SRV_MASTER]) == 0) {
+ if (srv_sys.n_threads_active[SRV_MASTER] == 0) {
srv_slot_t* slot;
srv_sys_mutex_enter();
@@ -1952,11 +1940,12 @@ srv_active_wake_master_thread_low()
void
srv_wake_purge_thread_if_not_active()
{
- ut_ad(!srv_sys_mutex_own());
+ ut_ad(!srv_read_only_mode);
+ ut_ad(!mutex_own(&srv_sys.mutex));
if (purge_sys.enabled() && !purge_sys.paused()
- && !my_atomic_loadlint(&srv_sys.n_threads_active[SRV_PURGE])
- && trx_sys.history_size()) {
+ && !srv_sys.n_threads_active[SRV_PURGE]
+ && trx_sys.rseg_history_len) {
srv_release_threads(SRV_PURGE, 1);
}
@@ -2024,16 +2013,12 @@ srv_master_evict_from_table_cache(
{
ulint n_tables_evicted = 0;
- rw_lock_x_lock(&dict_operation_lock);
-
- dict_mutex_enter_for_mysql();
+ dict_sys_lock();
n_tables_evicted = dict_make_room_in_cache(
innobase_get_table_cache_size(), pct_check);
- dict_mutex_exit_for_mysql();
-
- rw_lock_x_unlock(&dict_operation_lock);
+ dict_sys_unlock();
return(n_tables_evicted);
}
@@ -2443,8 +2428,7 @@ static bool srv_purge_should_exit()
return(true);
}
/* Slow shutdown was requested. */
- ulint history_size = trx_sys.history_size();
-
+ uint32_t history_size = trx_sys.rseg_history_len;
if (history_size) {
#if defined HAVE_SYSTEMD && !defined EMBEDDED_LIBRARY
static time_t progress_time;
@@ -2453,7 +2437,7 @@ static bool srv_purge_should_exit()
progress_time = now;
service_manager_extend_timeout(
INNODB_EXTEND_TIMEOUT_INTERVAL,
- "InnoDB: to purge " ULINTPF " transactions",
+ "InnoDB: to purge %u transactions",
history_size);
}
#endif
@@ -2480,7 +2464,7 @@ static bool srv_task_execute(ut_d(srv_slot_t *slot))
mutex_exit(&srv_sys.tasks_mutex);
ut_d(thr->thread_slot = slot);
que_run_threads(thr);
- my_atomic_addlint(&purge_sys.n_completed, 1);
+ purge_sys.n_tasks.fetch_sub(1, std::memory_order_release);
return true;
}
@@ -2523,7 +2507,7 @@ DECLARE_THREAD(srv_worker_thread)(
#endif
ut_a(srv_n_purge_threads > 1);
- ut_a(ulong(my_atomic_loadlint(&srv_sys.n_threads_active[SRV_WORKER]))
+ ut_a(ulong(srv_sys.n_threads_active[SRV_WORKER])
< srv_n_purge_threads);
/* We need to ensure that the worker threads exit after the
@@ -2564,17 +2548,17 @@ DECLARE_THREAD(srv_worker_thread)(
/** Do the actual purge operation.
@param[in,out] n_total_purged total number of purged pages
@return length of history list before the last purge batch. */
-static ulint srv_do_purge(ulint* n_total_purged
+static uint32_t srv_do_purge(ulint* n_total_purged
#ifdef UNIV_DEBUG
- , srv_slot_t* slot /*!< purge coordinator */
+ , srv_slot_t* slot /*!< purge coordinator */
#endif
- )
+ )
{
ulint n_pages_purged;
static ulint count = 0;
static ulint n_use_threads = 0;
- static ulint rseg_history_len = 0;
+ static uint32_t rseg_history_len = 0;
ulint old_activity_count = srv_get_activity_count();
const ulint n_threads = srv_n_purge_threads;
@@ -2592,7 +2576,7 @@ static ulint srv_do_purge(ulint* n_total_purged
}
do {
- if (trx_sys.history_size() > rseg_history_len
+ if (trx_sys.rseg_history_len > rseg_history_len
|| (srv_max_purge_lag > 0
&& rseg_history_len > srv_max_purge_lag)) {
@@ -2621,20 +2605,14 @@ static ulint srv_do_purge(ulint* n_total_purged
ut_a(n_use_threads <= n_threads);
/* Take a snapshot of the history list before purge. */
- if (!(rseg_history_len = trx_sys.history_size())) {
+ if (!(rseg_history_len = trx_sys.rseg_history_len)) {
break;
}
- ulint undo_trunc_freq =
- purge_sys.undo_trunc.get_rseg_truncate_frequency();
-
- ulint rseg_truncate_frequency = ut_min(
- static_cast<ulint>(srv_purge_rseg_truncate_frequency),
- undo_trunc_freq);
-
n_pages_purged = trx_purge(
n_use_threads,
- (++count % rseg_truncate_frequency) == 0
+ !(++count % srv_purge_rseg_truncate_frequency)
+ || purge_sys.truncate.current
#ifdef UNIV_DEBUG
, slot
#endif
@@ -2658,7 +2636,7 @@ srv_purge_coordinator_suspend(
/*==========================*/
srv_slot_t* slot, /*!< in/out: Purge coordinator
thread slot */
- ulint rseg_history_len) /*!< in: history list length
+ uint32_t rseg_history_len) /*!< in: history list length
before last purge */
{
ut_ad(!srv_read_only_mode);
@@ -2675,7 +2653,7 @@ srv_purge_coordinator_suspend(
/* We don't wait right away on the the non-timed wait because
we want to signal the thread that wants to suspend purge. */
const bool wait = stop
- || rseg_history_len <= trx_sys.history_size();
+ || rseg_history_len <= trx_sys.rseg_history_len;
const bool timeout = srv_resume_thread(
slot, sig_count, wait,
stop ? 0 : SRV_PURGE_MAX_TIMEOUT);
@@ -2685,12 +2663,12 @@ srv_purge_coordinator_suspend(
rw_lock_x_lock(&purge_sys.latch);
stop = srv_shutdown_state == SRV_SHUTDOWN_NONE
- && purge_sys.paused_latched();
+ && purge_sys.paused();
if (!stop) {
if (timeout
&& rseg_history_len < 5000
- && rseg_history_len == trx_sys.history_size()) {
+ && rseg_history_len == trx_sys.rseg_history_len) {
/* No new records were added since the
wait started. Simply wait for new
records. The magic number 5000 is an
@@ -2749,7 +2727,7 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
rw_lock_create(PFS_NOT_INSTRUMENTED, &slot->debug_sync_lock,
SYNC_NO_ORDER_CHECK);
#endif
- ulint rseg_history_len = trx_sys.history_size();
+ uint32_t rseg_history_len = trx_sys.rseg_history_len;
do {
/* If there are no records to purge or the last
@@ -2782,11 +2760,6 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
/* Note that we are shutting down. */
rw_lock_x_lock(&purge_sys.latch);
purge_sys.coordinator_shutdown();
-
- /* If there are any pending undo-tablespace truncate then clear
- it off as we plan to shutdown the purge thread. */
- purge_sys.undo_trunc.clear();
-
/* Ensure that the wait in purge_sys_t::stop() will terminate. */
os_event_set(purge_sys.event);
@@ -2878,9 +2851,7 @@ srv_purge_wakeup()
srv_release_threads(SRV_WORKER, n_workers);
}
- } while (!my_atomic_loadptr_explicit(reinterpret_cast<void**>
- (&srv_running),
- MY_MEMORY_ORDER_RELAXED)
+ } while (!srv_running.load(std::memory_order_relaxed)
&& (srv_sys.n_threads_active[SRV_WORKER]
|| srv_sys.n_threads_active[SRV_PURGE]));
}
@@ -2894,41 +2865,6 @@ void srv_purge_shutdown()
} while (srv_sys.sys_threads[SRV_PURGE_SLOT].in_use);
}
-/** Check if tablespace is being truncated.
-(Ignore system-tablespace as we don't re-create the tablespace
-and so some of the action that are suppressed by this function
-for independent tablespace are not applicable to system-tablespace).
-@param space_id space_id to check for truncate action
-@return true if being truncated, false if not being
- truncated or tablespace is system-tablespace. */
-bool
-srv_is_tablespace_truncated(ulint space_id)
-{
- if (is_system_tablespace(space_id)) {
- return(false);
- }
-
- return(truncate_t::is_tablespace_truncated(space_id)
- || undo::Truncate::is_tablespace_truncated(space_id));
-
-}
-
-/** Check if tablespace was truncated.
-@param[in] space space object to check for truncate action
-@return true if tablespace was truncated and we still have an active
-MLOG_TRUNCATE REDO log record. */
-bool
-srv_was_tablespace_truncated(const fil_space_t* space)
-{
- if (space == NULL) {
- ut_ad(0);
- return(false);
- }
-
- return (!is_system_tablespace(space->id)
- && truncate_t::was_tablespace_truncated(space->id));
-}
-
#ifdef UNIV_DEBUG
static ulint get_first_slot(srv_thread_type type)
{
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 15b4ab8395c..bd393ec2157 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -73,7 +73,6 @@ Created 2/16/1996 Heikki Tuuri
#include "srv0start.h"
#include "srv0srv.h"
#include "btr0defragment.h"
-#include "row0trunc.h"
#include "mysql/service_wsrep.h" /* wsrep_recovery */
#include "trx0rseg.h"
#include "os0proc.h"
@@ -96,7 +95,6 @@ Created 2/16/1996 Heikki Tuuri
#include "row0upd.h"
#include "row0row.h"
#include "row0mysql.h"
-#include "row0trunc.h"
#include "btr0pcur.h"
#include "os0event.h"
#include "zlib.h"
@@ -676,9 +674,19 @@ static bool srv_undo_tablespace_open(const char* name, ulint space_id,
fil_set_max_space_id_if_bigger(space_id);
- fil_space_t* space = fil_space_create(
- undo_name, space_id, FSP_FLAGS_PAGE_SSIZE(),
- FIL_TYPE_TABLESPACE, NULL);
+ ulint fsp_flags;
+ switch (srv_checksum_algorithm) {
+ case SRV_CHECKSUM_ALGORITHM_FULL_CRC32:
+ case SRV_CHECKSUM_ALGORITHM_STRICT_FULL_CRC32:
+ fsp_flags = (FSP_FLAGS_FCRC32_MASK_MARKER
+ | FSP_FLAGS_FCRC32_PAGE_SSIZE());
+ break;
+ default:
+ fsp_flags = FSP_FLAGS_PAGE_SSIZE();
+ }
+
+ fil_space_t* space = fil_space_create(undo_name, space_id, fsp_flags,
+ FIL_TYPE_TABLESPACE, NULL);
ut_a(fil_validate());
ut_a(space);
@@ -781,8 +789,6 @@ srv_check_undo_redo_logs_exists()
return(DB_SUCCESS);
}
-undo::undo_spaces_t undo::Truncate::s_fix_up_spaces;
-
/** Open the configured number of dedicated undo tablespaces.
@param[in] create_new_db whether the database is being initialized
@return DB_SUCCESS or error code */
@@ -864,46 +870,8 @@ srv_undo_tablespaces_init(bool create_new_db)
prev_space_id = srv_undo_space_id_start - 1;
break;
case SRV_OPERATION_NORMAL:
- if (create_new_db) {
- break;
- }
- /* fall through */
case SRV_OPERATION_RESTORE:
case SRV_OPERATION_RESTORE_EXPORT:
- ut_ad(!create_new_db);
-
- /* Check if any of the UNDO tablespace needs fix-up because
- server crashed while truncate was active on UNDO tablespace.*/
- for (i = 0; i < n_undo_tablespaces; ++i) {
-
- undo::Truncate undo_trunc;
-
- if (undo_trunc.needs_fix_up(undo_tablespace_ids[i])) {
-
- char name[OS_FILE_MAX_PATH];
-
- snprintf(name, sizeof(name),
- "%s%cundo%03zu",
- srv_undo_dir, OS_PATH_SEPARATOR,
- undo_tablespace_ids[i]);
-
- os_file_delete(innodb_data_file_key, name);
-
- err = srv_undo_tablespace_create(
- name,
- SRV_UNDO_TABLESPACE_SIZE_IN_PAGES);
-
- if (err != DB_SUCCESS) {
- ib::error() << "Could not fix-up undo "
- " tablespace truncate '"
- << name << "'.";
- return(err);
- }
-
- undo::Truncate::s_fix_up_spaces.push_back(
- undo_tablespace_ids[i]);
- }
- }
break;
}
@@ -1008,64 +976,6 @@ srv_undo_tablespaces_init(bool create_new_db)
}
}
- if (!undo::Truncate::s_fix_up_spaces.empty()) {
-
- /* Step-1: Initialize the tablespace header and rsegs header. */
- mtr_t mtr;
-
- mtr_start(&mtr);
- /* Turn off REDO logging. We are in server start mode and fixing
- UNDO tablespace even before REDO log is read. Let's say we
- do REDO logging here then this REDO log record will be applied
- as part of the current recovery process. We surely don't need
- that as this is fix-up action parallel to REDO logging. */
- mtr_set_log_mode(&mtr, MTR_LOG_NO_REDO);
- buf_block_t* sys_header = trx_sysf_get(&mtr);
- if (!sys_header) {
- mtr.commit();
- return DB_CORRUPTION;
- }
-
- for (undo::undo_spaces_t::const_iterator it
- = undo::Truncate::s_fix_up_spaces.begin();
- it != undo::Truncate::s_fix_up_spaces.end();
- ++it) {
-
- undo::Truncate::add_space_to_trunc_list(*it);
-
- fil_space_t* space = fil_space_get(*it);
-
- fsp_header_init(space,
- SRV_UNDO_TABLESPACE_SIZE_IN_PAGES,
- &mtr);
-
- for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
- if (trx_sysf_rseg_get_space(sys_header, i)
- == *it) {
- trx_rseg_header_create(
- space, i, sys_header, &mtr);
- }
- }
-
- undo::Truncate::clear_trunc_list();
- }
- mtr_commit(&mtr);
-
- /* Step-2: Flush the dirty pages from the buffer pool. */
- for (undo::undo_spaces_t::const_iterator it
- = undo::Truncate::s_fix_up_spaces.begin();
- it != undo::Truncate::s_fix_up_spaces.end();
- ++it) {
- FlushObserver dummy(fil_system.sys_space, NULL, NULL);
- buf_LRU_flush_or_remove_pages(TRX_SYS_SPACE, &dummy);
- FlushObserver dummy2(fil_space_get(*it), NULL, NULL);
- buf_LRU_flush_or_remove_pages(*it, &dummy2);
-
- /* Remove the truncate redo log file. */
- undo::done(*it);
- }
- }
-
return(DB_SUCCESS);
}
@@ -1196,11 +1106,11 @@ srv_shutdown_all_bg_threads()
ut_ad(!srv_read_only_mode);
/* e. Exit the i/o threads */
- if (recv_sys->flush_start != NULL) {
- os_event_set(recv_sys->flush_start);
+ if (recv_sys.flush_start != NULL) {
+ os_event_set(recv_sys.flush_start);
}
- if (recv_sys->flush_end != NULL) {
- os_event_set(recv_sys->flush_end);
+ if (recv_sys.flush_end != NULL) {
+ os_event_set(recv_sys.flush_end);
}
os_event_set(buf_flush_event);
@@ -1293,9 +1203,7 @@ srv_prepare_to_delete_redo_log_files(
ulint pending_io = 0;
ulint count = 0;
- if ((log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
- != LOG_HEADER_FORMAT_CURRENT
- || log_sys.log.subformat != 2) {
+ if (log_sys.log.subformat != 2) {
srv_log_file_size = 0;
}
@@ -1314,12 +1222,10 @@ srv_prepare_to_delete_redo_log_files(
{
ib::info info;
- if (srv_log_file_size == 0) {
- info << ((log_sys.log.format
- & ~LOG_HEADER_FORMAT_ENCRYPTED)
- != LOG_HEADER_FORMAT_10_4
- ? "Upgrading redo log: "
- : "Downgrading redo log: ");
+ if (srv_log_file_size == 0
+ || (log_sys.log.format & ~log_t::FORMAT_ENCRYPTED)
+ != log_t::FORMAT_10_4) {
+ info << "Upgrading redo log: ";
} else if (n_files != srv_n_log_files
|| srv_log_file_size
!= srv_log_file_size_requested) {
@@ -1625,7 +1531,7 @@ dberr_t srv_start(bool create_new_db)
#endif /* UNIV_DEBUG */
log_sys.create();
- recv_sys_init();
+ recv_sys.create();
lock_sys.create(srv_lock_table_size);
/* Create i/o-handler threads: */
@@ -1653,7 +1559,7 @@ dberr_t srv_start(bool create_new_db)
#ifdef UNIV_LINUX
/* Wait for the setpriority() call to finish. */
- os_event_wait(recv_sys->flush_end);
+ os_event_wait(recv_sys.flush_end);
#endif /* UNIV_LINUX */
srv_start_state_set(SRV_START_STATE_IO);
}
@@ -1667,7 +1573,7 @@ dberr_t srv_start(bool create_new_db)
if (err != DB_SUCCESS) {
return(srv_init_abort(DB_ERROR));
}
- recv_sys_debug_free();
+ recv_sys.debug_free();
}
/* Open or create the data files. */
@@ -1912,7 +1818,7 @@ files_checked:
ulint ibuf_root = btr_create(
DICT_CLUSTERED | DICT_IBUF, fil_system.sys_space,
- DICT_IBUF_ID_MIN, dict_ind_redundant, NULL, &mtr);
+ DICT_IBUF_ID_MIN, dict_ind_redundant, &mtr);
mtr_commit(&mtr);
@@ -1951,28 +1857,20 @@ files_checked:
return(srv_init_abort(err));
}
} else {
- /* Invalidate the buffer pool to ensure that we reread
- the page that we read above, during recovery.
- Note that this is not as heavy weight as it seems. At
- this point there will be only ONE page in the buf_LRU
- and there must be no page in the buf_flush list. */
- buf_pool_invalidate();
-
- /* Scan and locate truncate log files. Parsed located files
- and add table to truncate information to central vector for
- truncate fix-up action post recovery. */
- err = TruncateLogParser::scan_and_parse(srv_log_group_home_dir);
- if (err != DB_SUCCESS) {
+ /* Work around the bug that we were performing a dirty read of
+ at least the TRX_SYS page into the buffer pool above, without
+ reading or applying any redo logs.
- return(srv_init_abort(DB_ERROR));
- }
+ MDEV-19229 FIXME: Remove the dirty reads and this call.
+ Add an assertion that the buffer pool is empty. */
+ buf_pool_invalidate();
/* We always try to do a recovery, even if the database had
been shut down normally: this is the normal startup path */
err = recv_recovery_from_checkpoint_start(flushed_lsn);
- recv_sys->dblwr.pages.clear();
+ recv_sys.dblwr.pages.clear();
if (err != DB_SUCCESS) {
return(srv_init_abort(err));
@@ -2004,8 +1902,8 @@ files_checked:
recv_apply_hashed_log_recs(true);
- if (recv_sys->found_corrupt_log
- || recv_sys->found_corrupt_fs) {
+ if (recv_sys.found_corrupt_log
+ || recv_sys.found_corrupt_fs) {
return(srv_init_abort(DB_CORRUPTION));
}
@@ -2028,7 +1926,7 @@ files_checked:
/* New data file(s) were added */
mtr.start();
buf_block_t* block = buf_page_get(
- page_id_t(0, 0), univ_page_size,
+ page_id_t(0, 0), 0,
RW_SX_LATCH, &mtr);
ulint size = mach_read_from_4(
FSP_HEADER_OFFSET + FSP_SIZE
@@ -2052,8 +1950,7 @@ files_checked:
#ifdef UNIV_DEBUG
{
mtr.start();
- buf_block_t* block = buf_page_get(page_id_t(0, 0),
- univ_page_size,
+ buf_block_t* block = buf_page_get(page_id_t(0, 0), 0,
RW_S_LATCH, &mtr);
ut_ad(mach_read_from_4(FSP_SIZE + FSP_HEADER_OFFSET
+ block->frame)
@@ -2147,9 +2044,8 @@ files_checked:
&& srv_n_log_files_found == srv_n_log_files
&& log_sys.log.format
== (srv_encrypt_log
- ? LOG_HEADER_FORMAT_CURRENT
- | LOG_HEADER_FORMAT_ENCRYPTED
- : LOG_HEADER_FORMAT_CURRENT)
+ ? log_t::FORMAT_ENC_10_4
+ : log_t::FORMAT_10_4)
&& log_sys.log.subformat == 2) {
/* No need to add or remove encryption,
upgrade, downgrade, or resize. */
@@ -2208,8 +2104,9 @@ files_checked:
}
/* Validate a few system page types that were left
- uninitialized by older versions of MySQL. */
- if (!high_level_read_only) {
+ uninitialized before MySQL or MariaDB 5.5. */
+ if (!high_level_read_only
+ && !fil_system.sys_space->full_crc32()) {
buf_block_t* block;
mtr.start();
/* Bitmap page types will be reset in
@@ -2217,24 +2114,24 @@ files_checked:
block = buf_page_get(
page_id_t(IBUF_SPACE_ID,
FSP_IBUF_HEADER_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr);
/* Already MySQL 3.23.53 initialized
FSP_IBUF_TREE_ROOT_PAGE_NO to
FIL_PAGE_INDEX. No need to reset that one. */
block = buf_page_get(
page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_TRX_SYS,
&mtr);
block = buf_page_get(
page_id_t(TRX_SYS_SPACE,
FSP_FIRST_RSEG_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr);
block = buf_page_get(
page_id_t(TRX_SYS_SPACE, FSP_DICT_HDR_PAGE_NO),
- univ_page_size, RW_X_LATCH, &mtr);
+ 0, RW_X_LATCH, &mtr);
fil_block_check_type(*block, FIL_PAGE_TYPE_SYS, &mtr);
mtr.commit();
}
@@ -2244,17 +2141,18 @@ files_checked:
The data dictionary latch should guarantee that there is at
most one data dictionary transaction active at a time. */
if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
+ /* If the following call is ever removed, the
+ first-time ha_innobase::open() must hold (or
+ acquire and release) a table lock that
+ conflicts with trx_resurrect_table_locks(), to
+ ensure that any recovered incomplete ALTER TABLE
+ will have been rolled back. Otherwise,
+ dict_table_t::instant could be cleared by rollback
+ invoking dict_index_t::clear_instant_alter() while
+ open table handles exist in client connections. */
trx_rollback_recovered(false);
}
- /* Fix-up truncate of tables in the system tablespace
- if server crashed while truncate was active. The non-
- system tables are done after tablespace discovery. Do
- this now because this procedure assumes that no pages
- have changed since redo recovery. Tablespace discovery
- can do updates to pages in the system tablespace.*/
- err = truncate_t::fixup_tables_in_system_tablespace();
-
if (srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE) {
/* Open or Create SYS_TABLESPACES and SYS_DATAFILES
so that tablespace names and other metadata can be
@@ -2281,10 +2179,6 @@ files_checked:
dict_check_tablespaces_and_store_max_id();
}
- /* Fix-up truncate of table if server crashed while truncate
- was active. */
- err = truncate_t::fixup_tables_in_non_system_tablespace();
-
if (err != DB_SUCCESS) {
return(srv_init_abort(err));
}
@@ -2479,7 +2373,7 @@ skip_monitors:
Create the dump/load thread only when not running with
--wsrep-recover.
*/
- if (!wsrep_recovery) {
+ if (!get_wsrep_recovery()) {
#endif /* WITH_WSREP */
/* Create the buffer pool dump/load thread */
@@ -2537,9 +2431,7 @@ void srv_shutdown_bg_undo_sources()
/** Shut down InnoDB. */
void innodb_shutdown()
{
- ut_ad(!my_atomic_loadptr_explicit(reinterpret_cast<void**>
- (&srv_running),
- MY_MEMORY_ORDER_RELAXED));
+ ut_ad(!srv_running.load(std::memory_order_relaxed));
ut_ad(!srv_undo_sources);
switch (srv_operation) {
@@ -2578,7 +2470,7 @@ void innodb_shutdown()
}
ut_ad(dict_stats_event || !srv_was_started || srv_read_only_mode);
- ut_ad(dict_sys || !srv_was_started);
+ ut_ad(dict_sys.is_initialised() || !srv_was_started);
ut_ad(trx_sys.is_initialised() || !srv_was_started);
ut_ad(buf_dblwr || !srv_was_started || srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
@@ -2607,7 +2499,7 @@ void innodb_shutdown()
and closing the data dictionary. */
#ifdef BTR_CUR_HASH_ADAPT
- if (dict_sys) {
+ if (dict_sys.is_initialised()) {
btr_search_disable(true);
}
#endif /* BTR_CUR_HASH_ADAPT */
@@ -2628,7 +2520,7 @@ void innodb_shutdown()
mutex_free(&srv_misc_tmpfile_mutex);
}
- dict_close();
+ dict_sys.close();
btr_search_sys_free();
/* 3. Free all InnoDB's own mutexes and the os_fast_mutexes inside
@@ -2641,7 +2533,7 @@ void innodb_shutdown()
/* 4. Free all allocated memory */
pars_lexer_close();
- recv_sys_close();
+ recv_sys.close();
ut_ad(buf_pool_ptr || !srv_was_started);
if (buf_pool_ptr) {
diff --git a/storage/innobase/sync/sync0arr.cc b/storage/innobase/sync/sync0arr.cc
index 352e93a4392..6e858254ad4 100644
--- a/storage/innobase/sync/sync0arr.cc
+++ b/storage/innobase/sync/sync0arr.cc
@@ -76,8 +76,8 @@ keep the global wait array for the sake of diagnostics and also to avoid
infinite wait The error_monitor thread scans the global wait array to signal
any waiting threads who have missed the signal. */
-typedef SyncArrayMutex::MutexType WaitMutex;
-typedef BlockSyncArrayMutex::MutexType BlockWaitMutex;
+typedef TTASEventMutex<GenericPolicy> WaitMutex;
+typedef TTASEventMutex<BlockMutexPolicy> BlockWaitMutex;
/** The latch types that use the sync array. */
union sync_object_t {
@@ -501,7 +501,7 @@ sync_array_cell_print(
WaitMutex* mutex = cell->latch.mutex;
const WaitMutex::MutexPolicy& policy = mutex->policy();
#ifdef UNIV_DEBUG
- const char* name = policy.get_enter_filename();
+ const char* name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been released. */
name = "NULL";
@@ -520,7 +520,7 @@ sync_array_cell_print(
mutex->state()
#ifdef UNIV_DEBUG
,name,
- policy.get_enter_line()
+ policy.context.get_enter_line()
#endif /* UNIV_DEBUG */
);
}
@@ -530,7 +530,7 @@ sync_array_cell_print(
const BlockWaitMutex::MutexPolicy& policy =
mutex->policy();
#ifdef UNIV_DEBUG
- const char* name = policy.get_enter_filename();
+ const char* name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been released. */
name = "NULL";
@@ -548,7 +548,7 @@ sync_array_cell_print(
(ulong) mutex->state()
#ifdef UNIV_DEBUG
,name,
- (ulong) policy.get_enter_line()
+ (ulong) policy.context.get_enter_line()
#endif /* UNIV_DEBUG */
);
} else if (type == RW_LOCK_X
@@ -593,8 +593,8 @@ sync_array_cell_print(
#endif
"\n",
rw_lock_get_reader_count(rwlock),
- my_atomic_load32_explicit(&rwlock->waiters, MY_MEMORY_ORDER_RELAXED),
- my_atomic_load32_explicit(&rwlock->lock_word, MY_MEMORY_ORDER_RELAXED),
+ rwlock->waiters.load(std::memory_order_relaxed),
+ rwlock->lock_word.load(std::memory_order_relaxed),
innobase_basename(rwlock->last_x_file_name),
rwlock->last_x_line
#if 0 /* JAN: TODO: FIX LATER */
@@ -740,7 +740,7 @@ sync_array_detect_deadlock(
const WaitMutex::MutexPolicy& policy = mutex->policy();
if (mutex->state() != MUTEX_STATE_UNLOCKED) {
- thread = policy.get_thread_id();
+ thread = policy.context.get_thread_id();
/* Note that mutex->thread_id above may be
also OS_THREAD_ID_UNDEFINED, because the
@@ -755,7 +755,7 @@ sync_array_detect_deadlock(
if (ret) {
const char* name;
- name = policy.get_enter_filename();
+ name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been
@@ -767,7 +767,7 @@ sync_array_detect_deadlock(
<< "Mutex " << mutex << " owned by"
" thread " << os_thread_pf(thread)
<< " file " << name << " line "
- << policy.get_enter_line();
+ << policy.context.get_enter_line();
sync_array_cell_print(stderr, cell);
@@ -787,7 +787,7 @@ sync_array_detect_deadlock(
mutex->policy();
if (mutex->state() != MUTEX_STATE_UNLOCKED) {
- thread = policy.get_thread_id();
+ thread = policy.context.get_thread_id();
/* Note that mutex->thread_id above may be
also OS_THREAD_ID_UNDEFINED, because the
@@ -802,7 +802,7 @@ sync_array_detect_deadlock(
if (ret) {
const char* name;
- name = policy.get_enter_filename();
+ name = policy.context.get_enter_filename();
if (name == NULL) {
/* The mutex might have been
@@ -814,7 +814,7 @@ sync_array_detect_deadlock(
<< "Mutex " << mutex << " owned by"
" thread " << os_thread_pf(thread)
<< " file " << name << " line "
- << policy.get_enter_line();
+ << policy.context.get_enter_line();
return(true);
@@ -972,7 +972,7 @@ sync_array_print_long_waits_low(
ulint i;
/* For huge tables, skip the check during CHECK TABLE etc... */
- if (fatal_timeout > SRV_SEMAPHORE_WAIT_EXTENSION) {
+ if (btr_validate_index_running) {
return(false);
}
@@ -1381,9 +1381,9 @@ sync_arr_fill_sys_semphore_waits_table(
//fields[SYS_SEMAPHORE_WAITS_HOLDER_LINE]->set_notnull();
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_READERS], rw_lock_get_reader_count(rwlock)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_WAITERS_FLAG],
- my_atomic_load32_explicit(&rwlock->waiters, MY_MEMORY_ORDER_RELAXED)));
+ rwlock->waiters.load(std::memory_order_relaxed)));
OK(field_store_ulint(fields[SYS_SEMAPHORE_WAITS_LOCK_WORD],
- my_atomic_load32_explicit(&rwlock->lock_word, MY_MEMORY_ORDER_RELAXED)));
+ rwlock->lock_word.load(std::memory_order_relaxed)));
OK(field_store_string(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_FILE], innobase_basename(rwlock->last_x_file_name)));
OK(fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE]->store(rwlock->last_x_line, true));
fields[SYS_SEMAPHORE_WAITS_LAST_WRITER_LINE]->set_notnull();
diff --git a/storage/innobase/sync/sync0rw.cc b/storage/innobase/sync/sync0rw.cc
index f075e01c857..2795fc902fc 100644
--- a/storage/innobase/sync/sync0rw.cc
+++ b/storage/innobase/sync/sync0rw.cc
@@ -205,8 +205,8 @@ rw_lock_create_func(
/* If this is the very first time a synchronization object is
created, then the following call initializes the sync system. */
- lock->lock_word = X_LOCK_DECR;
- lock->waiters = 0;
+ lock->lock_word.store(X_LOCK_DECR, std::memory_order_relaxed);
+ lock->waiters.store(0, std::memory_order_relaxed);
lock->sx_recursive = 0;
lock->writer_thread= 0;
@@ -238,9 +238,7 @@ rw_lock_create_func(
lock->is_block_lock = 0;
mutex_enter(&rw_lock_list_mutex);
-
UT_LIST_ADD_FIRST(rw_lock_list, lock);
-
mutex_exit(&rw_lock_list_mutex);
}
@@ -254,8 +252,7 @@ rw_lock_free_func(
rw_lock_t* lock) /*!< in/out: rw-lock */
{
ut_ad(rw_lock_validate(lock));
- ut_a(my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED) == X_LOCK_DECR);
+ ut_a(lock->lock_word.load(std::memory_order_relaxed) == X_LOCK_DECR);
mutex_enter(&rw_lock_list_mutex);
@@ -297,8 +294,7 @@ lock_loop:
/* Spin waiting for the writer field to become free */
HMT_low();
while (i < srv_n_spin_wait_rounds &&
- my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED) <= 0) {
+ lock->lock_word.load(std::memory_order_relaxed) <= 0) {
ut_delay(srv_spin_wait_delay);
i++;
}
@@ -338,7 +334,7 @@ lock_loop:
/* Set waiters before checking lock_word to ensure wake-up
signal is sent. This may lead to some unnecessary signals. */
- my_atomic_fas32_explicit(&lock->waiters, 1, MY_MEMORY_ORDER_ACQUIRE);
+ lock->waiters.exchange(1, std::memory_order_acquire);
if (rw_lock_s_lock_low(lock, pass, file_name, line)) {
@@ -416,10 +412,10 @@ rw_lock_x_lock_wait_func(
sync_array_t* sync_arr;
int64_t count_os_wait = 0;
- ut_ad(my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) <= threshold);
+ ut_ad(lock->lock_word.load(std::memory_order_relaxed) <= threshold);
HMT_low();
- while (my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) < threshold) {
+ while (lock->lock_word.load(std::memory_order_relaxed) < threshold) {
ut_delay(srv_spin_wait_delay);
if (i < srv_n_spin_wait_rounds) {
@@ -438,7 +434,7 @@ rw_lock_x_lock_wait_func(
i = 0;
/* Check lock_word to ensure wake-up isn't missed.*/
- if (my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) < threshold) {
+ if (lock->lock_word.load(std::memory_order_relaxed) < threshold) {
++count_os_wait;
@@ -528,18 +524,17 @@ rw_lock_x_lock_low(
file_name, line);
} else {
- int32_t lock_word = my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_word = lock->lock_word.load(std::memory_order_relaxed);
/* At least one X lock by this thread already
exists. Add another. */
if (lock_word == 0
|| lock_word == -X_LOCK_HALF_DECR) {
- my_atomic_add32_explicit(&lock->lock_word, -X_LOCK_DECR,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_sub(X_LOCK_DECR,
+ std::memory_order_relaxed);
} else {
ut_ad(lock_word <= -X_LOCK_DECR);
- my_atomic_add32_explicit(&lock->lock_word, -1,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_sub(1,
+ std::memory_order_relaxed);
}
}
@@ -611,10 +606,10 @@ rw_lock_sx_lock_low(
read and write to the lock_word. */
#ifdef UNIV_DEBUG
- int32_t lock_word =
+ auto lock_word =
#endif
- my_atomic_add32_explicit(&lock->lock_word, -X_LOCK_HALF_DECR,
- MY_MEMORY_ORDER_RELAXED);
+ lock->lock_word.fetch_sub(X_LOCK_HALF_DECR,
+ std::memory_order_relaxed);
ut_ad((lock_word == 0)
|| ((lock_word <= -X_LOCK_DECR)
@@ -682,7 +677,7 @@ lock_loop:
/* Spin waiting for the lock_word to become free */
HMT_low();
while (i < srv_n_spin_wait_rounds
- && my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) <= X_LOCK_HALF_DECR) {
+ && lock->lock_word.load(std::memory_order_relaxed) <= X_LOCK_HALF_DECR) {
ut_delay(srv_spin_wait_delay);
i++;
}
@@ -707,7 +702,7 @@ lock_loop:
/* Waiters must be set before checking lock_word, to ensure signal
is sent. This could lead to a few unnecessary wake-up signals. */
- my_atomic_fas32_explicit(&lock->waiters, 1, MY_MEMORY_ORDER_ACQUIRE);
+ lock->waiters.exchange(1, std::memory_order_acquire);
if (rw_lock_x_lock_low(lock, pass, file_name, line)) {
sync_array_free_cell(sync_arr, cell);
@@ -783,7 +778,7 @@ lock_loop:
/* Spin waiting for the lock_word to become free */
while (i < srv_n_spin_wait_rounds
- && my_atomic_load32_explicit(&lock->lock_word, MY_MEMORY_ORDER_RELAXED) <= X_LOCK_HALF_DECR) {
+ && lock->lock_word.load(std::memory_order_relaxed) <= X_LOCK_HALF_DECR) {
ut_delay(srv_spin_wait_delay);
i++;
}
@@ -807,7 +802,7 @@ lock_loop:
/* Waiters must be set before checking lock_word, to ensure signal
is sent. This could lead to a few unnecessary wake-up signals. */
- my_atomic_fas32_explicit(&lock->waiters, 1, MY_MEMORY_ORDER_ACQUIRE);
+ lock->waiters.exchange(1, std::memory_order_acquire);
if (rw_lock_sx_lock_low(lock, pass, file_name, line)) {
@@ -850,11 +845,9 @@ rw_lock_validate(
ut_ad(lock);
- lock_word = my_atomic_load32_explicit(const_cast<int32_t*>(&lock->lock_word),
- MY_MEMORY_ORDER_RELAXED);
+ lock_word = lock->lock_word.load(std::memory_order_relaxed);
- ut_ad(my_atomic_load32_explicit(const_cast<int32_t*>(&lock->waiters),
- MY_MEMORY_ORDER_RELAXED) < 2);
+ ut_ad(lock->waiters.load(std::memory_order_relaxed) < 2);
ut_ad(lock_word > -(2 * X_LOCK_DECR));
ut_ad(lock_word <= X_LOCK_DECR);
@@ -917,8 +910,7 @@ rw_lock_add_debug_info(
rw_lock_debug_mutex_exit();
if (pass == 0 && lock_type != RW_LOCK_X_WAIT) {
- int32_t lock_word = my_atomic_load32_explicit(&lock->lock_word,
- MY_MEMORY_ORDER_RELAXED);
+ auto lock_word = lock->lock_word.load(std::memory_order_relaxed);
/* Recursive x while holding SX
(lock_type == RW_LOCK_X && lock_word == -X_LOCK_HALF_DECR)
@@ -1104,11 +1096,11 @@ rw_lock_list_print_info(
count++;
- if (my_atomic_load32_explicit(const_cast<int32_t*>(&lock->lock_word), MY_MEMORY_ORDER_RELAXED) != X_LOCK_DECR) {
+ if (lock->lock_word.load(std::memory_order_relaxed) != X_LOCK_DECR) {
fprintf(file, "RW-LOCK: %p ", (void*) lock);
- if (int32_t waiters= my_atomic_load32_explicit(const_cast<int32_t*>(&lock->waiters), MY_MEMORY_ORDER_RELAXED)) {
+ if (int32_t waiters= lock->waiters.load(std::memory_order_relaxed)) {
fprintf(file, " (%d waiters)\n", waiters);
} else {
putc('\n', file);
@@ -1172,10 +1164,10 @@ rw_lock_debug_print(
fprintf(f, "\n");
}
-/** Print where it was locked from
+/** Print the rw-lock information.
@return the string representation */
std::string
-rw_lock_t::locked_from() const
+rw_lock_t::to_string() const
{
/* Note: For X locks it can be locked form multiple places because
the same thread can call X lock recursively. */
@@ -1185,6 +1177,11 @@ rw_lock_t::locked_from() const
ut_ad(rw_lock_validate(this));
+ msg << "RW-LATCH: "
+ << "thread id " << os_thread_pf(os_thread_get_curr_id())
+ << " addr: " << this
+ << " Locked from: ";
+
rw_lock_debug_mutex_enter();
for (rw_lock_debug_t* info = UT_LIST_GET_FIRST(debug_list);
@@ -1207,19 +1204,4 @@ rw_lock_t::locked_from() const
return(msg.str());
}
-
-/** Print the rw-lock information.
-@return the string representation */
-std::string
-rw_lock_t::to_string() const
-{
- std::ostringstream msg;
-
- msg << "RW-LATCH: "
- << "thread id " << os_thread_pf(os_thread_get_curr_id())
- << " addr: " << this
- << " Locked from: " << locked_from().c_str();
-
- return(msg.str());
-}
#endif /* UNIV_DEBUG */
diff --git a/storage/innobase/trx/trx0purge.cc b/storage/innobase/trx/trx0purge.cc
index cd1a57998f3..39035dc545e 100644
--- a/storage/innobase/trx/trx0purge.cc
+++ b/storage/innobase/trx/trx0purge.cc
@@ -166,8 +166,6 @@ void purge_sys_t::create()
ut_ad(event);
m_paused= 0;
query= purge_graph_build();
- n_submitted= 0;
- n_completed= 0;
next_stored= false;
rseg= NULL;
page_no= 0;
@@ -176,7 +174,8 @@ void purge_sys_t::create()
hdr_offset= 0;
rw_lock_create(trx_purge_latch_key, &latch, SYNC_PURGE_LATCH);
mutex_create(LATCH_ID_PURGE_SYS_PQ, &pq_mutex);
- undo_trunc.create();
+ truncate.current= NULL;
+ truncate.last= NULL;
}
/** Close the purge subsystem on shutdown. */
@@ -185,7 +184,8 @@ void purge_sys_t::close()
ut_ad(this == &purge_sys);
if (!event) return;
- m_enabled= false;
+ ut_ad(!enabled());
+ ut_ad(n_tasks.load(std::memory_order_relaxed) == 0);
trx_t* trx = query->trx;
que_graph_free(query);
ut_ad(!trx->id);
@@ -308,7 +308,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
rseg->needs_purge = true;
}
- trx_sys.history_insert();
+ trx_sys.rseg_history_len++;
if (undo->state == TRX_UNDO_CACHED) {
UT_LIST_ADD_FIRST(rseg->undo_cached, undo);
@@ -334,7 +334,7 @@ trx_purge_remove_log_hdr(
{
flst_remove(rseg_hdr + TRX_RSEG_HISTORY,
log_hdr + TRX_UNDO_HISTORY_NODE, mtr);
- trx_sys.history_remove();
+ trx_sys.rseg_history_len--;
}
/** Free an undo log segment, and remove the header from the history list.
@@ -504,309 +504,22 @@ func_exit:
goto loop;
}
-/** UNDO log truncate logger. Needed to track state of truncate during crash.
-An auxiliary redo log file undo_<space_id>_trunc.log will created while the
-truncate of the UNDO is in progress. This file is required during recovery
-to complete the truncate. */
-
-namespace undo {
- /** Magic Number to indicate truncate action is complete. */
- static const ib_uint32_t s_magic = 76845412;
-
- /** Populate log file name based on space_id
- @param[in] space_id id of the undo tablespace.
- @return DB_SUCCESS or error code */
- static dberr_t populate_log_file_name(
- ulint space_id,
- char*& log_file_name)
- {
- static const char s_log_prefix[] = "undo_";
- static const char s_log_ext[] = "trunc.log";
-
- ulint log_file_name_sz = strlen(srv_log_group_home_dir)
- + (22 - 1 /* NUL */
- + sizeof s_log_prefix + sizeof s_log_ext);
-
- log_file_name = new (std::nothrow) char[log_file_name_sz];
- if (log_file_name == 0) {
- return(DB_OUT_OF_MEMORY);
- }
-
- memset(log_file_name, 0, log_file_name_sz);
-
- strcpy(log_file_name, srv_log_group_home_dir);
- ulint log_file_name_len = strlen(log_file_name);
-
- if (log_file_name[log_file_name_len - 1]
- != OS_PATH_SEPARATOR) {
-
- log_file_name[log_file_name_len]
- = OS_PATH_SEPARATOR;
- log_file_name_len = strlen(log_file_name);
- }
-
- snprintf(log_file_name + log_file_name_len,
- log_file_name_sz - log_file_name_len,
- "%s" ULINTPF "_%s", s_log_prefix,
- space_id, s_log_ext);
-
- return(DB_SUCCESS);
- }
-
- /** Mark completion of undo truncate action by writing magic number to
- the log file and then removing it from the disk.
- If we are going to remove it from disk then why write magic number ?
- This is to safeguard from unlink (file-system) anomalies that will keep
- the link to the file even after unlink action is successfull and
- ref-count = 0.
- @param[in] space_id id of the undo tablespace to truncate.*/
- void done(
- ulint space_id)
- {
- dberr_t err;
- char* log_file_name;
-
- /* Step-1: Create the log file name using the pre-decided
- prefix/suffix and table id of undo tablepsace to truncate. */
- err = populate_log_file_name(space_id, log_file_name);
- if (err != DB_SUCCESS) {
- return;
- }
-
- /* Step-2: Open log file and write magic number to
- indicate done phase. */
- bool ret;
- os_file_t handle =
- os_file_create_simple_no_error_handling(
- innodb_log_file_key, log_file_name,
- OS_FILE_OPEN, OS_FILE_READ_WRITE,
- srv_read_only_mode, &ret);
-
- if (!ret) {
- os_file_delete(innodb_log_file_key, log_file_name);
- delete[] log_file_name;
- return;
- }
-
- ulint sz = srv_page_size;
- void* buf = ut_zalloc_nokey(sz + srv_page_size);
- if (buf == NULL) {
- os_file_close(handle);
- os_file_delete(innodb_log_file_key, log_file_name);
- delete[] log_file_name;
- return;
- }
-
- byte* log_buf = static_cast<byte*>(
- ut_align(buf, srv_page_size));
-
- mach_write_to_4(log_buf, undo::s_magic);
-
- IORequest request(IORequest::WRITE);
-
- err = os_file_write(
- request, log_file_name, handle, log_buf, 0, sz);
-
- ut_ad(err == DB_SUCCESS);
-
- os_file_flush(handle);
- os_file_close(handle);
-
- ut_free(buf);
- os_file_delete(innodb_log_file_key, log_file_name);
- delete[] log_file_name;
- }
-
- /** Check if TRUNCATE_DDL_LOG file exist.
- @param[in] space_id id of the undo tablespace.
- @return true if exist else false. */
- bool is_log_present(
- ulint space_id)
- {
- dberr_t err;
- char* log_file_name;
-
- /* Step-1: Populate log file name. */
- err = populate_log_file_name(space_id, log_file_name);
- if (err != DB_SUCCESS) {
- return(false);
- }
-
- /* Step-2: Check for existence of the file. */
- bool exist;
- os_file_type_t type;
- os_file_status(log_file_name, &exist, &type);
-
- /* Step-3: If file exists, check it for presence of magic
- number. If found, then delete the file and report file
- doesn't exist as presence of magic number suggest that
- truncate action was complete. */
-
- if (exist) {
- bool ret;
- os_file_t handle =
- os_file_create_simple_no_error_handling(
- innodb_log_file_key, log_file_name,
- OS_FILE_OPEN, OS_FILE_READ_WRITE,
- srv_read_only_mode, &ret);
- if (!ret) {
- os_file_delete(innodb_log_file_key,
- log_file_name);
- delete[] log_file_name;
- return(false);
- }
-
- ulint sz = srv_page_size;
- void* buf = ut_zalloc_nokey(sz + srv_page_size);
- if (buf == NULL) {
- os_file_close(handle);
- os_file_delete(innodb_log_file_key,
- log_file_name);
- delete[] log_file_name;
- return(false);
- }
-
- byte* log_buf = static_cast<byte*>(
- ut_align(buf, srv_page_size));
-
- IORequest request(IORequest::READ);
-
- dberr_t err;
-
- err = os_file_read(request, handle, log_buf, 0, sz);
-
- os_file_close(handle);
-
- if (err != DB_SUCCESS) {
-
- ib::info()
- << "Unable to read '"
- << log_file_name << "' : "
- << ut_strerr(err);
-
- os_file_delete(
- innodb_log_file_key, log_file_name);
-
- ut_free(buf);
-
- delete[] log_file_name;
-
- return(false);
- }
-
- ulint magic_no = mach_read_from_4(log_buf);
-
- ut_free(buf);
-
- if (magic_no == undo::s_magic) {
- /* Found magic number. */
- os_file_delete(innodb_log_file_key,
- log_file_name);
- delete[] log_file_name;
- return(false);
- }
- }
-
- delete[] log_file_name;
-
- return(exist);
- }
-};
-
-/** Iterate over all the UNDO tablespaces and check if any of the UNDO
-tablespace qualifies for TRUNCATE (size > threshold).
-@param[in,out] undo_trunc undo truncate tracker */
-static
-void
-trx_purge_mark_undo_for_truncate(
- undo::Truncate* undo_trunc)
-{
- /* Step-1: If UNDO Tablespace
- - already marked for truncate (OR)
- - truncate disabled
- return immediately else search for qualifying tablespace. */
- if (undo_trunc->is_marked() || !srv_undo_log_truncate) {
- return;
- }
-
- /* Step-2: Validation/Qualification checks
- a. At-least 2 UNDO tablespaces so even if one UNDO tablespace
- is being truncated server can continue to operate.
- b. At-least 2 persistent UNDO logs (besides the default rseg-0)
- b. At-least 1 UNDO tablespace size > threshold. */
- if (srv_undo_tablespaces_active < 2 || srv_undo_logs < 3) {
- return;
- }
-
- /* Avoid bias selection and so start the scan from immediate next
- of last selected UNDO tablespace for truncate. */
- ulint space_id = undo_trunc->get_scan_start();
-
- for (ulint i = 1; i <= srv_undo_tablespaces_active; i++) {
-
- if (fil_space_get_size(space_id)
- > (srv_max_undo_log_size >> srv_page_size_shift)) {
- /* Tablespace qualifies for truncate. */
- undo_trunc->mark(space_id);
- undo::Truncate::add_space_to_trunc_list(space_id);
- break;
- }
-
- space_id = ((space_id + 1) % (srv_undo_tablespaces_active + 1));
- if (space_id == 0) {
- /* Note: UNDO tablespace ids starts from 1. */
- ++space_id;
- }
- }
-
- /* Couldn't make any selection. */
- if (!undo_trunc->is_marked()) {
- return;
- }
-
- DBUG_LOG("undo",
- "marking for truncate UNDO tablespace "
- << undo_trunc->get_marked_space_id());
-
- /* Step-3: Iterate over all the rsegs of selected UNDO tablespace
- and mark them temporarily unavailable for allocation.*/
- for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
- if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
- ut_ad(rseg->is_persistent());
- if (rseg->space->id
- == undo_trunc->get_marked_space_id()) {
-
- /* Once set this rseg will not be allocated
- to new booting transaction but we will wait
- for existing active transaction to finish. */
- rseg->skip_allocation = true;
- undo_trunc->add_rseg_to_trunc(rseg);
- }
- }
- }
-}
-
-undo::undo_spaces_t undo::Truncate::s_spaces_to_truncate;
-
/** Cleanse purge queue to remove the rseg that reside in undo-tablespace
marked for truncate.
-@param[in,out] undo_trunc undo truncate tracker */
-static
-void
-trx_purge_cleanse_purge_queue(
- undo::Truncate* undo_trunc)
+@param[in] space undo tablespace being truncated */
+static void trx_purge_cleanse_purge_queue(const fil_space_t& space)
{
- mutex_enter(&purge_sys.pq_mutex);
typedef std::vector<TrxUndoRsegs> purge_elem_list_t;
purge_elem_list_t purge_elem_list;
+ mutex_enter(&purge_sys.pq_mutex);
+
/* Remove rseg instances that are in the purge queue before we start
truncate of corresponding UNDO truncate. */
while (!purge_sys.purge_queue.empty()) {
purge_elem_list.push_back(purge_sys.purge_queue.top());
purge_sys.purge_queue.pop();
}
- ut_ad(purge_sys.purge_queue.empty());
for (purge_elem_list_t::iterator it = purge_elem_list.begin();
it != purge_elem_list.end();
@@ -815,9 +528,7 @@ trx_purge_cleanse_purge_queue(
for (TrxUndoRsegs::iterator it2 = it->begin();
it2 != it->end();
++it2) {
-
- if ((*it2)->space->id
- == undo_trunc->get_marked_space_id()) {
+ if ((*it2)->space == &space) {
it->erase(it2);
break;
}
@@ -827,278 +538,285 @@ trx_purge_cleanse_purge_queue(
purge_sys.purge_queue.push(*it);
}
}
+
mutex_exit(&purge_sys.pq_mutex);
}
-/** Iterate over selected UNDO tablespace and check if all the rsegs
-that resides in the tablespace are free.
-@param[in] limit truncate_limit
-@param[in,out] undo_trunc undo truncate tracker */
-static
-void
-trx_purge_initiate_truncate(
- const purge_sys_t::iterator& limit,
- undo::Truncate* undo_trunc)
+/**
+Removes unnecessary history data from rollback segments. NOTE that when this
+function is called, the caller must not have any latches on undo log pages!
+*/
+static void trx_purge_truncate_history()
{
- /* Step-1: Early check to findout if any of the the UNDO tablespace
- is marked for truncate. */
- if (!undo_trunc->is_marked()) {
- /* No tablespace marked for truncate yet. */
- return;
- }
-
- /* Step-2: Scan over each rseg and ensure that it doesn't hold any
- active undo records. */
- bool all_free = true;
-
- for (ulint i = 0; i < undo_trunc->rsegs_size() && all_free; ++i) {
-
- trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i);
+ ut_ad(purge_sys.head <= purge_sys.tail);
+ purge_sys_t::iterator& head = purge_sys.head.commit
+ ? purge_sys.head : purge_sys.tail;
- mutex_enter(&rseg->mutex);
+ if (head.trx_no() >= purge_sys.view.low_limit_no()) {
+ /* This is sometimes necessary. TODO: find out why. */
+ head.reset_trx_no(purge_sys.view.low_limit_no());
+ head.undo_no = 0;
+ }
- if (rseg->trx_ref_count > 0) {
- /* This rseg is still being held by an active
- transaction. */
- all_free = false;
- mutex_exit(&rseg->mutex);
- continue;
+ for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
+ if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
+ ut_ad(rseg->id == i);
+ trx_purge_truncate_rseg_history(*rseg, head);
}
+ }
- ut_ad(rseg->trx_ref_count == 0);
- ut_ad(rseg->skip_allocation);
-
- ulint size_of_rsegs = rseg->curr_size;
-
- if (size_of_rsegs == 1) {
- mutex_exit(&rseg->mutex);
- continue;
- } else {
-
- /* There could be cached undo segment. Check if records
- in these segments can be purged. Normal purge history
- will not touch these cached segment. */
- ulint cached_undo_size = 0;
+ if (srv_undo_tablespaces_active < 2) {
+ return;
+ }
- for (trx_undo_t* undo =
- UT_LIST_GET_FIRST(rseg->undo_cached);
- undo != NULL && all_free;
- undo = UT_LIST_GET_NEXT(undo_list, undo)) {
+ while (srv_undo_log_truncate && srv_undo_logs >= 3) {
+ if (!purge_sys.truncate.current) {
+ const ulint threshold = ulint(srv_max_undo_log_size
+ >> srv_page_size_shift);
+ for (ulint i = purge_sys.truncate.last
+ ? purge_sys.truncate.last->id
+ - srv_undo_space_id_start
+ : 0, j = i;; ) {
+ ulint space_id = srv_undo_space_id_start + i;
+ ut_ad(srv_is_undo_tablespace(space_id));
+
+ if (fil_space_get_size(space_id)
+ > threshold) {
+ purge_sys.truncate.current
+ = fil_space_get(space_id);
+ break;
+ }
- if (limit.trx_no() < undo->trx_id) {
- all_free = false;
- } else {
- cached_undo_size += undo->size;
+ ++i;
+ i %= srv_undo_tablespaces_active;
+ if (i == j) {
+ break;
}
}
+ }
- ut_ad(size_of_rsegs >= (cached_undo_size + 1));
+ if (!purge_sys.truncate.current) {
+ return;
+ }
- if (size_of_rsegs > (cached_undo_size + 1)) {
- /* There are pages besides cached pages that
- still hold active data. */
- all_free = false;
+ const fil_space_t& space = *purge_sys.truncate.current;
+ /* Undo tablespace always are a single file. */
+ ut_a(UT_LIST_GET_LEN(space.chain) == 1);
+ fil_node_t* file = UT_LIST_GET_FIRST(space.chain);
+ /* The undo tablespace files are never closed. */
+ ut_ad(file->is_open());
+
+ DBUG_LOG("undo", "marking for truncate: " << file->name);
+
+ for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
+ if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
+ ut_ad(rseg->is_persistent());
+ if (rseg->space == &space) {
+ /* Once set, this rseg will
+ not be allocated to subsequent
+ transactions, but we will wait
+ for existing active
+ transactions to finish. */
+ rseg->skip_allocation = true;
+ }
}
}
- mutex_exit(&rseg->mutex);
- }
-
- if (!all_free) {
- /* rseg still holds active data.*/
- return;
- }
-
-
- /* Step-3: Start the actual truncate.
- a. Remove rseg instance if added to purge queue before we
- initiate truncate.
- b. Execute actual truncate */
-
- const ulint space_id = undo_trunc->get_marked_space_id();
-
- ib::info() << "Truncating UNDO tablespace " << space_id;
-
- trx_purge_cleanse_purge_queue(undo_trunc);
-
- ut_a(srv_is_undo_tablespace(space_id));
-
- fil_space_t* space = fil_space_get(space_id);
-
- if (!space) {
-not_found:
- ib::error() << "Failed to find UNDO tablespace " << space_id;
- return;
- }
-
- /* Flush all to-be-discarded pages of the tablespace.
-
- During truncation, we do not want any writes to the
- to-be-discarded area, because we must set the space->size
- early in order to have deterministic page allocation.
-
- If a log checkpoint was completed at LSN earlier than our
- mini-transaction commit and the server was killed, then
- discarding the to-be-trimmed pages without flushing would
- break crash recovery. So, we cannot avoid the write. */
- {
- FlushObserver observer(
- space,
- UT_LIST_GET_FIRST(purge_sys.query->thrs)->graph->trx,
- NULL);
- buf_LRU_flush_or_remove_pages(space_id, &observer);
- }
-
- log_free_check();
+ for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
+ trx_rseg_t* rseg = trx_sys.rseg_array[i];
+ if (!rseg || rseg->space != &space) {
+ continue;
+ }
+ mutex_enter(&rseg->mutex);
+ ut_ad(rseg->skip_allocation);
+ if (rseg->trx_ref_count) {
+not_free:
+ mutex_exit(&rseg->mutex);
+ return;
+ }
- /* Adjust the tablespace metadata. */
- space = fil_truncate_prepare(space_id);
+ if (rseg->curr_size != 1) {
+ /* Check if all segments are
+ cached and safe to remove. */
+ ulint cached = 0;
+
+ for (trx_undo_t* undo = UT_LIST_GET_FIRST(
+ rseg->undo_cached);
+ undo;
+ undo = UT_LIST_GET_NEXT(undo_list,
+ undo)) {
+ if (head.trx_no() < undo->trx_id) {
+ goto not_free;
+ } else {
+ cached += undo->size;
+ }
+ }
- if (!space) {
- goto not_found;
- }
+ ut_ad(rseg->curr_size > cached);
- /* Undo tablespace always are a single file. */
- ut_a(UT_LIST_GET_LEN(space->chain) == 1);
- fil_node_t* file = UT_LIST_GET_FIRST(space->chain);
- /* The undo tablespace files are never closed. */
- ut_ad(file->is_open());
+ if (rseg->curr_size > cached + 1) {
+ goto not_free;
+ }
+ }
- /* Re-initialize tablespace, in a single mini-transaction. */
- mtr_t mtr;
- const ulint size = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
- mtr.start();
- mtr_x_lock_space(space, &mtr);
- fil_truncate_log(space, size, &mtr);
- fsp_header_init(space, size, &mtr);
- mutex_enter(&fil_system.mutex);
- space->size = file->size = size;
- mutex_exit(&fil_system.mutex);
-
- buf_block_t* sys_header = trx_sysf_get(&mtr);
-
- for (ulint i = 0; i < undo_trunc->rsegs_size(); ++i) {
- trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i);
- buf_block_t* rblock = trx_rseg_header_create(
- space, rseg->id, sys_header, &mtr);
- ut_ad(rblock);
- rseg->page_no = rblock ? rblock->page.id.page_no() : FIL_NULL;
-
- /* Before re-initialization ensure that we free the existing
- structure. There can't be any active transactions. */
- ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0);
- ut_a(UT_LIST_GET_LEN(rseg->old_insert_list) == 0);
-
- trx_undo_t* next_undo;
-
- for (trx_undo_t* undo = UT_LIST_GET_FIRST(rseg->undo_cached);
- undo != NULL;
- undo = next_undo) {
-
- next_undo = UT_LIST_GET_NEXT(undo_list, undo);
- UT_LIST_REMOVE(rseg->undo_cached, undo);
- MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_CACHED);
- ut_free(undo);
+ mutex_exit(&rseg->mutex);
}
- UT_LIST_INIT(rseg->undo_list, &trx_undo_t::undo_list);
- UT_LIST_INIT(rseg->undo_cached, &trx_undo_t::undo_list);
- UT_LIST_INIT(rseg->old_insert_list, &trx_undo_t::undo_list);
-
- /* These were written by trx_rseg_header_create(). */
- ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
- + rblock->frame));
- ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE
- + rblock->frame));
-
- /* Initialize the undo log lists according to the rseg header */
- rseg->curr_size = 1;
- rseg->trx_ref_count = 0;
- rseg->last_page_no = FIL_NULL;
- rseg->last_offset = 0;
- rseg->last_commit = 0;
- rseg->needs_purge = false;
- }
+ ib::info() << "Truncating " << file->name;
+ trx_purge_cleanse_purge_queue(space);
+
+ /* Flush all to-be-discarded pages of the tablespace.
+
+ During truncation, we do not want any writes to the
+ to-be-discarded area, because we must set the space.size
+ early in order to have deterministic page allocation.
+
+ If a log checkpoint was completed at LSN earlier than our
+ mini-transaction commit and the server was killed, then
+ discarding the to-be-trimmed pages without flushing would
+ break crash recovery. So, we cannot avoid the write. */
+ {
+ FlushObserver observer(
+ purge_sys.truncate.current,
+ UT_LIST_GET_FIRST(purge_sys.query->thrs)
+ ->graph->trx,
+ NULL);
+ buf_LRU_flush_or_remove_pages(space.id, &observer);
+ }
- mtr.commit();
- /* Write-ahead the redo log record. */
- log_write_up_to(mtr.commit_lsn(), true);
-
- /* Trim the file size. */
- os_file_truncate(file->name, file->handle,
- os_offset_t(size) << srv_page_size_shift, true);
-
- /* This is only executed by the srv_purge_coordinator_thread. */
- export_vars.innodb_undo_truncations++;
-
- /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */
-
- mutex_enter(&fil_system.mutex);
- ut_ad(space->stop_new_ops);
- ut_ad(space->is_being_truncated);
- space->stop_new_ops = false;
- space->is_being_truncated = false;
- mutex_exit(&fil_system.mutex);
-
- if (purge_sys.rseg != NULL
- && purge_sys.rseg->last_page_no == FIL_NULL) {
- /* If purge_sys.rseg is pointing to rseg that was recently
- truncated then move to next rseg element.
- Note: Ideally purge_sys.rseg should be NULL because purge
- should complete processing of all the records but there is
- purge_batch_size that can force the purge loop to exit before
- all the records are purged and in this case purge_sys.rseg
- could point to a valid rseg waiting for next purge cycle. */
- purge_sys.next_stored = false;
- purge_sys.rseg = NULL;
- }
+ log_free_check();
- DBUG_EXECUTE_IF("ib_undo_trunc",
- ib::info() << "ib_undo_trunc";
- log_write_up_to(LSN_MAX, true);
- DBUG_SUICIDE(););
+ /* Adjust the tablespace metadata. */
+ if (!fil_truncate_prepare(space.id)) {
+ ib::error() << "Failed to find UNDO tablespace "
+ << file->name;
+ return;
+ }
- /* Completed truncate. Now it is safe to re-use the tablespace. */
- for (ulint i = 0; i < undo_trunc->rsegs_size(); ++i) {
- trx_rseg_t* rseg = undo_trunc->get_ith_rseg(i);
- rseg->skip_allocation = false;
- }
+ /* Re-initialize tablespace, in a single mini-transaction. */
+ mtr_t mtr;
+ const ulint size = SRV_UNDO_TABLESPACE_SIZE_IN_PAGES;
+ mtr.start();
+ mtr_x_lock_space(purge_sys.truncate.current, &mtr);
+ fil_truncate_log(purge_sys.truncate.current, size, &mtr);
+ fsp_header_init(purge_sys.truncate.current, size, &mtr);
+ mutex_enter(&fil_system.mutex);
+ purge_sys.truncate.current->size = file->size = size;
+ mutex_exit(&fil_system.mutex);
+
+ buf_block_t* sys_header = trx_sysf_get(&mtr);
+
+ for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
+ trx_rseg_t* rseg = trx_sys.rseg_array[i];
+ if (!rseg || rseg->space != &space) {
+ continue;
+ }
- ib::info() << "Truncated UNDO tablespace " << space_id;
+ ut_ad(rseg->is_persistent());
+ ut_d(const ulint old_page = rseg->page_no);
+
+ buf_block_t* rblock = trx_rseg_header_create(
+ purge_sys.truncate.current,
+ rseg->id, sys_header, &mtr);
+ ut_ad(rblock);
+ rseg->page_no = rblock
+ ? rblock->page.id.page_no() : FIL_NULL;
+ ut_ad(old_page == rseg->page_no);
+
+ /* Before re-initialization ensure that we
+ free the existing structure. There can't be
+ any active transactions. */
+ ut_a(UT_LIST_GET_LEN(rseg->undo_list) == 0);
+ ut_a(UT_LIST_GET_LEN(rseg->old_insert_list) == 0);
+
+ trx_undo_t* next_undo;
+
+ for (trx_undo_t* undo = UT_LIST_GET_FIRST(
+ rseg->undo_cached);
+ undo; undo = next_undo) {
+
+ next_undo = UT_LIST_GET_NEXT(undo_list, undo);
+ UT_LIST_REMOVE(rseg->undo_cached, undo);
+ MONITOR_DEC(MONITOR_NUM_UNDO_SLOT_CACHED);
+ ut_free(undo);
+ }
- undo_trunc->reset();
- undo::Truncate::clear_trunc_list();
-}
+ UT_LIST_INIT(rseg->undo_list,
+ &trx_undo_t::undo_list);
+ UT_LIST_INIT(rseg->undo_cached,
+ &trx_undo_t::undo_list);
+ UT_LIST_INIT(rseg->old_insert_list,
+ &trx_undo_t::undo_list);
+
+ /* These were written by trx_rseg_header_create(). */
+ ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_FORMAT
+ + rblock->frame));
+ ut_ad(!mach_read_from_4(TRX_RSEG + TRX_RSEG_HISTORY_SIZE
+ + rblock->frame));
+
+ /* Initialize the undo log lists according to
+ the rseg header */
+ rseg->curr_size = 1;
+ rseg->trx_ref_count = 0;
+ rseg->last_page_no = FIL_NULL;
+ rseg->last_offset = 0;
+ rseg->last_commit = 0;
+ rseg->needs_purge = false;
+ }
-/**
-Removes unnecessary history data from rollback segments. NOTE that when this
-function is called, the caller must not have any latches on undo log pages!
-*/
-static void trx_purge_truncate_history()
-{
- ut_ad(purge_sys.head <= purge_sys.tail);
- purge_sys_t::iterator& head = purge_sys.head.commit
- ? purge_sys.head : purge_sys.tail;
+ mtr.commit();
+ /* Write-ahead the redo log record. */
+ log_write_up_to(mtr.commit_lsn(), true);
+
+ /* Trim the file size. */
+ os_file_truncate(file->name, file->handle,
+ os_offset_t(size) << srv_page_size_shift,
+ true);
+
+ /* This is only executed by srv_purge_coordinator_thread. */
+ export_vars.innodb_undo_truncations++;
+
+ /* TODO: PUNCH_HOLE the garbage (with write-ahead logging) */
+ mutex_enter(&fil_system.mutex);
+ ut_ad(&space == purge_sys.truncate.current);
+ ut_ad(space.stop_new_ops);
+ ut_ad(space.is_being_truncated);
+ purge_sys.truncate.current->stop_new_ops = false;
+ purge_sys.truncate.current->is_being_truncated = false;
+ mutex_exit(&fil_system.mutex);
+
+ if (purge_sys.rseg != NULL
+ && purge_sys.rseg->last_page_no == FIL_NULL) {
+ /* If purge_sys.rseg is pointing to rseg that
+ was recently truncated then move to next rseg
+ element. Note: Ideally purge_sys.rseg should
+ be NULL because purge should complete
+ processing of all the records but there is
+ purge_batch_size that can force the purge loop
+ to exit before all the records are purged and
+ in this case purge_sys.rseg could point to a
+ valid rseg waiting for next purge cycle. */
+ purge_sys.next_stored = false;
+ purge_sys.rseg = NULL;
+ }
- if (head.trx_no() >= purge_sys.view.low_limit_no()) {
- /* This is sometimes necessary. TODO: find out why. */
- head.reset_trx_no(purge_sys.view.low_limit_no());
- head.undo_no = 0;
- }
+ DBUG_EXECUTE_IF("ib_undo_trunc",
+ ib::info() << "ib_undo_trunc";
+ log_write_up_to(LSN_MAX, true);
+ DBUG_SUICIDE(););
- for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
- if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
- ut_ad(rseg->id == i);
- trx_purge_truncate_rseg_history(*rseg, head);
+ for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
+ if (trx_rseg_t* rseg = trx_sys.rseg_array[i]) {
+ ut_ad(rseg->is_persistent());
+ if (rseg->space == &space) {
+ rseg->skip_allocation = false;
+ }
+ }
}
- }
- /* UNDO tablespace truncate. We will try to truncate as much as we
- can (greedy approach). This will ensure when the server is idle we
- try and truncate all the UNDO tablespaces. */
- for (ulint i = srv_undo_tablespaces_active; i--; ) {
- trx_purge_mark_undo_for_truncate(&purge_sys.undo_trunc);
- trx_purge_initiate_truncate(head, &purge_sys.undo_trunc);
+ ib::info() << "Truncated " << file->name;
+ purge_sys.truncate.last = purge_sys.truncate.current;
+ purge_sys.truncate.current = NULL;
}
}
@@ -1512,7 +1230,7 @@ trx_purge_dml_delay(void)
if (srv_max_purge_lag > 0) {
float ratio;
- ratio = float(trx_sys.history_size()) / srv_max_purge_lag;
+ ratio = float(trx_sys.rseg_history_len) / srv_max_purge_lag;
if (ratio > 1.0) {
/* If the history list length exceeds the
@@ -1538,8 +1256,7 @@ void
trx_purge_wait_for_workers_to_complete()
{
/* Ensure that the work queue empties out. */
- while (my_atomic_loadlint(&purge_sys.n_completed)
- != purge_sys.n_submitted) {
+ while (purge_sys.n_tasks.load(std::memory_order_acquire)) {
if (srv_get_task_queue_length() > 0) {
srv_release_threads(SRV_WORKER, 1);
@@ -1575,9 +1292,8 @@ trx_purge(
srv_dml_needed_delay = trx_purge_dml_delay();
- /* The number of tasks submitted should be completed. */
- ut_a(purge_sys.n_submitted
- == my_atomic_loadlint(&purge_sys.n_completed));
+ /* All submitted tasks should be completed. */
+ ut_ad(purge_sys.n_tasks.load(std::memory_order_relaxed) == 0);
rw_lock_x_lock(&purge_sys.latch);
trx_sys.clone_oldest_view();
@@ -1591,7 +1307,7 @@ trx_purge(
/* Fetch the UNDO recs that need to be purged. */
n_pages_handled = trx_purge_attach_undo_recs(n_purge_threads);
- purge_sys.n_submitted += n_purge_threads;
+ purge_sys.n_tasks.store(n_purge_threads - 1, std::memory_order_relaxed);
/* Submit tasks to workers queue if using multi-threaded purge. */
for (ulint i = n_purge_threads; --i; ) {
@@ -1605,14 +1321,9 @@ trx_purge(
ut_d(thr->thread_slot = slot);
que_run_threads(thr);
- my_atomic_addlint(&purge_sys.n_completed, 1);
-
- if (n_purge_threads > 1) {
- trx_purge_wait_for_workers_to_complete();
- }
+ trx_purge_wait_for_workers_to_complete();
- ut_a(purge_sys.n_submitted
- == my_atomic_loadlint(&purge_sys.n_completed));
+ ut_ad(purge_sys.n_tasks.load(std::memory_order_relaxed) == 0);
if (truncate) {
trx_purge_truncate_history();
@@ -1629,7 +1340,7 @@ void purge_sys_t::stop()
{
rw_lock_x_lock(&latch);
- if (!enabled_latched())
+ if (!enabled())
{
/* Shutdown must have been initiated during FLUSH TABLES FOR EXPORT. */
ut_ad(!srv_undo_sources);
@@ -1639,7 +1350,7 @@ void purge_sys_t::stop()
ut_ad(srv_n_purge_threads > 0);
- if (0 == my_atomic_add32_explicit(&m_paused, 1, MY_MEMORY_ORDER_RELAXED))
+ if (m_paused++ == 0)
{
/* We need to wakeup the purge thread in case it is suspended, so
that it can acknowledge the state change. */
@@ -1673,8 +1384,7 @@ void purge_sys_t::resume()
return;
}
- int32_t paused= my_atomic_add32_explicit(&m_paused, -1,
- MY_MEMORY_ORDER_RELAXED);
+ int32_t paused= m_paused--;
ut_a(paused);
if (paused == 1)
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index 242ac46c720..e612a9f577b 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -39,9 +39,11 @@ Created 3/26/1996 Heikki Tuuri
#include "row0row.h"
#include "row0mysql.h"
-/** The search tuple corresponding to TRX_UNDO_INSERT_METADATA */
+/** The search tuple corresponding to TRX_UNDO_INSERT_METADATA. */
const dtuple_t trx_undo_metadata = {
- REC_INFO_METADATA, 0, 0,
+ /* This also works for REC_INFO_METADATA_ALTER, because the
+ delete-mark (REC_INFO_DELETED_FLAG) is ignored when searching. */
+ REC_INFO_METADATA_ADD, 0, 0,
NULL, 0, NULL
#ifdef UNIV_DEBUG
, DATA_TUPLE_MAGIC_N
@@ -228,8 +230,7 @@ trx_undo_log_v_idx(
{
ut_ad(pos < table->n_v_def);
dict_v_col_t* vcol = dict_table_get_nth_v_col(table, pos);
-
- ulint n_idx = vcol->v_indexes->size();
+ ulint n_idx = vcol->n_v_indexes;
byte* old_ptr;
ut_ad(n_idx > 0);
@@ -256,12 +257,7 @@ trx_undo_log_v_idx(
ptr += mach_write_compressed(ptr, n_idx);
- dict_v_idx_list::iterator it;
-
- for (it = vcol->v_indexes->begin();
- it != vcol->v_indexes->end(); ++it) {
- dict_v_idx_t v_index = *it;
-
+ for (const auto& v_index : vcol->v_indexes) {
ptr += mach_write_compressed(
ptr, static_cast<ulint>(v_index.index->id));
@@ -503,7 +499,7 @@ trx_undo_page_report_insert(
/* Store then the fields required to uniquely determine the record
to be inserted in the clustered index */
if (UNIV_UNLIKELY(clust_entry->info_bits != 0)) {
- ut_ad(clust_entry->info_bits == REC_INFO_METADATA);
+ ut_ad(clust_entry->is_metadata());
ut_ad(index->is_instant());
ut_ad(undo_block->frame[first_free + 2]
== TRX_UNDO_INSERT_REC);
@@ -716,7 +712,7 @@ trx_undo_rec_skip_row_ref(
log of an update or delete marking of a clustered index record.
@param[out] ext_buf buffer to hold the prefix data and BLOB pointer
@param[in] prefix_len prefix size to store in the undo log
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] field an externally stored column
@param[in,out] len input: length of field; output: used length of
ext_buf
@@ -726,13 +722,13 @@ byte*
trx_undo_page_fetch_ext(
byte* ext_buf,
ulint prefix_len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte* field,
ulint* len)
{
/* Fetch the BLOB. */
ulint ext_len = btr_copy_externally_stored_field_prefix(
- ext_buf, prefix_len, page_size, field, *len);
+ ext_buf, prefix_len, zip_size, field, *len);
/* BLOBs should always be nonempty. */
ut_a(ext_len);
/* Append the BLOB pointer to the prefix. */
@@ -750,7 +746,7 @@ available
size, or NULL when should not fetch a longer
prefix
@param[in] prefix_len prefix size to store in the undo log
-@param[in] page_size page size
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in,out] field the locally stored part of the externally
stored column
@param[in,out] len length of field, in bytes
@@ -763,7 +759,7 @@ trx_undo_page_report_modify_ext(
byte* ptr,
byte* ext_buf,
ulint prefix_len,
- const page_size_t& page_size,
+ ulint zip_size,
const byte** field,
ulint* len,
spatial_status_t spatial_status)
@@ -805,7 +801,7 @@ trx_undo_page_report_modify_ext(
ptr += mach_write_compressed(ptr, *len);
*field = trx_undo_page_fetch_ext(ext_buf, prefix_len,
- page_size, *field, len);
+ zip_size, *field, len);
ptr += mach_write_compressed(ptr, *len + spatial_len);
} else {
@@ -818,7 +814,7 @@ trx_undo_page_report_modify_ext(
/** Get MBR from a Geometry column stored externally
@param[out] mbr MBR to fill
-@param[in] pagesize table pagesize
+@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param[in] field field contain the geometry data
@param[in,out] len length of field, in bytes
*/
@@ -826,17 +822,17 @@ static
void
trx_undo_get_mbr_from_ext(
/*======================*/
- double* mbr,
- const page_size_t& page_size,
- const byte* field,
- ulint* len)
+ double* mbr,
+ ulint zip_size,
+ const byte* field,
+ ulint* len)
{
uchar* dptr = NULL;
ulint dlen;
mem_heap_t* heap = mem_heap_create(100);
dptr = btr_copy_externally_stored_field(
- &dlen, field, page_size, *len, heap);
+ &dlen, field, zip_size, *len, heap);
if (dlen <= GEO_DATA_HEADER_SIZE) {
for (uint i = 0; i < SPDIMS; ++i) {
@@ -920,9 +916,9 @@ trx_undo_page_report_modify(
/* Store first some general parameters to the undo log */
if (!update) {
- ut_ad(!rec_get_deleted_flag(rec, dict_table_is_comp(table)));
+ ut_ad(!rec_is_delete_marked(rec, dict_table_is_comp(table)));
type_cmpl = TRX_UNDO_DEL_MARK_REC;
- } else if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) {
+ } else if (rec_is_delete_marked(rec, dict_table_is_comp(table))) {
/* In delete-marked records, DB_TRX_ID must
always refer to an existing update_undo log record. */
ut_ad(row_get_rec_trx_id(rec, index, offsets));
@@ -951,9 +947,7 @@ trx_undo_page_report_modify(
*ptr++ = (byte) rec_get_info_bits(rec, dict_table_is_comp(table));
/* Store the values of the system columns */
- field = rec_get_nth_field(rec, offsets,
- dict_index_get_sys_col_pos(
- index, DATA_TRX_ID), &flen);
+ field = rec_get_nth_field(rec, offsets, index->db_trx_id(), &flen);
ut_ad(flen == DATA_TRX_ID_LEN);
trx_id = trx_read_trx_id(field);
@@ -967,9 +961,7 @@ trx_undo_page_report_modify(
}
ptr += mach_u64_write_compressed(ptr, trx_id);
- field = rec_get_nth_field(rec, offsets,
- dict_index_get_sys_col_pos(
- index, DATA_ROLL_PTR), &flen);
+ field = rec_get_nth_field(rec, offsets, index->db_roll_ptr(), &flen);
ut_ad(flen == DATA_ROLL_PTR_LEN);
ut_ad(memcmp(field, field_ref_zero, DATA_ROLL_PTR_LEN));
@@ -1030,45 +1022,60 @@ trx_undo_page_report_modify(
on them */
if (upd_fld_is_virtual_col(fld)
&& dict_table_get_nth_v_col(
- table, pos)->v_indexes->empty()) {
+ table, pos)->v_indexes.empty()) {
n_updated--;
}
}
}
+ i = 0;
+
+ if (UNIV_UNLIKELY(update->is_alter_metadata())) {
+ ut_ad(update->n_fields >= 1);
+ ut_ad(!upd_fld_is_virtual_col(&update->fields[0]));
+ ut_ad(update->fields[0].field_no
+ == index->first_user_field());
+ ut_ad(!dfield_is_ext(&update->fields[0].new_val));
+ ut_ad(!dfield_is_null(&update->fields[0].new_val));
+ /* The instant ADD COLUMN metadata record does not
+ contain the BLOB. Do not write anything for it. */
+ i = !rec_is_alter_metadata(rec, *index);
+ n_updated -= i;
+ }
+
ptr += mach_write_compressed(ptr, n_updated);
- for (i = 0; i < upd_get_n_fields(update); i++) {
+ for (; i < upd_get_n_fields(update); i++) {
+ if (trx_undo_left(undo_block, ptr) < 5) {
+ return 0;
+ }
+
upd_field_t* fld = upd_get_nth_field(update, i);
bool is_virtual = upd_fld_is_virtual_col(fld);
ulint max_v_log_len = 0;
- ulint pos = fld->field_no;
-
- /* Write field number to undo log */
- if (trx_undo_left(undo_block, ptr) < 5) {
- return(0);
- }
+ ulint pos = fld->field_no;
+ const dict_col_t* col = NULL;
if (is_virtual) {
/* Skip the non-indexed column, during
an online alter table */
if (dict_index_is_online_ddl(index)
&& dict_table_get_nth_v_col(
- table, pos)->v_indexes->empty()) {
+ table, pos)->v_indexes.empty()) {
continue;
}
/* add REC_MAX_N_FIELDS to mark this
is a virtual col */
- pos += REC_MAX_N_FIELDS;
- }
+ ptr += mach_write_compressed(
+ ptr, pos + REC_MAX_N_FIELDS);
- ptr += mach_write_compressed(ptr, pos);
+ if (trx_undo_left(undo_block, ptr) < 15) {
+ return 0;
+ }
- /* Save the old value of field */
- if (is_virtual) {
ut_ad(fld->field_no < table->n_v_def);
ptr = trx_undo_log_v_idx(undo_block, table,
@@ -1093,36 +1100,87 @@ trx_undo_page_report_modify(
flen = ut_min(
flen, max_v_log_len);
}
+
+ goto store_len;
+ }
+
+ if (UNIV_UNLIKELY(update->is_metadata())) {
+ ut_ad(pos >= index->first_user_field());
+ ut_ad(rec_is_metadata(rec, *index));
+
+ if (rec_is_alter_metadata(rec, *index)) {
+ ut_ad(update->is_alter_metadata());
+
+ field = rec_offs_n_fields(offsets)
+ > pos
+ && !rec_offs_nth_default(
+ offsets, pos)
+ ? rec_get_nth_field(
+ rec, offsets,
+ pos, &flen)
+ : index->instant_field_value(
+ pos - 1, &flen);
+
+ if (pos == index->first_user_field()) {
+ ut_ad(rec_offs_nth_extern(
+ offsets, pos));
+ ut_ad(flen == FIELD_REF_SIZE);
+ goto write_field;
+ }
+ col = dict_index_get_nth_col(index,
+ pos - 1);
+ } else if (!update->is_alter_metadata()) {
+ goto get_field;
+ } else {
+ /* We are converting an ADD COLUMN
+ metadata record to an ALTER TABLE
+ metadata record, with BLOB. Subtract
+ the missing metadata BLOB field. */
+ ut_ad(pos > index->first_user_field());
+ --pos;
+ goto get_field;
+ }
} else {
+get_field:
+ col = dict_index_get_nth_col(index, pos);
field = rec_get_nth_cfield(
rec, index, offsets, pos, &flen);
}
+write_field:
+ /* Write field number to undo log */
+ ptr += mach_write_compressed(ptr, pos);
if (trx_undo_left(undo_block, ptr) < 15) {
- return(0);
+ return 0;
}
- if (!is_virtual && rec_offs_nth_extern(offsets, pos)) {
- const dict_col_t* col
- = dict_index_get_nth_col(index, pos);
- ulint prefix_len
- = dict_max_field_len_store_undo(
- table, col);
+ if (rec_offs_n_fields(offsets) > pos
+ && rec_offs_nth_extern(offsets, pos)) {
+ ut_ad(col || pos == index->first_user_field());
+ ut_ad(col || update->is_alter_metadata());
+ ut_ad(col
+ || rec_is_alter_metadata(rec, *index));
+ ulint prefix_len = col
+ ? dict_max_field_len_store_undo(
+ table, col)
+ : 0;
ut_ad(prefix_len + BTR_EXTERN_FIELD_REF_SIZE
<= sizeof ext_buf);
ptr = trx_undo_page_report_modify_ext(
ptr,
- col->ord_part
+ col
+ && col->ord_part
&& !ignore_prefix
&& flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
? ext_buf : NULL, prefix_len,
- dict_table_page_size(table),
+ table->space->zip_size(),
&field, &flen, SPATIAL_UNKNOWN);
*type_cmpl_ptr |= TRX_UNDO_UPD_EXTERN;
} else {
+store_len:
ptr += mach_write_compressed(ptr, flen);
}
@@ -1271,6 +1329,8 @@ trx_undo_page_report_modify(
table, col);
ut_a(prefix_len < sizeof ext_buf);
+ const ulint zip_size
+ = table->space->zip_size();
/* If there is a spatial index on it,
log its MBR */
@@ -1279,9 +1339,7 @@ trx_undo_page_report_modify(
col->mtype));
trx_undo_get_mbr_from_ext(
- mbr,
- dict_table_page_size(
- table),
+ mbr, zip_size,
field, &flen);
}
@@ -1290,7 +1348,7 @@ trx_undo_page_report_modify(
flen < REC_ANTELOPE_MAX_INDEX_COL_LEN
&& !ignore_prefix
? ext_buf : NULL, prefix_len,
- dict_table_page_size(table),
+ zip_size,
&field, &flen,
spatial_status);
} else {
@@ -1487,7 +1545,6 @@ trx_undo_update_rec_get_update(
upd_t* update;
ulint n_fields;
byte* buf;
- ulint i;
bool first_v_col = true;
bool is_undo_log = true;
ulint n_skip_field = 0;
@@ -1500,7 +1557,7 @@ trx_undo_update_rec_get_update(
n_fields = 0;
}
- update = upd_create(n_fields + 2, heap);
+ *upd = update = upd_create(n_fields + 2, heap);
update->info_bits = info_bits;
@@ -1512,9 +1569,7 @@ trx_undo_update_rec_get_update(
mach_write_to_6(buf, trx_id);
- upd_field_set_field_no(upd_field,
- dict_index_get_sys_col_pos(index, DATA_TRX_ID),
- index);
+ upd_field_set_field_no(upd_field, index->db_trx_id(), index);
dfield_set_data(&(upd_field->new_val), buf, DATA_TRX_ID_LEN);
upd_field = upd_get_nth_field(update, n_fields + 1);
@@ -1523,25 +1578,20 @@ trx_undo_update_rec_get_update(
trx_write_roll_ptr(buf, roll_ptr);
- upd_field_set_field_no(
- upd_field, dict_index_get_sys_col_pos(index, DATA_ROLL_PTR),
- index);
+ upd_field_set_field_no(upd_field, index->db_roll_ptr(), index);
dfield_set_data(&(upd_field->new_val), buf, DATA_ROLL_PTR_LEN);
/* Store then the updated ordinary columns to the update vector */
- for (i = 0; i < n_fields; i++) {
-
+ for (ulint i = 0; i < n_fields; i++) {
const byte* field;
ulint len;
- ulint field_no;
ulint orig_len;
- bool is_virtual;
upd_field = upd_get_nth_field(update, i);
- field_no = mach_read_next_compressed(&ptr);
+ ulint field_no = mach_read_next_compressed(&ptr);
- is_virtual = (field_no >= REC_MAX_N_FIELDS);
+ const bool is_virtual = (field_no >= REC_MAX_N_FIELDS);
if (is_virtual) {
/* If new version, we need to check index list to figure
@@ -1564,15 +1614,63 @@ trx_undo_update_rec_get_update(
}
upd_field_set_v_field_no(upd_field, field_no, index);
+ } else if (UNIV_UNLIKELY((update->info_bits
+ & ~REC_INFO_DELETED_FLAG)
+ == REC_INFO_MIN_REC_FLAG)) {
+ ut_ad(type == TRX_UNDO_UPD_EXIST_REC);
+ const ulint uf = index->first_user_field();
+ ut_ad(field_no >= uf);
+
+ if (update->info_bits != REC_INFO_MIN_REC_FLAG) {
+ /* Generic instant ALTER TABLE */
+ if (field_no == uf) {
+ upd_field->new_val.type
+ .metadata_blob_init();
+ } else if (field_no >= index->n_fields) {
+ /* This is reachable during
+ purge if the table was emptied
+ and converted to the canonical
+ format on a later ALTER TABLE.
+ In this case,
+ row_purge_upd_exist_or_extern()
+ would only be interested in
+ freeing any BLOBs that were
+ updated, that is, the metadata
+ BLOB above. Other BLOBs in
+ the metadata record are never
+ updated; they are for the
+ initial DEFAULT values of the
+ instantly added columns, and
+ they will never change.
+
+ Note: if the table becomes
+ empty during ROLLBACK or is
+ empty during subsequent ALTER
+ TABLE, and btr_page_empty() is
+ called to re-create the root
+ page without the metadata
+ record, in that case we should
+ only free the latest version
+ of BLOBs in the record,
+ which purge would never touch. */
+ field_no = REC_MAX_N_FIELDS;
+ n_skip_field++;
+ } else {
+ dict_col_copy_type(
+ dict_index_get_nth_col(
+ index, field_no - 1),
+ &upd_field->new_val.type);
+ }
+ } else {
+ /* Instant ADD COLUMN...LAST */
+ dict_col_copy_type(
+ dict_index_get_nth_col(index,
+ field_no),
+ &upd_field->new_val.type);
+ }
+ upd_field->field_no = field_no;
} else if (field_no < index->n_fields) {
upd_field_set_field_no(upd_field, field_no, index);
- } else if (update->info_bits == REC_INFO_MIN_REC_FLAG
- && index->is_instant()) {
- /* This must be a rollback of a subsequent
- instant ADD COLUMN operation. This will be
- detected and handled by btr_cur_trim(). */
- upd_field->field_no = field_no;
- upd_field->orig_len = 0;
} else {
ib::error() << "Trying to access update undo rec"
" field " << field_no
@@ -1605,6 +1703,12 @@ trx_undo_update_rec_get_update(
dfield_set_ext(&upd_field->new_val);
}
+ ut_ad(update->info_bits != (REC_INFO_DELETED_FLAG
+ | REC_INFO_MIN_REC_FLAG)
+ || field_no != index->first_user_field()
+ || (upd_field->new_val.ext
+ && upd_field->new_val.len == FIELD_REF_SIZE));
+
if (is_virtual) {
upd_field->old_v_val = static_cast<dfield_t*>(
mem_heap_alloc(
@@ -1622,31 +1726,23 @@ trx_undo_update_rec_get_update(
}
}
- /* In rare scenario, we could have skipped virtual column (as they
- are dropped. We will regenerate a update vector and skip them */
- if (n_skip_field > 0) {
- ulint n = 0;
- ut_ad(n_skip_field <= n_fields);
+ /* We may have to skip dropped indexed virtual columns.
+ Also, we may have to trim the update vector of a metadata record
+ if dict_index_t::clear_instant_alter() was invoked on the table
+ later, and the number of fields no longer matches. */
- upd_t* new_update = upd_create(
- n_fields + 2 - n_skip_field, heap);
+ if (n_skip_field) {
+ upd_field_t* d = upd_get_nth_field(update, 0);
+ const upd_field_t* const end = d + n_fields + 2;
- for (i = 0; i < n_fields + 2; i++) {
- upd_field = upd_get_nth_field(update, i);
-
- if (upd_field->field_no == REC_MAX_N_FIELDS) {
- continue;
+ for (const upd_field_t* s = d; s != end; s++) {
+ if (s->field_no != REC_MAX_N_FIELDS) {
+ *d++ = *s;
}
-
- upd_field_t* new_upd_field
- = upd_get_nth_field(new_update, n);
- *new_upd_field = *upd_field;
- n++;
}
- ut_ad(n == n_fields + 2 - n_skip_field);
- *upd = new_update;
- } else {
- *upd = update;
+
+ ut_ad(d + n_skip_field == end);
+ update->n_fields = d - upd_get_nth_field(update, 0);
}
return(const_cast<byte*>(ptr));
@@ -1701,8 +1797,11 @@ trx_undo_rec_get_partial_row(
if (uf->old_v_val) {
continue;
}
- ulint c = dict_index_get_nth_col(index, uf->field_no)->ind;
- *dtuple_get_nth_field(*row, c) = uf->new_val;
+ const dict_col_t& c = *dict_index_get_nth_col(index,
+ uf->field_no);
+ if (!c.is_dropped()) {
+ *dtuple_get_nth_field(*row, c.ind) = uf->new_val;
+ }
}
end_ptr = ptr + mach_read_from_2(ptr);
@@ -1713,7 +1812,6 @@ trx_undo_rec_get_partial_row(
const byte* field;
ulint field_no;
const dict_col_t* col;
- ulint col_no;
ulint len;
ulint orig_len;
bool is_virtual;
@@ -1741,15 +1839,18 @@ trx_undo_rec_get_partial_row(
dict_v_col_t* vcol = dict_table_get_nth_v_col(
index->table, field_no);
col = &vcol->m_col;
- col_no = dict_col_get_no(col);
dfield = dtuple_get_nth_v_field(*row, vcol->v_pos);
dict_col_copy_type(
&vcol->m_col,
dfield_get_type(dfield));
} else {
col = dict_index_get_nth_col(index, field_no);
- col_no = dict_col_get_no(col);
- dfield = dtuple_get_nth_field(*row, col_no);
+
+ if (col->is_dropped()) {
+ continue;
+ }
+
+ dfield = dtuple_get_nth_field(*row, col->ind);
ut_ad(dfield->type.mtype == DATA_MISSING
|| dict_col_type_assert_equal(col,
&dfield->type));
@@ -1757,9 +1858,7 @@ trx_undo_rec_get_partial_row(
|| dfield->len == len
|| (len != UNIV_SQL_NULL
&& len >= UNIV_EXTERN_STORAGE_FIELD));
- dict_col_copy_type(
- dict_table_get_nth_col(index->table, col_no),
- dfield_get_type(dfield));
+ dict_col_copy_type(col, dfield_get_type(dfield));
}
dfield_set_data(dfield, field, len);
@@ -2381,7 +2480,8 @@ trx_undo_prev_version_build(
row_upd_index_replace_new_col_vals(entry, index, update, heap);
/* Get number of externally stored columns in updated record */
- const ulint n_ext = dtuple_get_n_ext(entry);
+ const ulint n_ext = index->is_primary()
+ ? dtuple_get_n_ext(entry) : 0;
buf = static_cast<byte*>(mem_heap_alloc(
heap, rec_get_converted_size(index, entry, n_ext)));
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index a52724444ec..73ac60c635e 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -44,10 +44,6 @@ Created 3/26/1996 Heikki Tuuri
#include "trx0trx.h"
#include "trx0undo.h"
-/** This many pages must be undone before a truncate is tried within
-rollback */
-static const ulint TRX_ROLL_TRUNC_THRESHOLD = 1;
-
/** true if trx_rollback_all_recovered() thread is active */
bool trx_rollback_is_active;
@@ -181,6 +177,12 @@ trx_rollback_to_savepoint(
partial rollback requested, or NULL for
complete rollback */
{
+#ifdef WITH_WSREP
+ if (savept == NULL && wsrep_on(trx->mysql_thd)
+ && wsrep_thd_is_SR(trx->mysql_thd)) {
+ wsrep_handle_SR_rollback(NULL, trx->mysql_thd);
+ }
+#endif /* WITH_WSREP */
ut_ad(!trx_mutex_own(trx));
trx_start_if_not_started_xa(trx, true);
@@ -451,12 +453,8 @@ trx_rollback_to_savepoint_for_mysql_low(
trx_mark_sql_stat_end(trx);
trx->op_info = "";
-
#ifdef WITH_WSREP
- if (wsrep_on(trx->mysql_thd) &&
- trx->lock.was_chosen_as_deadlock_victim) {
- trx->lock.was_chosen_as_deadlock_victim = FALSE;
- }
+ trx->lock.was_chosen_as_wsrep_victim = FALSE;
#endif
return(err);
}
@@ -730,9 +728,9 @@ static my_bool trx_roll_count_callback(rw_trx_hash_element_t *element,
void trx_roll_report_progress()
{
time_t now = time(NULL);
- mutex_enter(&recv_sys->mutex);
- bool report = recv_sys->report(now);
- mutex_exit(&recv_sys->mutex);
+ mutex_enter(&recv_sys.mutex);
+ bool report = recv_sys.report(now);
+ mutex_exit(&recv_sys.mutex);
if (report) {
trx_roll_count_callback_arg arg;
@@ -891,175 +889,6 @@ DECLARE_THREAD(trx_rollback_all_recovered)(void*)
OS_THREAD_DUMMY_RETURN;
}
-/** Try to truncate the undo logs.
-@param[in,out] trx transaction */
-static
-void
-trx_roll_try_truncate(trx_t* trx)
-{
- trx->pages_undone = 0;
-
- undo_no_t undo_no = trx->undo_no;
-
- if (trx_undo_t* undo = trx->rsegs.m_redo.undo) {
- ut_ad(undo->rseg == trx->rsegs.m_redo.rseg);
- mutex_enter(&undo->rseg->mutex);
- trx_undo_truncate_end(undo, undo_no, false);
- mutex_exit(&undo->rseg->mutex);
- }
-
- if (trx_undo_t* undo = trx->rsegs.m_noredo.undo) {
- ut_ad(undo->rseg == trx->rsegs.m_noredo.rseg);
- mutex_enter(&undo->rseg->mutex);
- trx_undo_truncate_end(undo, undo_no, true);
- mutex_exit(&undo->rseg->mutex);
- }
-
-#ifdef WITH_WSREP_OUT
- if (wsrep_on(trx->mysql_thd)) {
- trx->lock.was_chosen_as_deadlock_victim = FALSE;
- }
-#endif /* WITH_WSREP */
-}
-
-/***********************************************************************//**
-Pops the topmost undo log record in a single undo log and updates the info
-about the topmost record in the undo log memory struct.
-@return undo log record, the page s-latched */
-static
-trx_undo_rec_t*
-trx_roll_pop_top_rec(
-/*=================*/
- trx_t* trx, /*!< in: transaction */
- trx_undo_t* undo, /*!< in: undo log */
- mtr_t* mtr) /*!< in: mtr */
-{
- page_t* undo_page = trx_undo_page_get_s_latched(
- page_id_t(undo->rseg->space->id, undo->top_page_no), mtr);
-
- ulint offset = undo->top_offset;
-
- trx_undo_rec_t* prev_rec = trx_undo_get_prev_rec(
- undo_page + offset, undo->hdr_page_no, undo->hdr_offset,
- true, mtr);
-
- if (prev_rec == NULL) {
- undo->top_undo_no = IB_ID_MAX;
- ut_ad(undo->empty());
- } else {
- page_t* prev_rec_page = page_align(prev_rec);
-
- if (prev_rec_page != undo_page) {
-
- trx->pages_undone++;
- }
-
- undo->top_page_no = page_get_page_no(prev_rec_page);
- undo->top_offset = ulint(prev_rec - prev_rec_page);
- undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);
- ut_ad(!undo->empty());
- }
-
- return(undo_page + offset);
-}
-
-/** Get the last undo log record of a transaction (for rollback).
-@param[in,out] trx transaction
-@param[out] roll_ptr DB_ROLL_PTR to the undo record
-@param[in,out] heap memory heap for allocation
-@return undo log record copied to heap
-@retval NULL if none left or the roll_limit (savepoint) was reached */
-trx_undo_rec_t*
-trx_roll_pop_top_rec_of_trx(trx_t* trx, roll_ptr_t* roll_ptr, mem_heap_t* heap)
-{
- if (trx->pages_undone >= TRX_ROLL_TRUNC_THRESHOLD) {
- trx_roll_try_truncate(trx);
- }
-
- trx_undo_t* undo = NULL;
- trx_undo_t* insert = trx->rsegs.m_redo.old_insert;
- trx_undo_t* update = trx->rsegs.m_redo.undo;
- trx_undo_t* temp = trx->rsegs.m_noredo.undo;
- const undo_no_t limit = trx->roll_limit;
-
- ut_ad(!insert || !update || insert->empty() || update->empty()
- || insert->top_undo_no != update->top_undo_no);
- ut_ad(!insert || !temp || insert->empty() || temp->empty()
- || insert->top_undo_no != temp->top_undo_no);
- ut_ad(!update || !temp || update->empty() || temp->empty()
- || update->top_undo_no != temp->top_undo_no);
-
- if (UNIV_LIKELY_NULL(insert)
- && !insert->empty() && limit <= insert->top_undo_no) {
- undo = insert;
- }
-
- if (update && !update->empty() && update->top_undo_no >= limit) {
- if (!undo) {
- undo = update;
- } else if (undo->top_undo_no < update->top_undo_no) {
- undo = update;
- }
- }
-
- if (temp && !temp->empty() && temp->top_undo_no >= limit) {
- if (!undo) {
- undo = temp;
- } else if (undo->top_undo_no < temp->top_undo_no) {
- undo = temp;
- }
- }
-
- if (undo == NULL) {
- trx_roll_try_truncate(trx);
- /* Mark any ROLLBACK TO SAVEPOINT completed, so that
- if the transaction object is committed and reused
- later, we will default to a full ROLLBACK. */
- trx->roll_limit = 0;
- trx->in_rollback = false;
- return(NULL);
- }
-
- ut_ad(!undo->empty());
- ut_ad(limit <= undo->top_undo_no);
-
- *roll_ptr = trx_undo_build_roll_ptr(
- false, undo->rseg->id, undo->top_page_no, undo->top_offset);
-
- mtr_t mtr;
- mtr.start();
-
- trx_undo_rec_t* undo_rec = trx_roll_pop_top_rec(trx, undo, &mtr);
- const undo_no_t undo_no = trx_undo_rec_get_undo_no(undo_rec);
- switch (trx_undo_rec_get_type(undo_rec)) {
- case TRX_UNDO_INSERT_METADATA:
- /* This record type was introduced in MDEV-11369
- instant ADD COLUMN, which was implemented after
- MDEV-12288 removed the insert_undo log. There is no
- instant ADD COLUMN for temporary tables. Therefore,
- this record can only be present in the main undo log. */
- ut_ad(undo == update);
- /* fall through */
- case TRX_UNDO_RENAME_TABLE:
- ut_ad(undo == insert || undo == update);
- /* fall through */
- case TRX_UNDO_INSERT_REC:
- ut_ad(undo == insert || undo == update || undo == temp);
- *roll_ptr |= 1ULL << ROLL_PTR_INSERT_FLAG_POS;
- break;
- default:
- ut_ad(undo == update || undo == temp);
- break;
- }
-
- trx->undo_no = undo_no;
-
- trx_undo_rec_t* undo_rec_copy = trx_undo_rec_copy(undo_rec, heap);
- mtr.commit();
-
- return(undo_rec_copy);
-}
-
/****************************************************************//**
Builds an undo 'query' graph for a transaction. The actual rollback is
performed by executing this query graph like a query subprocedure call.
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 46fb2680371..29e6acc773c 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -53,6 +53,10 @@ trx_rseg_write_wsrep_checkpoint(
const XID* xid,
mtr_t* mtr)
{
+ DBUG_ASSERT(xid->gtrid_length >= 0);
+ DBUG_ASSERT(xid->bqual_length >= 0);
+ DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE);
+
mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header,
uint32_t(xid->formatID),
MLOG_4BYTES, mtr);
@@ -65,9 +69,15 @@ trx_rseg_write_wsrep_checkpoint(
uint32_t(xid->bqual_length),
MLOG_4BYTES, mtr);
+ const ulint xid_length = static_cast<ulint>(xid->gtrid_length
+ + xid->bqual_length);
mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header,
reinterpret_cast<const byte*>(xid->data),
- XIDDATASIZE, mtr);
+ xid_length, mtr);
+ if (UNIV_LIKELY(xid_length < XIDDATASIZE)) {
+ mlog_memset(TRX_RSEG_WSREP_XID_DATA + rseg_header + xid_length,
+ XIDDATASIZE - xid_length, 0, mtr);
+ }
}
/** Update the WSREP XID information in rollback segment header.
@@ -106,8 +116,9 @@ trx_rseg_clear_wsrep_checkpoint(
trx_rsegf_t* rseg_header,
mtr_t* mtr)
{
- mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header,
- 0, MLOG_4BYTES, mtr);
+ mlog_memset(rseg_header + TRX_RSEG_WSREP_XID_INFO,
+ TRX_RSEG_WSREP_XID_DATA + XIDDATASIZE
+ - TRX_RSEG_WSREP_XID_INFO, 0, mtr);
}
static void
@@ -275,12 +286,10 @@ void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr)
mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr);
/* Clear also possible garbage at the end of the page. Old
InnoDB versions did not initialize unused parts of pages. */
- byte* b = rseg_header + TRX_RSEG_MAX_TRX_ID + 8;
- ulint len = srv_page_size
- - (FIL_PAGE_DATA_END
- + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8);
- memset(b, 0, len);
- mlog_log_string(b, len, mtr);
+ mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header,
+ srv_page_size
+ - (FIL_PAGE_DATA_END
+ + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr);
}
/** Create a rollback segment header.
@@ -312,22 +321,17 @@ trx_rseg_header_create(
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
- mlog_write_ulint(TRX_RSEG + TRX_RSEG_FORMAT + block->frame, 0,
- MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(TRX_RSEG_FORMAT + TRX_RSEG
+ + block->frame));
+ ut_ad(0 == mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG
+ + block->frame));
/* Initialize the history list */
-
- mlog_write_ulint(TRX_RSEG + TRX_RSEG_HISTORY_SIZE + block->frame, 0,
- MLOG_4BYTES, mtr);
- flst_init(TRX_RSEG + TRX_RSEG_HISTORY + block->frame, mtr);
- trx_rsegf_t* rsegf = TRX_RSEG + block->frame;
+ flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr);
/* Reset the undo log slots */
- for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) {
- /* This is generating a lot of redo log. MariaDB 10.4
- introduced MLOG_MEMSET to reduce the redo log volume. */
- trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
- }
+ mlog_memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG,
+ TRX_RSEG_N_SLOTS * 4, 0xff, mtr);
if (sys_header) {
/* Add the rollback segment info to the free slot in
@@ -498,8 +502,8 @@ trx_rseg_mem_restore(trx_rseg_t* rseg, trx_id_t& max_trx_id, mtr_t* mtr)
rseg->curr_size = mach_read_from_4(rseg_header + TRX_RSEG_HISTORY_SIZE)
+ 1 + trx_undo_lists_init(rseg, max_trx_id, rseg_header);
- if (ulint len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) {
- trx_sys.history_add(int32(len));
+ if (auto len = flst_get_len(rseg_header + TRX_RSEG_HISTORY)) {
+ trx_sys.rseg_history_len += len;
fil_addr_t node_addr = trx_purge_get_log_from_hist(
flst_get_last(rseg_header + TRX_RSEG_HISTORY, mtr));
@@ -635,10 +639,8 @@ trx_rseg_array_init()
/* Finally, clear WSREP XID in TRX_SYS page. */
const buf_block_t* sys = trx_sysf_get(&mtr);
- mlog_write_ulint(TRX_SYS + TRX_SYS_WSREP_XID_INFO +
- + TRX_SYS_WSREP_XID_MAGIC_N_FLD + sys->frame,
- 0, MLOG_4BYTES, &mtr);
-
+ mlog_memset(TRX_SYS + TRX_SYS_WSREP_XID_INFO + sys->frame,
+ TRX_SYS_WSREP_XID_LEN, 0, &mtr);
mtr.commit();
}
#endif
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 3b7d6dab4eb..e1d72f14e3a 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -189,10 +189,9 @@ trx_sysf_create(
ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END));
/* Initialize all of the page. This part used to be uninitialized. */
- memset(ptr, 0, srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr));
-
- mlog_log_string(TRX_SYS + page, srv_page_size - FIL_PAGE_DATA_END
- - TRX_SYS, mtr);
+ mlog_memset(block, ptr - page,
+ srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr),
+ 0, mtr);
/* Create the first rollback segment in the SYSTEM tablespace */
slot_no = trx_sys_rseg_find_free(block);
@@ -212,7 +211,7 @@ trx_sys_t::create()
m_initialised = true;
mutex_create(LATCH_ID_TRX_SYS, &mutex);
UT_LIST_INIT(trx_list, &trx_t::trx_list);
- my_atomic_store32(&rseg_history_len, 0);
+ rseg_history_len= 0;
rw_trx_hash.init();
}
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index 359ea694536..10c6af6dfeb 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -200,6 +200,9 @@ struct TrxFactory {
lock_trx_lock_list_init(&trx->lock.trx_locks);
+ UT_LIST_INIT(trx->lock.evicted_tables,
+ &dict_table_t::table_LRU);
+
UT_LIST_INIT(
trx->trx_savepoints,
&trx_named_savept_t::trx_savepoints);
@@ -224,6 +227,7 @@ struct TrxFactory {
}
ut_a(UT_LIST_GET_LEN(trx->lock.trx_locks) == 0);
+ ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
UT_DELETE(trx->xid);
ut_free(trx->detailed_error);
@@ -376,6 +380,7 @@ trx_t *trx_create()
ut_ad(trx->lock.n_rec_locks == 0);
ut_ad(trx->lock.table_cached == 0);
ut_ad(trx->lock.rec_cached == 0);
+ ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
#ifdef WITH_WSREP
trx->wsrep_event = NULL;
@@ -613,10 +618,10 @@ trx_resurrect_table_locks(
if (dict_table_t* table = dict_table_open_on_id(
*i, FALSE, DICT_TABLE_OP_LOAD_TABLESPACE)) {
if (!table->is_readable()) {
- mutex_enter(&dict_sys->mutex);
+ mutex_enter(&dict_sys.mutex);
dict_table_close(table, TRUE, FALSE);
- dict_table_remove_from_cache(table);
- mutex_exit(&dict_sys->mutex);
+ dict_sys.remove(table);
+ mutex_exit(&dict_sys.mutex);
continue;
}
@@ -1257,16 +1262,10 @@ trx_update_mod_tables_timestamp(
trx_mod_tables_t::const_iterator end = trx->mod_tables.end();
#ifdef UNIV_DEBUG
-# if MYSQL_VERSION_ID >= 100405
-# define dict_sys_mutex dict_sys.mutex
-# else
-# define dict_sys_mutex dict_sys->mutex
-# endif
-
const bool preserve_tables = !innodb_evict_tables_on_commit_debug
|| trx->is_recovered /* avoid trouble with XA recovery */
# if 1 /* if dict_stats_exec_sql() were not playing dirty tricks */
- || mutex_own(&dict_sys_mutex)
+ || mutex_own(&dict_sys.mutex)
# else /* this would be more proper way to do it */
|| trx->dict_operation_lock_mode || trx->dict_operation
# endif
@@ -1296,21 +1295,48 @@ trx_update_mod_tables_timestamp(
}
/* recheck while holding the mutex that blocks
table->acquire() */
- mutex_enter(&dict_sys_mutex);
+ mutex_enter(&dict_sys.mutex);
if (!table->get_ref_count()) {
-# if MYSQL_VERSION_ID >= 100405
dict_sys.remove(table, true);
-# else
- dict_table_remove_from_cache_low(table, true);
-# endif
}
- mutex_exit(&dict_sys_mutex);
+ mutex_exit(&dict_sys.mutex);
#endif
}
trx->mod_tables.clear();
}
+/** Evict a table definition due to the rollback of ALTER TABLE.
+@param[in] table_id table identifier */
+void trx_t::evict_table(table_id_t table_id)
+{
+ ut_ad(in_rollback);
+
+ dict_table_t* table = dict_table_open_on_id(
+ table_id, true, DICT_TABLE_OP_OPEN_ONLY_IF_CACHED);
+ if (!table) {
+ return;
+ }
+
+ if (!table->release()) {
+ /* This must be a DDL operation that is being rolled
+ back in an active connection. */
+ ut_a(table->get_ref_count() == 1);
+ ut_ad(!is_recovered);
+ ut_ad(mysql_thd);
+ return;
+ }
+
+ /* This table should only be locked by this transaction, if at all. */
+ ut_ad(UT_LIST_GET_LEN(table->locks) <= 1);
+ const bool locked = UT_LIST_GET_LEN(table->locks);
+ ut_ad(!locked || UT_LIST_GET_FIRST(table->locks)->trx == this);
+ dict_sys.remove(table, true, locked);
+ if (locked) {
+ UT_LIST_ADD_FIRST(lock.evicted_tables, table);
+ }
+}
+
/****************************************************************//**
Commits a transaction in memory. */
static
@@ -1390,9 +1416,16 @@ trx_commit_in_memory(
MONITOR_INC(MONITOR_TRX_RW_COMMIT);
trx->is_recovered = false;
}
+
+ while (dict_table_t* table = UT_LIST_GET_FIRST(
+ trx->lock.evicted_tables)) {
+ UT_LIST_REMOVE(trx->lock.evicted_tables, table);
+ dict_mem_table_free(table);
+ }
}
ut_ad(!trx->rsegs.m_redo.undo);
+ ut_ad(UT_LIST_GET_LEN(trx->lock.evicted_tables) == 0);
if (trx_rseg_t* rseg = trx->rsegs.m_redo.rseg) {
mutex_enter(&rseg->mutex);
@@ -1479,11 +1512,8 @@ trx_commit_in_memory(
trx_mutex_enter(trx);
trx->dict_operation = TRX_DICT_OP_NONE;
-
#ifdef WITH_WSREP
- if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) {
- trx->lock.was_chosen_as_deadlock_victim = FALSE;
- }
+ trx->lock.was_chosen_as_wsrep_victim = FALSE;
#endif
DBUG_LOG("trx", "Commit in memory: " << trx);
@@ -1496,7 +1526,9 @@ trx_commit_in_memory(
trx_mutex_exit(trx);
ut_a(trx->error_state == DB_SUCCESS);
- srv_wake_purge_thread_if_not_active();
+ if (!srv_read_only_mode) {
+ srv_wake_purge_thread_if_not_active();
+ }
}
/** Commit a transaction and a mini-transaction.
@@ -1608,6 +1640,16 @@ trx_commit(
}
trx_commit_low(trx, mtr);
+#ifdef WITH_WSREP
+ /* Serialization history has been written and the
+ transaction is committed in memory, which makes
+ this commit ordered. Release commit order critical
+ section. */
+ if (wsrep_on(trx->mysql_thd))
+ {
+ wsrep_commit_ordered(trx->mysql_thd);
+ }
+#endif /* WITH_WSREP */
}
/****************************************************************//**
@@ -2228,7 +2270,7 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element,
transaction needs a valid trx->xid for
invoking trx_sys_update_wsrep_checkpoint(). */
if (!wsrep_is_wsrep_xid(trx->xid))
-#endif
+#endif /* WITH_WSREP */
/* Invalidate the XID, so that subsequent calls will not find it. */
trx->xid->null();
arg->trx= trx;
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index 2c061965e34..5cb7ec3ae0e 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -187,7 +187,7 @@ trx_undo_get_prev_rec_from_prev_page(
space = page_get_space_id(undo_page);
buf_block_t* block = buf_page_get(
- page_id_t(space, prev_page_no), univ_page_size,
+ page_id_t(space, prev_page_no), 0,
shared ? RW_S_LATCH : RW_X_LATCH, mtr);
buf_block_dbg_add_level(block, SYNC_TRX_UNDO_PAGE);
@@ -388,7 +388,7 @@ trx_undo_parse_page_init(const byte* ptr, const byte* end_ptr, page_t* page)
const ulint type = *ptr++;
if (type > TRX_UNDO_UPDATE) {
- recv_sys->found_corrupt_log = true;
+ recv_sys.found_corrupt_log = true;
} else if (page) {
/* Starting with MDEV-12288 in MariaDB 10.3.1, we use
type=0 for the combined insert/update undo log
@@ -662,6 +662,10 @@ trx_undo_write_xid(
const XID* xid, /*!< in: X/Open XA Transaction Identification */
mtr_t* mtr) /*!< in: mtr */
{
+ DBUG_ASSERT(xid->gtrid_length >= 0);
+ DBUG_ASSERT(xid->bqual_length >= 0);
+ DBUG_ASSERT(xid->gtrid_length + xid->bqual_length < XIDDATASIZE);
+
mlog_write_ulint(log_hdr + TRX_UNDO_XA_FORMAT,
static_cast<ulint>(xid->formatID),
MLOG_4BYTES, mtr);
@@ -673,10 +677,15 @@ trx_undo_write_xid(
mlog_write_ulint(log_hdr + TRX_UNDO_XA_BQUAL_LEN,
static_cast<ulint>(xid->bqual_length),
MLOG_4BYTES, mtr);
-
+ const ulint xid_length = static_cast<ulint>(xid->gtrid_length
+ + xid->bqual_length);
mlog_write_string(log_hdr + TRX_UNDO_XA_XID,
reinterpret_cast<const byte*>(xid->data),
- XIDDATASIZE, mtr);
+ xid_length, mtr);
+ if (UNIV_LIKELY(xid_length < XIDDATASIZE)) {
+ mlog_memset(log_hdr + TRX_UNDO_XA_XID + xid_length,
+ XIDDATASIZE - xid_length, 0, mtr);
+ }
}
/********************************************************************//**
@@ -844,7 +853,7 @@ trx_undo_free_page(
TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_NODE + undo_page, mtr);
fseg_free_page(TRX_UNDO_SEG_HDR + TRX_UNDO_FSEG_HEADER + header_page,
- rseg->space, page_no, false, mtr);
+ rseg->space, page_no, false, true, mtr);
const fil_addr_t last_addr = flst_get_last(
TRX_UNDO_SEG_HDR + TRX_UNDO_PAGE_LIST + header_page, mtr);
@@ -883,54 +892,55 @@ trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr)
@param[in,out] undo undo log
@param[in] limit all undo logs after this limit will be discarded
@param[in] is_temp whether this is temporary undo log */
-void
-trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp)
+void trx_undo_truncate_end(trx_undo_t& undo, undo_no_t limit, bool is_temp)
{
- ut_ad(mutex_own(&undo->rseg->mutex));
- ut_ad(is_temp == !undo->rseg->is_persistent());
+ mtr_t mtr;
+ ut_ad(is_temp == !undo.rseg->is_persistent());
for (;;) {
- mtr_t mtr;
mtr.start();
if (is_temp) {
mtr.set_log_mode(MTR_LOG_NO_REDO);
}
trx_undo_rec_t* trunc_here = NULL;
+ mutex_enter(&undo.rseg->mutex);
page_t* undo_page = trx_undo_page_get(
- page_id_t(undo->rseg->space->id, undo->last_page_no),
+ page_id_t(undo.rseg->space->id, undo.last_page_no),
&mtr);
trx_undo_rec_t* rec = trx_undo_page_get_last_rec(
- undo_page, undo->hdr_page_no, undo->hdr_offset);
+ undo_page, undo.hdr_page_no, undo.hdr_offset);
while (rec) {
- if (trx_undo_rec_get_undo_no(rec) >= limit) {
- /* Truncate at least this record off, maybe
- more */
- trunc_here = rec;
- } else {
- goto function_exit;
+ if (trx_undo_rec_get_undo_no(rec) < limit) {
+ goto func_exit;
}
+ /* Truncate at least this record off, maybe more */
+ trunc_here = rec;
rec = trx_undo_page_get_prev_rec(rec,
- undo->hdr_page_no,
- undo->hdr_offset);
+ undo.hdr_page_no,
+ undo.hdr_offset);
}
- if (undo->last_page_no == undo->hdr_page_no) {
-function_exit:
- if (trunc_here) {
- mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR
- + TRX_UNDO_PAGE_FREE,
- ulint(trunc_here - undo_page),
- MLOG_2BYTES, &mtr);
- }
-
+ if (undo.last_page_no != undo.hdr_page_no) {
+ trx_undo_free_last_page(&undo, &mtr);
+ mutex_exit(&undo.rseg->mutex);
mtr.commit();
- return;
+ continue;
+ }
+
+func_exit:
+ mutex_exit(&undo.rseg->mutex);
+
+ if (trunc_here) {
+ mlog_write_ulint(undo_page + TRX_UNDO_PAGE_HDR
+ + TRX_UNDO_PAGE_FREE,
+ ulint(trunc_here - undo_page),
+ MLOG_2BYTES, &mtr);
}
- trx_undo_free_last_page(undo, &mtr);
mtr.commit();
+ return;
}
}
@@ -1334,7 +1344,7 @@ trx_undo_reuse_cached(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** pundo,
buf_block_t* block = buf_page_get(page_id_t(undo->rseg->space->id,
undo->hdr_page_no),
- univ_page_size, RW_X_LATCH, mtr);
+ 0, RW_X_LATCH, mtr);
if (!block) {
return NULL;
}
@@ -1402,7 +1412,7 @@ trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr)
if (undo) {
return buf_page_get_gen(
page_id_t(undo->rseg->space->id, undo->last_page_no),
- univ_page_size, RW_X_LATCH,
+ 0, RW_X_LATCH,
buf_pool_is_obsolete(undo->withdraw_clock)
? NULL : undo->guess_block,
BUF_GET, __FILE__, __LINE__, mtr, err);
@@ -1458,7 +1468,7 @@ trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
if (*undo) {
return buf_page_get_gen(
page_id_t(rseg->space->id, (*undo)->last_page_no),
- univ_page_size, RW_X_LATCH,
+ 0, RW_X_LATCH,
buf_pool_is_obsolete((*undo)->withdraw_clock)
? NULL : (*undo)->guess_block,
BUF_GET, __FILE__, __LINE__, mtr, err);
diff --git a/storage/innobase/ut/ut0crc32.cc b/storage/innobase/ut/ut0crc32.cc
index 13850a48600..5ccd15dd5ca 100644
--- a/storage/innobase/ut/ut0crc32.cc
+++ b/storage/innobase/ut/ut0crc32.cc
@@ -469,34 +469,6 @@ ut_crc32_64_sw(
*len -= 8;
}
-#ifdef INNODB_BUG_ENDIAN_CRC32
-/** Calculate CRC32 over 64-bit byte string using a software implementation.
-The byte string is converted to a 64-bit integer using big endian byte order.
-@param[in,out] crc crc32 checksum so far when this function is called,
-when the function ends it will contain the new checksum
-@param[in,out] data data to be checksummed, the pointer will be advanced
-with 8 bytes
-@param[in,out] len remaining bytes, it will be decremented with 8 */
-inline
-void
-ut_crc32_64_legacy_big_endian_sw(
- uint32_t* crc,
- const byte** data,
- ulint* len)
-{
- uint64_t data_int = *reinterpret_cast<const uint64_t*>(*data);
-
-#ifndef WORDS_BIGENDIAN
- data_int = ut_crc32_swap_byteorder(data_int);
-#endif /* WORDS_BIGENDIAN */
-
- *crc = ut_crc32_64_low_sw(*crc, data_int);
-
- *data += 8;
- *len -= 8;
-}
-#endif /* INNODB_BUG_ENDIAN_CRC32 */
-
/** Calculates CRC32 in software, without using CPU instructions.
@param[in] buf data over which to calculate CRC32
@param[in] len data length
@@ -547,57 +519,6 @@ ut_crc32_sw(
return(~crc);
}
-#ifdef INNODB_BUG_ENDIAN_CRC32
-/** Calculates CRC32 in software, without using CPU instructions.
-This function uses big endian byte ordering when converting byte sequence to
-integers.
-@param[in] buf data over which to calculate CRC32
-@param[in] len data length
-@return CRC-32C (polynomial 0x11EDC6F41) */
-uint32_t ut_crc32_legacy_big_endian(const byte* buf, ulint len)
-{
- uint32_t crc = 0xFFFFFFFFU;
-
- ut_a(ut_crc32_slice8_table_initialized);
-
- /* Calculate byte-by-byte up to an 8-byte aligned address. After
- this consume the input 8-bytes at a time. */
- while (len > 0 && (reinterpret_cast<uintptr_t>(buf) & 7) != 0) {
- ut_crc32_8_sw(&crc, &buf, &len);
- }
-
- while (len >= 128) {
- /* This call is repeated 16 times. 16 * 8 = 128. */
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- }
-
- while (len >= 8) {
- ut_crc32_64_legacy_big_endian_sw(&crc, &buf, &len);
- }
-
- while (len > 0) {
- ut_crc32_8_sw(&crc, &buf, &len);
- }
-
- return(~crc);
-}
-#endif /* INNODB_BUG_ENDIAN_CRC32 */
-
/********************************************************************//**
Initializes the data structures used by ut_crc32*(). Does not do any
allocations, would not hurt if called twice, but would be pointless. */
@@ -620,9 +541,6 @@ ut_crc32_init()
if (features_ecx & 1 << 20) {
ut_crc32 = ut_crc32_hw;
-#ifdef INNODB_BUG_ENDIAN_CRC32
- ut_crc32_legacy_big_endian = ut_crc32_legacy_big_endian_hw;
-#endif /* INNODB_BUG_ENDIAN_CRC32 */
ut_crc32_implementation = "Using SSE2 crc32 instructions";
}
#endif
diff --git a/storage/innobase/ut/ut0new.cc b/storage/innobase/ut/ut0new.cc
index 2a372ca9f63..f47a5112fd7 100644
--- a/storage/innobase/ut/ut0new.cc
+++ b/storage/innobase/ut/ut0new.cc
@@ -147,7 +147,6 @@ ut_new_boot()
"row0merge",
"row0mysql",
"row0sel",
- "row0trunc",
"srv0conc",
"srv0srv",
"srv0start",
diff --git a/storage/innobase/ut/ut0rnd.cc b/storage/innobase/ut/ut0rnd.cc
index 8265121ef2e..a2e569514cb 100644
--- a/storage/innobase/ut/ut0rnd.cc
+++ b/storage/innobase/ut/ut0rnd.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2019, MariaDB Corporation.
+Copyright (c) 2019, 2020, 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
@@ -27,7 +27,7 @@ Created 5/11/1994 Heikki Tuuri
#include "ut0rnd.h"
/** Seed value of ut_rnd_gen() */
-int32 ut_rnd_current;
+std::atomic<uint32_t> ut_rnd_current;
/** These random numbers are used in ut_find_prime */
/*@{*/
diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc
index 0d6e9c45aec..5c19fcb6825 100644
--- a/storage/innobase/ut/ut0ut.cc
+++ b/storage/innobase/ut/ut0ut.cc
@@ -421,8 +421,6 @@ ut_strerr(
return("Tablespace already exists");
case DB_TABLESPACE_DELETED:
return("Tablespace deleted or being deleted");
- case DB_TABLESPACE_TRUNCATED:
- return("Tablespace was truncated");
case DB_TABLESPACE_NOT_FOUND:
return("Tablespace not found");
case DB_LOCK_TABLE_FULL:
diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt
index 2c46492c93e..248f7cbe177 100644
--- a/storage/maria/CMakeLists.txt
+++ b/storage/maria/CMakeLists.txt
@@ -47,7 +47,7 @@ SET(ARIA_SOURCES ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c
ma_checkpoint.c ma_recovery.c ma_commit.c ma_pagecrc.c
ha_maria.h maria_def.h ma_recovery_util.c ma_servicethread.c
ma_norec.c
- ma_crypt.c
+ ma_crypt.c ma_backup.c
)
IF(APPLE)
@@ -56,7 +56,8 @@ IF(APPLE)
ENDIF()
MYSQL_ADD_PLUGIN(aria ${ARIA_SOURCES}
- STORAGE_ENGINE STATIC_ONLY DEFAULT
+ STORAGE_ENGINE
+ MANDATORY
RECOMPILE_FOR_EMBEDDED)
IF(NOT WITH_ARIA_STORAGE_ENGINE)
@@ -97,7 +98,12 @@ IF(WITH_UNIT_TESTS)
ADD_EXECUTABLE(ma_sp_test ma_sp_test.c)
TARGET_LINK_LIBRARIES(ma_sp_test aria)
+
+ ADD_EXECUTABLE(test_ma_backup test_ma_backup.c)
+ TARGET_LINK_LIBRARIES(test_ma_backup aria)
+
ADD_SUBDIRECTORY(unittest)
+
ENDIF()
IF (MSVC)
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 1745e1fa653..dabacc5af53 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -152,10 +152,11 @@ static void update_log_file_size(MYSQL_THD thd,
struct st_mysql_sys_var *var,
void *var_ptr, const void *save);
+/* The 4096 is there because of MariaDB privilege tables */
static MYSQL_SYSVAR_ULONG(block_size, maria_block_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Block size to be used for Aria index pages.", 0, 0,
- MARIA_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH,
+ MARIA_KEY_BLOCK_LENGTH, 4096,
MARIA_MAX_KEY_BLOCK_LENGTH, MARIA_MIN_KEY_BLOCK_LENGTH);
static MYSQL_SYSVAR_ULONG(checkpoint_interval, checkpoint_interval,
@@ -390,6 +391,10 @@ static void init_aria_psi_keys(void)
#define init_aria_psi_keys() /* no-op */
#endif /* HAVE_PSI_INTERFACE */
+const char *MA_CHECK_INFO= "info";
+const char *MA_CHECK_WARNING= "warning";
+const char *MA_CHECK_ERROR= "error";
+
/*****************************************************************************
** MARIA tables
*****************************************************************************/
@@ -402,6 +407,20 @@ static handler *maria_create_handler(handlerton *hton,
}
+static void _ma_check_print(HA_CHECK *param, const char* msg_type,
+ const char *msgbuf)
+{
+ if (msg_type == MA_CHECK_INFO)
+ sql_print_information("%s.%s: %s", param->db_name, param->table_name,
+ msgbuf);
+ else if (msg_type == MA_CHECK_WARNING)
+ sql_print_warning("%s.%s: %s", param->db_name, param->table_name,
+ msgbuf);
+ else
+ sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+}
+
+
// collect errors printed by maria_check routines
static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
@@ -423,16 +442,21 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
if (!thd->vio_ok())
{
- sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+ _ma_check_print(param, msg_type, msgbuf);
return;
}
if (param->testflag &
(T_CREATE_MISSING_KEYS | T_SAFE_REPAIR | T_AUTO_REPAIR))
{
- my_message(ER_NOT_KEYFILE, msgbuf, MYF(MY_WME));
+ myf flag= 0;
+ if (msg_type == MA_CHECK_INFO)
+ flag= ME_NOTE;
+ else if (msg_type == MA_CHECK_WARNING)
+ flag= ME_WARNING;
+ my_message(ER_NOT_KEYFILE, msgbuf, MYF(flag));
if (thd->variables.log_warnings > 2)
- sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+ _ma_check_print(param, msg_type, msgbuf);
return;
}
length= (uint) (strxmov(name, param->db_name, ".", param->table_name,
@@ -454,7 +478,7 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
sql_print_error("Failed on my_net_write, writing to stderr instead: %s.%s: %s\n",
param->db_name, param->table_name, msgbuf);
else if (thd->variables.log_warnings > 2)
- sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+ _ma_check_print(param, msg_type, msgbuf);
return;
}
@@ -530,6 +554,11 @@ static int table2maria(TABLE *table_arg, data_file_type row_type,
if (!table_arg->field[field->field_index]->stored_in_db())
{
my_free(*recinfo_out);
+ if (table_arg->s->long_unique_table)
+ {
+ my_error(ER_TOO_LONG_KEY, MYF(0), table_arg->file->max_key_length());
+ DBUG_RETURN(HA_ERR_INDEX_COL_TOO_LONG);
+ }
my_error(ER_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN, MYF(0));
DBUG_RETURN(HA_ERR_UNSUPPORTED);
}
@@ -882,7 +911,7 @@ void _ma_check_print_error(HA_CHECK *param, const char *fmt, ...)
if (param->testflag & T_SUPPRESS_ERR_HANDLING)
DBUG_VOID_RETURN;
va_start(args, fmt);
- _ma_check_print_msg(param, "error", fmt, args);
+ _ma_check_print_msg(param, MA_CHECK_ERROR, fmt, args);
va_end(args);
DBUG_VOID_RETURN;
}
@@ -893,7 +922,7 @@ void _ma_check_print_info(HA_CHECK *param, const char *fmt, ...)
va_list args;
DBUG_ENTER("_ma_check_print_info");
va_start(args, fmt);
- _ma_check_print_msg(param, "info", fmt, args);
+ _ma_check_print_msg(param, MA_CHECK_INFO, fmt, args);
va_end(args);
DBUG_VOID_RETURN;
}
@@ -906,7 +935,7 @@ void _ma_check_print_warning(HA_CHECK *param, const char *fmt, ...)
param->warning_printed= 1;
param->out_flag |= O_DATA_LOST;
va_start(args, fmt);
- _ma_check_print_msg(param, "warning", fmt, args);
+ _ma_check_print_msg(param, MA_CHECK_WARNING, fmt, args);
va_end(args);
DBUG_VOID_RETURN;
}
@@ -1011,6 +1040,8 @@ handler *ha_maria::clone(const char *name __attribute__((unused)),
new_handler->file->state= file->state;
/* maria_create_trn_for_mysql() is never called for clone() tables */
new_handler->file->trn= file->trn;
+ DBUG_ASSERT(new_handler->file->trn_prev == 0 &&
+ new_handler->file->trn_next == 0);
}
return new_handler;
}
@@ -1156,6 +1187,14 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
int_table_flags |= HA_HAS_NEW_CHECKSUM;
/*
+ We can only do online backup on transactional tables with checksum.
+ Checksums are needed to avoid half writes.
+ */
+ if (file->s->options & HA_OPTION_PAGE_CHECKSUM &&
+ file->s->base.born_transactional)
+ int_table_flags |= HA_CAN_ONLINE_BACKUPS;
+
+ /*
For static size rows, tell MariaDB that we will access all bytes
in the record when writing it. This signals MariaDB to initialize
the full row to ensure we don't get any errors from valgrind and
@@ -1191,12 +1230,14 @@ int ha_maria::close(void)
MARIA_HA *tmp= file;
if (!tmp)
return 0;
+ DBUG_ASSERT(file->trn == 0 || file->trn == &dummy_transaction_object);
+ DBUG_ASSERT(file->trn_next == 0 && file->trn_prev == 0);
file= 0;
return maria_close(tmp);
}
-int ha_maria::write_row(uchar * buf)
+int ha_maria::write_row(const uchar * buf)
{
/*
If we have an auto_increment column and we are writing a changed row
@@ -1307,6 +1348,16 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
mysql_mutex_unlock(&share->intern_lock);
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
HA_STATUS_CONST);
+
+ /*
+ Write a 'table is ok' message to error log if table is ok and
+ we have written to error log that table was getting checked
+ */
+ if (!error && !(table->db_stat & HA_READ_ONLY) &&
+ !maria_is_crashed(file) && thd->error_printed_to_log &&
+ (param->warning_printed || param->error_printed ||
+ param->note_printed))
+ _ma_check_print_info(param, "Table is fixed");
}
}
else if (!maria_is_crashed(file) && !thd->killed)
@@ -1317,7 +1368,10 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
/* Reset trn, that may have been set by repair */
if (old_trn && old_trn != file->trn)
+ {
+ DBUG_ASSERT(old_trn->used_instances == 0);
_ma_set_trn_for_table(file, old_trn);
+ }
thd_proc_info(thd, old_proc_info);
thd_progress_end(thd);
return error ? HA_ADMIN_CORRUPT : HA_ADMIN_OK;
@@ -2103,7 +2157,32 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags)
else
{
my_bool all_keys= MY_TEST(flags & HA_CREATE_UNIQUE_INDEX_BY_SORT);
- maria_disable_indexes_for_rebuild(file, rows, all_keys);
+ /*
+ Deactivate all indexes that can be recreated fast.
+ These include packed keys on which sorting will use more temporary
+ space than the max allowed file length or for which the unpacked keys
+ will take much more space than packed keys.
+ Note that 'rows' may be zero for the case when we don't know how many
+ rows we will put into the file.
+ */
+ MARIA_SHARE *share= file->s;
+ MARIA_KEYDEF *key=share->keyinfo;
+ uint i;
+
+ DBUG_ASSERT(share->state.state.records == 0 &&
+ (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES));
+ for (i=0 ; i < share->base.keys ; i++,key++)
+ {
+ if (!(key->flag & (HA_SPATIAL | HA_AUTO_KEY | HA_RTREE_INDEX)) &&
+ ! maria_too_big_key_for_sort(key,rows) && share->base.auto_key != i+1 &&
+ (all_keys || !(key->flag & HA_NOSAME)) &&
+ table->key_info[i].algorithm != HA_KEY_ALG_LONG_HASH)
+ {
+ maria_clear_key_active(share->state.key_map, i);
+ file->update|= HA_STATE_CHANGED;
+ file->create_unique_index_by_sort= all_keys;
+ }
+ }
}
if (share->now_transactional)
{
@@ -2538,14 +2617,20 @@ int ha_maria::extra(enum ha_extra_function operation)
operation == HA_EXTRA_PREPARE_FOR_FORCED_CLOSE))
{
THD *thd= table->in_use;
- TRN *trn= THD_TRN;
- _ma_set_tmp_trn_for_table(file, trn);
+ file->trn= THD_TRN;
}
DBUG_ASSERT(file->s->base.born_transactional || file->trn == 0 ||
file->trn == &dummy_transaction_object);
tmp= maria_extra(file, operation, 0);
- file->trn= old_trn; // Reset trn if was used
+ /*
+ Restore trn if it was changed above.
+ Note that table could be removed from trn->used_tables and
+ trn->used_instances if trn was set and some of the above operations
+ was used. This is ok as the table should not be part of any transaction
+ after this and thus doesn't need to be part of any of the above lists.
+ */
+ file->trn= old_trn;
return tmp;
}
@@ -2785,9 +2870,10 @@ static void reset_thd_trn(THD *thd, MARIA_HA *first_table)
{
DBUG_ENTER("reset_thd_trn");
THD_TRN= NULL;
- for (MARIA_HA *table= first_table; table ;
- table= table->trn_next)
+ MARIA_HA *next;
+ for (MARIA_HA *table= first_table; table ; table= next)
{
+ next= table->trn_next;
_ma_reset_trn_for_table(table);
/*
@@ -2847,9 +2933,11 @@ int ha_maria::implicit_commit(THD *thd, bool new_trn)
DBUG_RETURN(0);
}
+ /* Prepare to move used_instances and locked tables to new TRN object */
locked_tables= trnman_has_locked_tables(trn);
+ trnman_reset_locked_tables(trn, 0);
+ relink_trn_used_instances(&used_tables, trn);
- used_tables= (MARIA_HA*) trn->used_instances;
error= 0;
if (unlikely(ma_commit(trn)))
error= 1;
@@ -3271,6 +3359,7 @@ static int maria_commit(handlerton *hton __attribute__ ((unused)),
MARIA_HA *used_instances= (MARIA_HA*) trn->used_instances;
DBUG_ENTER("maria_commit");
+ DBUG_ASSERT(trnman_has_locked_tables(trn) == 0);
trnman_reset_locked_tables(trn, 0);
trnman_set_flags(trn, trnman_get_flags(trn) & ~TRN_STATE_INFO_LOGGED);
@@ -3289,9 +3378,12 @@ static int maria_rollback(handlerton *hton __attribute__ ((unused)),
{
TRN *trn= THD_TRN;
DBUG_ENTER("maria_rollback");
+
+ DBUG_ASSERT(trnman_has_locked_tables(trn) == 0);
trnman_reset_locked_tables(trn, 0);
/* statement or transaction ? */
- if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) && !all)
+ if ((thd->variables.option_bits & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
+ !all)
{
trnman_rollback_statement(trn);
DBUG_RETURN(0); // end of statement
@@ -3325,6 +3417,21 @@ int maria_checkpoint_state(handlerton *hton, bool disabled)
}
+/*
+ Handle backup calls
+*/
+
+void maria_prepare_for_backup()
+{
+ translog_disable_purge();
+}
+
+void maria_end_backup()
+{
+ translog_enable_purge();
+}
+
+
#define SHOW_MSG_LEN (FN_REFLEN + 20)
/**
@@ -3447,7 +3554,7 @@ static int mark_recovery_start(const char* log_dir)
int res;
DBUG_ENTER("mark_recovery_start");
if (!(maria_recover_options & HA_RECOVER_ANY))
- ma_message_no_user(ME_JUST_WARNING, "Please consider using option"
+ ma_message_no_user(ME_WARNING, "Please consider using option"
" --aria-recover-options[=...] to automatically check and"
" repair tables when logs are removed by option"
" --aria-force-start-after-recovery-failures=#");
@@ -3465,7 +3572,7 @@ static int mark_recovery_start(const char* log_dir)
" recovery from logs",
(res ? "failed to remove some" : "removed all"),
recovery_failures);
- ma_message_no_user((res ? 0 : ME_JUST_WARNING), msg);
+ ma_message_no_user((res ? 0 : ME_WARNING), msg);
}
else
res= ma_control_file_write_and_force(last_checkpoint_lsn, last_logno,
@@ -3525,6 +3632,9 @@ static int ha_maria_init(void *p)
#endif
maria_hton->flush_logs= maria_flush_logs;
maria_hton->show_status= maria_show_status;
+ maria_hton->prepare_for_backup= maria_prepare_for_backup;
+ maria_hton->end_backup= maria_end_backup;
+
/* TODO: decide if we support Maria being used for log tables */
maria_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
bzero(maria_log_pagecache, sizeof(*maria_log_pagecache));
@@ -3926,8 +4036,8 @@ maria_declare_plugin(aria)
MYSQL_STORAGE_ENGINE_PLUGIN,
&maria_storage_engine,
"Aria",
- "Monty Program Ab",
- "Crash-safe tables with MyISAM heritage",
+ "MariaDB Corporation Ab",
+ "Crash-safe tables with MyISAM heritage. Used for internal temporary tables and privilege tables",
PLUGIN_LICENSE_GPL,
ha_maria_init, /* Plugin Init */
NULL, /* Plugin Deinit */
diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
index 48af840d86b..ef0ceb1cd32 100644
--- a/storage/maria/ha_maria.h
+++ b/storage/maria/ha_maria.h
@@ -73,7 +73,7 @@ public:
int open(const char *name, int mode, uint test_if_locked);
int close(void);
- int write_row(uchar * buf);
+ int write_row(const uchar * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int index_read_map(uchar * buf, const uchar * key, key_part_map keypart_map,
diff --git a/storage/maria/ma_backup.c b/storage/maria/ma_backup.c
new file mode 100644
index 00000000000..8f20209c48a
--- /dev/null
+++ b/storage/maria/ma_backup.c
@@ -0,0 +1,281 @@
+/* Copyright (C) 2018 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 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 Street, Fifth Floor, Boston, MA 02111-1301 USA */
+
+/* Code for doing backups of Aria tables */
+
+#include "maria_def.h"
+#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */
+#include "ma_checkpoint.h"
+#include <aria_backup.h>
+
+static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base);
+
+/**
+ @brief Get capabilites for an Aria table
+
+ @param kfile key file (.MAI)
+ @param cap Capabilities are stored here
+
+ @return 0 ok
+ @return X errno
+*/
+
+int aria_get_capabilities(File kfile, ARIA_TABLE_CAPABILITIES *cap)
+{
+ MARIA_SHARE share;
+ int error= 0;
+ uint head_length= sizeof(share.state.header), base_pos;
+ uint aligned_bit_blocks;
+ size_t info_length;
+ uchar *disc_cache;
+ DBUG_ENTER("aria_get_capabilities");
+
+ bzero(cap, sizeof(*cap));
+ if (my_pread(kfile,share.state.header.file_version, head_length, 0,
+ MYF(MY_NABP)))
+ DBUG_RETURN(HA_ERR_NOT_A_TABLE);
+
+ if (memcmp(share.state.header.file_version, maria_file_magic, 4))
+ DBUG_RETURN(HA_ERR_NOT_A_TABLE);
+
+ share.options= mi_uint2korr(share.state.header.options);
+
+ info_length= mi_uint2korr(share.state.header.header_length);
+ base_pos= mi_uint2korr(share.state.header.base_pos);
+
+ /*
+ Allocate space for header information and for data that is too
+ big to keep on stack
+ */
+ if (!(disc_cache= my_malloc(info_length, MYF(MY_WME))))
+ DBUG_RETURN(ENOMEM);
+
+ if (my_pread(kfile, disc_cache, info_length, 0L, MYF(MY_NABP)))
+ {
+ error= my_errno;
+ goto err;
+ }
+ _ma_base_info_read(disc_cache + base_pos, &share.base);
+ cap->transactional= share.base.born_transactional;
+ cap->checksum= MY_TEST(share.options & HA_OPTION_PAGE_CHECKSUM);
+ cap->online_backup_safe= cap->transactional && cap->checksum;
+ cap->header_size= share.base.keystart;
+ cap->keypage_header= ((share.base.born_transactional ?
+ LSN_STORE_SIZE + TRANSID_SIZE :
+ 0) + KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE +
+ KEYPAGE_USED_SIZE);
+ cap->block_size= share.base.block_size;
+
+ if (share.state.header.data_file_type == BLOCK_RECORD)
+ {
+ /* Calulate how man pages the row bitmap covers. From _ma_bitmap_init() */
+ aligned_bit_blocks= (cap->block_size - PAGE_SUFFIX_SIZE) / 6;
+ /*
+ In each 6 bytes, we have 6*8/3 = 16 pages covered
+ The +1 is to add the bitmap page, as this doesn't have to be covered
+ */
+ cap->bitmap_pages_covered= aligned_bit_blocks * 16 + 1;
+ }
+
+ /* Do a check that that we got things right */
+ if (share.state.header.data_file_type != BLOCK_RECORD &&
+ cap->online_backup_safe)
+ error= HA_ERR_NOT_A_TABLE;
+
+err:
+ my_free(disc_cache);
+ DBUG_RETURN(error);
+} /* maria_get_capabilities */
+
+
+/*
+ This is a copy of my_base_info_read from ma_open().
+ The base information will never change (something may be added
+ last, but not relevant for maria_get_capabilities), so it's safe to
+ copy it here.
+
+ The copy is done to avoid linking in the fill Aria library just
+ because maria_backup uses maria_get_capabilities()
+*/
+
+
+static uchar *_ma_base_info_read(uchar *ptr, MARIA_BASE_INFO *base)
+{
+ bmove(base->uuid, ptr, MY_UUID_SIZE); ptr+= MY_UUID_SIZE;
+ base->keystart= mi_sizekorr(ptr); ptr+= 8;
+ base->max_data_file_length= mi_sizekorr(ptr); ptr+= 8;
+ base->max_key_file_length= mi_sizekorr(ptr); ptr+= 8;
+ base->records= (ha_rows) mi_sizekorr(ptr); ptr+= 8;
+ base->reloc= (ha_rows) mi_sizekorr(ptr); ptr+= 8;
+ base->mean_row_length= mi_uint4korr(ptr); ptr+= 4;
+ base->reclength= mi_uint4korr(ptr); ptr+= 4;
+ base->pack_reclength= mi_uint4korr(ptr); ptr+= 4;
+ base->min_pack_length= mi_uint4korr(ptr); ptr+= 4;
+ base->max_pack_length= mi_uint4korr(ptr); ptr+= 4;
+ base->min_block_length= mi_uint4korr(ptr); ptr+= 4;
+ base->fields= mi_uint2korr(ptr); ptr+= 2;
+ base->fixed_not_null_fields= mi_uint2korr(ptr); ptr+= 2;
+ base->fixed_not_null_fields_length= mi_uint2korr(ptr);ptr+= 2;
+ base->max_field_lengths= mi_uint2korr(ptr); ptr+= 2;
+ base->pack_fields= mi_uint2korr(ptr); ptr+= 2;
+ base->extra_options= mi_uint2korr(ptr); ptr+= 2;
+ base->null_bytes= mi_uint2korr(ptr); ptr+= 2;
+ base->original_null_bytes= mi_uint2korr(ptr); ptr+= 2;
+ base->field_offsets= mi_uint2korr(ptr); ptr+= 2;
+ base->language= mi_uint2korr(ptr); ptr+= 2;
+ base->block_size= mi_uint2korr(ptr); ptr+= 2;
+
+ base->rec_reflength= *ptr++;
+ base->key_reflength= *ptr++;
+ base->keys= *ptr++;
+ base->auto_key= *ptr++;
+ base->born_transactional= *ptr++;
+ ptr++;
+ base->pack_bytes= mi_uint2korr(ptr); ptr+= 2;
+ base->blobs= mi_uint2korr(ptr); ptr+= 2;
+ base->max_key_block_length= mi_uint2korr(ptr); ptr+= 2;
+ base->max_key_length= mi_uint2korr(ptr); ptr+= 2;
+ base->extra_alloc_bytes= mi_uint2korr(ptr); ptr+= 2;
+ base->extra_alloc_procent= *ptr++;
+ ptr+= 16;
+ return ptr;
+}
+
+
+/**
+ @brief Copy an index block with re-read if checksum doesn't match
+
+ @param dfile data file (.MAD)
+ @param cap aria capabilities from aria_get_capabilities
+ @param block block number to read (0, 1, 2, 3...)
+ @param buffer read data to this buffer
+ @param bytes_read number of bytes actually read (in case of end of file)
+
+ @return 0 ok
+ @return HA_ERR_END_OF_FILE ; End of file
+ @return # error number
+*/
+
+#define MAX_RETRY 10
+
+int aria_read_index(File kfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
+ uchar *buffer)
+{
+ MARIA_SHARE share;
+ int retry= 0;
+ DBUG_ENTER("aria_read_index");
+
+ share.keypage_header= cap->keypage_header;
+ share.block_size= cap->block_size;
+ do
+ {
+ int error;
+ size_t length;
+ if ((length= my_pread(kfile, buffer, cap->block_size,
+ block * cap->block_size, MYF(0))) != cap->block_size)
+ {
+ if (length == 0)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ if (length == (size_t) -1)
+ DBUG_RETURN(my_errno ? my_errno : -1);
+ /* Assume we got a half read; Do a re-read */
+ }
+ /* If not transactional or key file header, there are no checksums */
+ if (!cap->online_backup_safe ||
+ block < cap->header_size/ cap->block_size)
+ DBUG_RETURN(length == cap->block_size ? 0 : HA_ERR_CRASHED);
+
+ if (length == cap->block_size)
+ {
+ length= _ma_get_page_used(&share, buffer);
+ if (length > cap->block_size - CRC_SIZE)
+ DBUG_RETURN(HA_ERR_CRASHED);
+ error= maria_page_crc_check(buffer, block, &share,
+ MARIA_NO_CRC_NORMAL_PAGE,
+ (int) length);
+ if (error != HA_ERR_WRONG_CRC)
+ DBUG_RETURN(error);
+ }
+ my_sleep(100000); /* Sleep 0.1 seconds */
+ } while (retry < MAX_RETRY);
+ DBUG_RETURN(HA_ERR_WRONG_CRC);
+}
+
+
+/**
+ @brief Copy a data block with re-read if checksum doesn't match
+
+ @param dfile data file (.MAD)
+ @param cap aria capabilities from aria_get_capabilities
+ @param block block number to read (0, 1, 2, 3...)
+ @param buffer read data to this buffer
+ @param bytes_read number of bytes actually read (in case of end of file)
+
+ @return 0 ok
+ @return HA_ERR_END_OF_FILE ; End of file
+ @return # error number
+*/
+
+int aria_read_data(File dfile, ARIA_TABLE_CAPABILITIES *cap, ulonglong block,
+ uchar *buffer, size_t *bytes_read)
+{
+ MARIA_SHARE share;
+ int retry= 0;
+ DBUG_ENTER("aria_read_data");
+
+ share.keypage_header= cap->keypage_header;
+ share.block_size= cap->block_size;
+
+ if (!cap->online_backup_safe)
+ {
+ *bytes_read= my_pread(dfile, buffer, cap->block_size,
+ block * cap->block_size, MY_WME);
+ if (*bytes_read == 0)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ DBUG_RETURN(*bytes_read > 0 ? 0 : (my_errno ? my_errno : -1));
+ }
+
+ *bytes_read= cap->block_size;
+ do
+ {
+ int error;
+ size_t length;
+ if ((length= my_pread(dfile, buffer, cap->block_size,
+ block * cap->block_size, MYF(0))) != cap->block_size)
+ {
+ if (length == 0)
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ if (length == (size_t) -1)
+ DBUG_RETURN(my_errno ? my_errno : -1);
+ }
+
+ /* If not transactional or key file header, there are no checksums */
+ if (!cap->online_backup_safe)
+ DBUG_RETURN(length == cap->block_size ? 0 : HA_ERR_CRASHED);
+
+ if (length == cap->block_size)
+ {
+ error= maria_page_crc_check(buffer, block, &share,
+ ((block % cap->bitmap_pages_covered) == 0 ?
+ MARIA_NO_CRC_BITMAP_PAGE :
+ MARIA_NO_CRC_NORMAL_PAGE),
+ share.block_size - CRC_SIZE);
+ if (error != HA_ERR_WRONG_CRC)
+ DBUG_RETURN(error);
+ }
+ my_sleep(100000); /* Sleep 0.1 seconds */
+ } while (retry < MAX_RETRY);
+ DBUG_RETURN(HA_ERR_WRONG_CRC);
+}
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index 2fe2f13f17c..a82637e2b82 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -2598,7 +2598,8 @@ static my_bool free_full_page_range(MARIA_HA *info, pgcache_page_no_t page,
@param record Record we should write
@param row Statistics about record (calculated by
calc_record_size())
- @param map_blocks On which pages the record should be stored
+ @param bitmap_blocks On which pages the record should be stored
+ @param head_block_is_read 1 if head block existed. 0 if new block.
@param row_pos Position on head page where to put head part of
record
@param undo_lsn <> LSN_ERROR if we are executing an UNDO
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 101c33b7802..0a271a77a36 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -164,6 +164,9 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info)
{
MARIA_SHARE *share= info->s;
+ /* Protection for HA_EXTRA_FLUSH */
+ mysql_mutex_lock(&share->intern_lock);
+
if (maria_is_crashed_on_repair(info))
_ma_check_print_warning(param,
"Table is marked as crashed and last repair failed");
@@ -186,6 +189,9 @@ int maria_chk_status(HA_CHECK *param, MARIA_HA *info)
if (param->testflag & T_UPDATE_STATE)
param->warning_printed=save;
}
+
+ mysql_mutex_unlock(&share->intern_lock);
+
if (share->state.create_trid > param->max_trid)
{
param->wrong_trd_printed= 1; /* Force should run zerofill */
@@ -6435,7 +6441,7 @@ static ha_checksum maria_byte_checksum(const uchar *buf, uint length)
return crc;
}
-static my_bool maria_too_big_key_for_sort(MARIA_KEYDEF *key, ha_rows rows)
+my_bool maria_too_big_key_for_sort(MARIA_KEYDEF *key, ha_rows rows)
{
uint key_maxlength=key->maxlength;
if (key->flag & HA_FULLTEXT)
@@ -6451,38 +6457,6 @@ static my_bool maria_too_big_key_for_sort(MARIA_KEYDEF *key, ha_rows rows)
}
/*
- Deactivate all indexes that can be recreated fast.
- These include packed keys on which sorting will use more temporary
- space than the max allowed file length or for which the unpacked keys
- will take much more space than packed keys.
- Note that 'rows' may be zero for the case when we don't know how many
- rows we will put into the file.
- */
-
-void maria_disable_indexes_for_rebuild(MARIA_HA *info, ha_rows rows,
- my_bool all_keys)
-{
- MARIA_SHARE *share= info->s;
- MARIA_KEYDEF *key=share->keyinfo;
- uint i;
-
- DBUG_ASSERT(share->state.state.records == 0 &&
- (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES));
- for (i=0 ; i < share->base.keys ; i++,key++)
- {
- if (!(key->flag & (HA_SPATIAL | HA_AUTO_KEY | HA_RTREE_INDEX)) &&
- ! maria_too_big_key_for_sort(key,rows) && share->base.auto_key != i+1 &&
- (all_keys || !(key->flag & HA_NOSAME)))
- {
- maria_clear_key_active(share->state.key_map, i);
- info->update|= HA_STATE_CHANGED;
- info->create_unique_index_by_sort= all_keys;
- }
- }
-}
-
-
-/*
Return TRUE if we can use repair by sorting
One can set the force argument to force to use sorting
even if the temporary file would be quite big!
diff --git a/storage/maria/ma_checkpoint.h b/storage/maria/ma_checkpoint.h
index b306268ba5a..c719c3cfff7 100644
--- a/storage/maria/ma_checkpoint.h
+++ b/storage/maria/ma_checkpoint.h
@@ -84,8 +84,8 @@ static inline LSN lsn_read_non_atomic_32(const volatile LSN *x)
prints a message from a task not connected to any user (checkpoint
and recovery for example).
- @param level 0 if error, ME_JUST_WARNING if warning,
- ME_JUST_INFO if info
+ @param level 0 if error, ME_WARNING if warning,
+ ME_NOTE if info
@param sentence text to write
*/
#define ma_message_no_user(level, sentence) \
diff --git a/storage/maria/ma_control_file.c b/storage/maria/ma_control_file.c
index 423497c3aeb..d619a58ff29 100644
--- a/storage/maria/ma_control_file.c
+++ b/storage/maria/ma_control_file.c
@@ -531,7 +531,7 @@ int ma_control_file_write_and_force(LSN last_checkpoint_lsn_arg,
"Control file must be from a newer version; zero-ing out %u"
" unknown bytes in control file at offset %u", zeroed,
cf_changeable_size + cf_create_time_size);
- ma_message_no_user(ME_JUST_WARNING, msg);
+ ma_message_no_user(ME_WARNING, msg);
}
else
{
@@ -608,4 +608,124 @@ my_bool ma_control_file_inited(void)
return (control_file_fd >= 0);
}
+/**
+ Print content of aria_log_control file
+*/
+
+my_bool print_aria_log_control()
+{
+ uchar buffer[CF_MAX_SIZE];
+ char name[FN_REFLEN], uuid_str[MY_UUID_STRING_LENGTH+1];
+ const char *errmsg;
+ uint new_cf_create_time_size, new_cf_changeable_size;
+ my_off_t file_size;
+ ulong logno;
+ ulonglong trid,checkpoint_lsn;
+ int open_flags= O_BINARY | /*O_DIRECT |*/ O_RDWR | O_CLOEXEC;
+ int error= CONTROL_FILE_UNKNOWN_ERROR;
+ uint recovery_fails;
+ File file;
+ DBUG_ENTER("ma_control_file_open");
+
+ if (fn_format(name, CONTROL_FILE_BASE_NAME,
+ maria_data_root, "", MYF(MY_WME)) == NullS)
+ DBUG_RETURN(CONTROL_FILE_UNKNOWN_ERROR);
+
+ if ((file= mysql_file_open(key_file_control, name,
+ open_flags, MYF(MY_WME))) < 0)
+ {
+ errmsg= "Can't open file";
+ goto err;
+ }
+
+ file_size= mysql_file_seek(file, 0, SEEK_END, MYF(MY_WME));
+ if (file_size == MY_FILEPOS_ERROR)
+ {
+ errmsg= "Can't read size";
+ goto err;
+ }
+ if (file_size < CF_MIN_SIZE)
+ {
+ /*
+ Given that normally we write only a sector and it's atomic, the only
+ possibility for a file to be of too short size is if we crashed at the
+ very first startup, between file creation and file write. Quite unlikely
+ (and can be made even more unlikely by doing this: create a temp file,
+ write it, and then rename it to be the control file).
+ What's more likely is if someone forgot to restore the control file,
+ just did a "touch control" to try to get Maria to start, or if the
+ disk/filesystem has a problem.
+ So let's be rigid.
+ */
+ error= CONTROL_FILE_TOO_SMALL;
+ errmsg= "Size of control file is smaller than expected";
+ goto err;
+ }
+
+ /* Check if control file is unexpectedly big */
+ if (file_size > CF_MAX_SIZE)
+ {
+ error= CONTROL_FILE_TOO_BIG;
+ errmsg= "File size bigger than expected";
+ goto err;
+ }
+
+ if (mysql_file_pread(file, buffer, (size_t)file_size, 0, MYF(MY_FNABP)))
+ {
+ errmsg= "Can't read file";
+ goto err;
+ }
+
+ if (memcmp(buffer + CF_MAGIC_STRING_OFFSET,
+ CF_MAGIC_STRING, CF_MAGIC_STRING_SIZE))
+ {
+ error= CONTROL_FILE_BAD_MAGIC_STRING;
+ errmsg= "Missing valid id at start of file. File is not a valid aria control file";
+ goto err;
+ }
+
+ printf("Aria file version: %u\n", buffer[CF_VERSION_OFFSET]);
+
+ new_cf_create_time_size= uint2korr(buffer + CF_CREATE_TIME_SIZE_OFFSET);
+ new_cf_changeable_size= uint2korr(buffer + CF_CHANGEABLE_SIZE_OFFSET);
+
+ if (new_cf_create_time_size < CF_MIN_CREATE_TIME_TOTAL_SIZE ||
+ new_cf_changeable_size < CF_MIN_CHANGEABLE_TOTAL_SIZE ||
+ new_cf_create_time_size + new_cf_changeable_size != file_size)
+ {
+ error= CONTROL_FILE_INCONSISTENT_INFORMATION;
+ errmsg= "Sizes stored in control file are inconsistent";
+ goto err;
+ }
+ checkpoint_lsn= lsn_korr(buffer + new_cf_create_time_size +
+ CF_LSN_OFFSET);
+ logno= uint4korr(buffer + new_cf_create_time_size + CF_FILENO_OFFSET);
+ my_uuid2str(buffer + CF_UUID_OFFSET, uuid_str);
+ uuid_str[MY_UUID_STRING_LENGTH]= 0;
+
+ printf("Block size: %u\n", uint2korr(buffer + CF_BLOCKSIZE_OFFSET));
+ printf("maria_uuid: %s\n", uuid_str);
+ printf("last_checkpoint_lsn: " LSN_FMT "\n", LSN_IN_PARTS(checkpoint_lsn));
+ printf("last_log_number: %lu\n", (ulong) logno);
+ if (new_cf_changeable_size >= (CF_MAX_TRID_OFFSET + CF_MAX_TRID_SIZE))
+ {
+ trid= transid_korr(buffer + new_cf_create_time_size + CF_MAX_TRID_OFFSET);
+ printf("trid: %llu\n", (ulonglong) trid);
+ }
+ if (new_cf_changeable_size >= (CF_RECOV_FAIL_OFFSET + CF_RECOV_FAIL_SIZE))
+ {
+ recovery_fails=
+ (buffer + new_cf_create_time_size + CF_RECOV_FAIL_OFFSET)[0];
+ printf("recovery_failuers: %u\n", recovery_fails);
+ }
+
+ DBUG_RETURN(0);
+
+err:
+ my_printf_error(HA_ERR_INITIALIZATION,
+ "Got error '%s' when trying to use aria control file "
+ "'%s'", 0, errmsg, name);
+ DBUG_RETURN(error);
+}
+
#endif /* EXTRACT_DEFINITIONS */
diff --git a/storage/maria/ma_control_file.h b/storage/maria/ma_control_file.h
index 6bc3faca959..535b0c71e64 100644
--- a/storage/maria/ma_control_file.h
+++ b/storage/maria/ma_control_file.h
@@ -70,5 +70,6 @@ int ma_control_file_write_and_force(LSN last_checkpoint_lsn_arg,
uint8 recovery_failures_arg);
int ma_control_file_end(void);
my_bool ma_control_file_inited(void);
+my_bool print_aria_log_control(void);
C_MODE_END
#endif
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 0e5de2f8b89..93d65bf3a7d 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -827,6 +827,11 @@ int maria_create(const char *name, enum data_file_type datafile_type,
*/
share.state.skip_redo_lsn= share.state.is_of_horizon=
share.state.create_rename_lsn= LSN_MAX;
+ /*
+ We have to mark the table as not movable as the table will contain the
+ maria_uuid and create_rename_lsn
+ */
+ share.state.changed|= STATE_NOT_MOVABLE;
}
if (datafile_type == DYNAMIC_RECORD)
@@ -1446,6 +1451,7 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid,
uchar buf[LSN_STORE_SIZE * 3], *ptr;
uchar trid_buff[8];
File file= share->kfile.file;
+ DBUG_ENTER("_ma_update_state_lsns_sub");
DBUG_ASSERT(file >= 0);
if (lsn == LSN_IMPOSSIBLE)
@@ -1464,7 +1470,7 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid,
0].length,
sizeof(log_array)/sizeof(log_array[0]),
log_array, NULL, NULL)))
- return res;
+ DBUG_RETURN(res);
}
for (ptr= buf; ptr < (buf + sizeof(buf)); ptr+= LSN_STORE_SIZE)
@@ -1497,13 +1503,13 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid,
}
else
lsn_store(buf, share->state.create_rename_lsn);
- return (my_pwrite(file, buf, sizeof(buf),
- sizeof(share->state.header) +
- MARIA_FILE_CREATE_RENAME_LSN_OFFSET, MYF(MY_NABP)) ||
- my_pwrite(file, trid_buff, sizeof(trid_buff),
- sizeof(share->state.header) +
- MARIA_FILE_CREATE_TRID_OFFSET, MYF(MY_NABP)) ||
- (do_sync && mysql_file_sync(file, MYF(0))));
+ DBUG_RETURN(my_pwrite(file, buf, sizeof(buf),
+ sizeof(share->state.header) +
+ MARIA_FILE_CREATE_RENAME_LSN_OFFSET, MYF(MY_NABP)) ||
+ my_pwrite(file, trid_buff, sizeof(trid_buff),
+ sizeof(share->state.header) +
+ MARIA_FILE_CREATE_TRID_OFFSET, MYF(MY_NABP)) ||
+ (do_sync && mysql_file_sync(file, MYF(0))));
}
#if defined(_MSC_VER) && (_MSC_VER == 1310)
#pragma optimize("",on)
diff --git a/storage/maria/ma_crypt.c b/storage/maria/ma_crypt.c
index 79e41f979ec..95b84d38221 100644
--- a/storage/maria/ma_crypt.c
+++ b/storage/maria/ma_crypt.c
@@ -156,7 +156,7 @@ ma_crypt_read(MARIA_SHARE* share, uchar *buff)
{
my_printf_error(HA_ERR_UNSUPPORTED,
"Unsupported crypt scheme! type: %d iv_length: %d\n",
- MYF(ME_FATALERROR|ME_NOREFRESH),
+ MYF(ME_FATAL|ME_ERROR_LOG),
type, iv_length);
return 0;
}
@@ -464,7 +464,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data,
my_errno= HA_ERR_DECRYPTION_FAILED;
my_printf_error(HA_ERR_DECRYPTION_FAILED,
"Unknown key id %u. Can't continue!",
- MYF(ME_FATALERROR|ME_NOREFRESH),
+ MYF(ME_FATAL|ME_ERROR_LOG),
crypt_data->scheme.key_id);
return 1;
}
@@ -481,7 +481,7 @@ static int ma_encrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data,
my_errno= HA_ERR_DECRYPTION_FAILED;
my_printf_error(HA_ERR_DECRYPTION_FAILED,
"failed to encrypt '%s' rc: %d dstlen: %u size: %u\n",
- MYF(ME_FATALERROR|ME_NOREFRESH),
+ MYF(ME_FATAL|ME_ERROR_LOG),
share->open_file_name.str, rc, dstlen, size);
return 1;
}
@@ -508,7 +508,7 @@ static int ma_decrypt(MARIA_SHARE *share, MARIA_CRYPT_DATA *crypt_data,
my_errno= HA_ERR_DECRYPTION_FAILED;
my_printf_error(HA_ERR_DECRYPTION_FAILED,
"failed to decrypt '%s' rc: %d dstlen: %u size: %u\n",
- MYF(ME_FATALERROR|ME_NOREFRESH),
+ MYF(ME_FATAL|ME_ERROR_LOG),
share->open_file_name.str, rc, dstlen, size);
return 1;
}
diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
index c2ac4d588a9..b464cf4f94e 100644
--- a/storage/maria/ma_extra.c
+++ b/storage/maria/ma_extra.c
@@ -418,7 +418,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
error= _ma_flush_table_files(info, MARIA_FLUSH_DATA | MARIA_FLUSH_INDEX,
FLUSH_KEEP, FLUSH_KEEP);
+ mysql_mutex_lock(&share->intern_lock);
+ /* Tell maria_lock_database() that we locked the intern_lock mutex */
+ info->intern_lock_locked= 1;
_ma_decrement_open_count(info, 1);
+ info->intern_lock_locked= 0;
if (share->not_flushed)
{
share->not_flushed= 0;
@@ -431,6 +435,7 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
_ma_set_fatal_error(share, HA_ERR_CRASHED);
}
}
+ mysql_mutex_unlock(&share->intern_lock);
break;
case HA_EXTRA_NORMAL: /* Theese isn't in use */
info->quick_mode= 0;
diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c
index 01ae4f56efd..6d40f804880 100644
--- a/storage/maria/ma_info.c
+++ b/storage/maria/ma_info.c
@@ -148,6 +148,6 @@ void _ma_report_error(int errcode, const LEX_STRING *name)
}
}
- my_error(errcode, MYF(ME_NOREFRESH), file_name);
+ my_error(errcode, MYF(ME_ERROR_LOG), file_name);
DBUG_VOID_RETURN;
}
diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c
index e3d55cdb1ec..12d39db806a 100644
--- a/storage/maria/ma_init.c
+++ b/storage/maria/ma_init.c
@@ -148,7 +148,7 @@ my_bool maria_upgrade()
my_message(HA_ERR_INITIALIZATION,
"Found old style Maria log files; "
"Converting them to Aria names",
- MYF(ME_JUST_INFO));
+ MYF(ME_NOTE));
for (i= 0; i < dir->number_of_files; i++)
{
diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c
index a8cf936c873..200a728626f 100644
--- a/storage/maria/ma_locking.c
+++ b/storage/maria/ma_locking.c
@@ -47,7 +47,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
}
error=0;
- mysql_mutex_lock(&share->intern_lock);
+ if (!info->intern_lock_locked)
+ mysql_mutex_lock(&share->intern_lock);
if (share->kfile.file >= 0) /* May only be false on windows */
{
switch (lock_type) {
@@ -234,7 +235,8 @@ int maria_lock_database(MARIA_HA *info, int lock_type)
}
}
#endif
- mysql_mutex_unlock(&share->intern_lock);
+ if (!info->intern_lock_locked)
+ mysql_mutex_unlock(&share->intern_lock);
DBUG_RETURN(error);
} /* maria_lock_database */
@@ -454,7 +456,7 @@ int _ma_mark_file_changed_now(register MARIA_SHARE *share)
}
/* Set uuid of file if not yet set (zerofilled file) */
if (share->base.born_transactional &&
- !(share->state.changed & STATE_NOT_MOVABLE))
+ !(share->state.org_changed & STATE_NOT_MOVABLE))
{
/* Lock table to current installation */
if (_ma_set_uuid(share, 0) ||
@@ -464,6 +466,7 @@ int _ma_mark_file_changed_now(register MARIA_SHARE *share)
TRUE, TRUE)))
goto err;
share->state.changed|= STATE_NOT_MOVABLE;
+ share->state.org_changed|= STATE_NOT_MOVABLE;
}
}
error= 0;
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index f6a2919ddf5..d943666065a 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -60,6 +60,8 @@ static mysql_cond_t COND_soft_sync;
static MA_SERVICE_THREAD_CONTROL soft_sync_control=
{0, FALSE, FALSE, &LOCK_soft_sync, &COND_soft_sync};
+uint log_purge_disabled= 0;
+
/* transaction log file descriptor */
typedef struct st_translog_file
@@ -468,7 +470,6 @@ static ulonglong flush_start= 0;
#define TRANSLOG_CLSN_LEN_BITS 0xC0 /* Mask to get compressed LSN length */
-#include <my_atomic.h>
/* an array that maps id of a MARIA_SHARE to this MARIA_SHARE */
static MARIA_SHARE **id_to_share= NULL;
@@ -3624,6 +3625,7 @@ my_bool translog_init_with_table(const char *directory,
translog_syncs= 0;
flush_start= 0;
id_to_share= NULL;
+ log_purge_disabled= 0;
log_descriptor.directory_fd= -1;
log_descriptor.is_everything_flushed= 1;
@@ -8707,7 +8709,7 @@ my_bool translog_purge(TRANSLOG_ADDRESS low)
mysql_rwlock_unlock(&log_descriptor.open_files_lock);
translog_close_log_file(file);
}
- if (log_purge_type == TRANSLOG_PURGE_IMMIDIATE)
+ if (log_purge_type == TRANSLOG_PURGE_IMMIDIATE && ! log_purge_disabled)
{
char path[FN_REFLEN], *file_name;
file_name= translog_filename_by_fileno(i, path);
@@ -8760,7 +8762,7 @@ my_bool translog_purge_at_flush()
mysql_mutex_lock(&log_descriptor.purger_lock);
- if (unlikely(log_descriptor.min_need_file == 0))
+ if (unlikely(log_descriptor.min_need_file == 0 || log_purge_disabled))
{
DBUG_PRINT("info", ("No info about min need file => exit"));
mysql_mutex_unlock(&log_descriptor.purger_lock);
@@ -9324,3 +9326,22 @@ void dump_page(uchar *buffer, File handler)
}
dump_datapage(buffer, handler);
}
+
+
+/*
+ Handle backup calls
+*/
+
+void translog_disable_purge()
+{
+ mysql_mutex_lock(&log_descriptor.purger_lock);
+ log_purge_disabled++;
+ mysql_mutex_unlock(&log_descriptor.purger_lock);
+}
+
+void translog_enable_purge()
+{
+ mysql_mutex_lock(&log_descriptor.purger_lock);
+ log_purge_disabled--;
+ mysql_mutex_unlock(&log_descriptor.purger_lock);
+}
diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h
index b236fdc7ebe..3e5c58a8053 100644
--- a/storage/maria/ma_loghandler.h
+++ b/storage/maria/ma_loghandler.h
@@ -367,6 +367,8 @@ extern void dump_page(uchar *buffer, File handler);
extern my_bool translog_log_debug_info(TRN *trn,
enum translog_debug_info_type type,
uchar *info, size_t length);
+extern void translog_disable_purge(void);
+extern void translog_enable_purge(void);
enum enum_translog_status
{
@@ -522,6 +524,7 @@ typedef enum
} enum_maria_translog_purge_type;
extern ulong log_purge_type;
extern ulong log_file_size;
+extern uint log_purge_disabled; /* For backup */
typedef enum
{
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index 226ebe8c1dd..05aca8f37e1 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -440,6 +440,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->state.state_length=base_pos;
/* For newly opened tables we reset the error-has-been-printed flag */
share->state.changed&= ~STATE_CRASHED_PRINTED;
+ share->state.org_changed= share->state.changed;
if (!(open_flags & HA_OPEN_FOR_REPAIR) &&
((share->state.changed & STATE_CRASHED_FLAGS) ||
@@ -460,13 +461,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
/*
A transactional table is not usable on this system if:
- share->state.create_trid > trnman_get_max_trid()
- - Critical as trid as stored releativel to create_trid.
+ - Critical as trid as stored releative to create_trid.
- uuid is different
STATE_NOT_MOVABLE is reset when a table is zerofilled
(has no LSN's and no trids)
- We can ignore testing uuid if STATE_NOT_MOVABLE is set, as in this
+ We can ignore testing uuid if STATE_NOT_MOVABLE is not set, as in this
case the uuid will be set in _ma_mark_file_changed().
*/
if (share->base.born_transactional &&
@@ -787,17 +788,27 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->state.is_of_horizon) > 0) ||
!LSN_VALID(share->state.skip_redo_lsn) ||
(cmp_translog_addr(share->state.create_rename_lsn,
- share->state.skip_redo_lsn) > 0)) &&
- !(open_flags & HA_OPEN_FOR_REPAIR))
+ share->state.skip_redo_lsn) > 0)))
{
- /*
- If in Recovery, it will not work. If LSN is invalid and not
- LSN_NEEDS_NEW_STATE_LSNS, header must be corrupted.
- In both cases, must repair.
- */
- my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
- HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
- goto err;
+ if (!(open_flags & HA_OPEN_FOR_REPAIR))
+ {
+ /*
+ If in Recovery, it will not work. If LSN is invalid and not
+ LSN_NEEDS_NEW_STATE_LSNS, header must be corrupted.
+ In both cases, must repair.
+ */
+ my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
+ HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
+ goto err;
+ }
+ else
+ {
+ /*
+ Open in repair mode. Ensure that we mark the table crashed, so
+ that we run auto_repair on it
+ */
+ maria_mark_crashed_share(share);
+ }
}
else if (!(open_flags & HA_OPEN_FOR_REPAIR))
{
diff --git a/storage/maria/ma_pagecrc.c b/storage/maria/ma_pagecrc.c
index e0fee185980..b729d51cc33 100644
--- a/storage/maria/ma_pagecrc.c
+++ b/storage/maria/ma_pagecrc.c
@@ -54,11 +54,11 @@ static uint32 maria_page_crc(uint32 start, uchar *data, uint length)
@retval 1 Error
*/
-static my_bool maria_page_crc_check(uchar *page,
- pgcache_page_no_t page_no,
- MARIA_SHARE *share,
- uint32 no_crc_val,
- int data_length)
+my_bool maria_page_crc_check(uchar *page,
+ pgcache_page_no_t page_no,
+ MARIA_SHARE *share,
+ uint32 no_crc_val,
+ int data_length)
{
uint32 crc= uint4korr(page + share->block_size - CRC_SIZE), new_crc;
my_bool res;
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index f14bab970a9..27c941705b7 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -183,7 +183,7 @@ void maria_recover_error_handler_hook(uint error, const char *str,
static void print_preamble()
{
- ma_message_no_user(ME_JUST_INFO, "starting recovery");
+ ma_message_no_user(ME_NOTE, "starting recovery");
}
@@ -523,7 +523,7 @@ end:
}
if (!error)
{
- ma_message_no_user(ME_JUST_INFO, "recovery done");
+ ma_message_no_user(ME_NOTE, "recovery done");
maria_recovery_changed_data= 1;
}
}
@@ -1372,6 +1372,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
silently pass in the "info == NULL" test below.
*/
tprint(tracef, ", record is corrupted");
+ eprint(tracef, "\n***WARNING: %s may be corrupted", name ? name : "NULL");
info= NULL;
recovery_warnings++;
goto end;
@@ -1384,7 +1385,11 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
" or its header is so corrupted that we cannot open it;"
" we skip it");
if (my_errno != ENOENT)
+ {
recovery_found_crashed_tables++;
+ eprint(tracef, "\n***WARNING: %s could not be opened: Error: %d",
+ name ? name : "NULL", (int) my_errno);
+ }
error= 0;
goto end;
}
@@ -1413,6 +1418,7 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
not transactional table
*/
tprint(tracef, ", is not transactional. Ignoring open request");
+ eprint(tracef, "\n***WARNING: '%s' may be crashed", name);
error= -1;
recovery_warnings++;
goto end;
@@ -1459,6 +1465,8 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
(kfile_len == MY_FILEPOS_ERROR))
{
tprint(tracef, ", length unknown\n");
+ eprint(tracef, "\n***WARNING: Can't read length of file '%s'",
+ share->open_file_name.str);
recovery_warnings++;
goto end;
}
@@ -3589,7 +3597,12 @@ void _ma_tmp_disable_logging_for_table(MARIA_HA *info,
should be now. info->trn may be NULL in maria_chk.
*/
if (info->trn == NULL)
+ {
info->trn= &dummy_transaction_object;
+ info->trn_next= 0;
+ info->trn_prev= 0;
+ }
+
DBUG_ASSERT(info->trn->rec_lsn == LSN_IMPOSSIBLE);
share->page_type= PAGECACHE_PLAIN_PAGE;
/* Functions below will pick up now_transactional and change callbacks */
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index e68d099576d..4dc6472bd15 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -30,13 +30,11 @@
/* static variables */
#undef MIN_SORT_MEMORY
-#undef MYF_RW
#undef DISK_BUFFER_SIZE
#define MERGEBUFF 15
#define MERGEBUFF2 31
#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
-#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
#define DISK_BUFFER_SIZE (IO_SIZE*128)
/* How many keys we can keep in memory */
diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c
index 2514e74ec34..2eff64ec7cd 100644
--- a/storage/maria/ma_state.c
+++ b/storage/maria/ma_state.c
@@ -30,6 +30,7 @@
#include "maria_def.h"
#include "trnman.h"
+#include "ma_trnman.h"
#include "ma_blockrec.h"
/**
@@ -571,8 +572,6 @@ void _ma_remove_table_from_trnman(MARIA_HA *info)
MARIA_SHARE *share= info->s;
TRN *trn= info->trn;
MARIA_USED_TABLES *tables, **prev;
- MARIA_HA *handler, **prev_file;
- uint unlinked= 0;
DBUG_ENTER("_ma_remove_table_from_trnman");
DBUG_PRINT("enter", ("trn: %p used_tables: %p share: %p in_trans: %d",
trn, trn->used_tables, share, share->in_trans));
@@ -604,29 +603,9 @@ void _ma_remove_table_from_trnman(MARIA_HA *info)
DBUG_PRINT("warning", ("share: %p where not in used_tables_list", share));
}
- /* unlink all instances of the table from used_instances */
- prev_file= (MARIA_HA**) &trn->used_instances;
- while ((handler= *prev_file))
- {
- if (handler->s == share)
- {
- unlinked++;
- *prev_file= handler->trn_next; /* Remove instance */
- }
- else
- prev_file= &handler->trn_next; /* Continue with next instance */
- }
+ /* Reset trn and remove table from used_instances */
+ _ma_reset_trn_for_table(info);
- DBUG_PRINT("note", ("unlinked tables: %u", unlinked));
- if (!unlinked)
- {
- /*
- This can only happens in case of rename of intermediate table as
- part of alter table
- */
- DBUG_PRINT("warning", ("table: %p where not in used_instances", info));
- }
- info->trn= 0; /* Not part of trans anymore */
DBUG_VOID_RETURN;
}
diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c
index c7143d141b8..6a25ac8a363 100644
--- a/storage/maria/ma_test2.c
+++ b/storage/maria/ma_test2.c
@@ -1086,6 +1086,11 @@ static void get_options(int argc, char **argv)
fprintf(stderr,"record count must be >= 10 (if testflag > 2)\n");
exit(1);
}
+ if (recant <= 1)
+ {
+ fprintf(stderr,"record count must be >= 2\n");
+ exit(1);
+ }
break;
case 'e': /* maria_block_length */
case 'E':
diff --git a/storage/maria/ma_trnman.h b/storage/maria/ma_trnman.h
index 06e6a88304f..87e34e9da0b 100644
--- a/storage/maria/ma_trnman.h
+++ b/storage/maria/ma_trnman.h
@@ -18,7 +18,7 @@
/**
Sets table's trn and prints debug information
- Links table into used_instances if new_trn is not 0
+ Links table into new_trn->used_instances
@param tbl MARIA_HA of table
@param newtrn what to put into tbl->trn
@@ -34,7 +34,10 @@ static inline void _ma_set_trn_for_table(MARIA_HA *tbl, TRN *newtrn)
tbl->trn= newtrn;
/* Link into used list */
+ if (newtrn->used_instances)
+ ((MARIA_HA*) newtrn->used_instances)->trn_prev= &tbl->trn_next;
tbl->trn_next= (MARIA_HA*) newtrn->used_instances;
+ tbl->trn_prev= (MARIA_HA**) &newtrn->used_instances;
newtrn->used_instances= tbl;
}
@@ -49,6 +52,8 @@ static inline void _ma_set_tmp_trn_for_table(MARIA_HA *tbl, TRN *newtrn)
DBUG_PRINT("info",("table: %p trn: %p -> %p",
tbl, tbl->trn, newtrn));
tbl->trn= newtrn;
+ tbl->trn_prev= 0;
+ tbl->trn_next= 0; /* To avoid assert in ha_maria::close() */
}
@@ -59,7 +64,36 @@ static inline void _ma_set_tmp_trn_for_table(MARIA_HA *tbl, TRN *newtrn)
static inline void _ma_reset_trn_for_table(MARIA_HA *tbl)
{
DBUG_PRINT("info",("table: %p trn: %p -> NULL", tbl, tbl->trn));
+
+ /* The following is only false if tbl->trn == &dummy_transaction_object */
+ if (tbl->trn_prev)
+ {
+ if (tbl->trn_next)
+ tbl->trn_next->trn_prev= tbl->trn_prev;
+ *tbl->trn_prev= tbl->trn_next;
+ tbl->trn_prev= 0;
+ tbl->trn_next= 0;
+ }
tbl->trn= 0;
}
+
+/*
+ Take over the used_instances link from a trn object
+ Reset the link in the trn object
+*/
+
+static inline void relink_trn_used_instances(MARIA_HA **used_tables, TRN *trn)
+{
+ if (likely(*used_tables= (MARIA_HA*) trn->used_instances))
+ {
+ /* Check that first back link is correct */
+ DBUG_ASSERT((*used_tables)->trn_prev == (MARIA_HA **)&trn->used_instances);
+
+ /* Fix back link to point to new base for the list */
+ (*used_tables)->trn_prev= used_tables;
+ trn->used_instances= 0;
+ }
+}
+
#endif /* _ma_trnman_h */
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index faf47929973..07be8333794 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -83,7 +83,7 @@ my_bool _ma_write_abort_default(MARIA_HA *info __attribute__((unused)))
/* Write new record to a table */
-int maria_write(MARIA_HA *info, uchar *record)
+int maria_write(MARIA_HA *info, const uchar *record)
{
MARIA_SHARE *share= info->s;
uint i;
diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
index 85cdaa06701..2f130de1c7a 100644
--- a/storage/maria/maria_chk.c
+++ b/storage/maria/maria_chk.c
@@ -487,7 +487,7 @@ static void usage(void)
--ignore-control-file Don't open the control file. Only use this if you\n\
are sure the tables are not in use by another\n\
program!\n\
- --require-control-file Abort if we can't find/read the maria_log_control\n\
+ --require-control-file Abort if we can't find/read the aria_log_control\n\
file\n\
-s, --silent Only print errors. One can use two -s to make\n\
maria_chk very silent.\n\
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index 919dc831c75..3c0574fd783 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -177,6 +177,7 @@ typedef struct st_maria_state_info
uint sortkey; /* sorted by this key (not used) */
uint open_count;
uint changed; /* Changed since maria_chk */
+ uint org_changed; /* Changed since open */
/**
Birthday of the table: no record in the log before this LSN should ever
be applied to the table. Updated when created, renamed, explicitly
@@ -605,7 +606,7 @@ struct st_maria_handler
{
MARIA_SHARE *s; /* Shared between open:s */
struct st_ma_transaction *trn; /* Pointer to active transaction */
- struct st_maria_handler *trn_next;
+ struct st_maria_handler *trn_next,**trn_prev;
MARIA_STATUS_INFO *state, state_save;
MARIA_STATUS_INFO *state_start; /* State at start of transaction */
MARIA_USED_TABLES *used_tables;
@@ -690,6 +691,7 @@ struct st_maria_handler
uint16 last_used_keyseg; /* For MARIAMRG */
uint8 key_del_used; /* != 0 if key_del is used */
my_bool was_locked; /* Was locked in panic */
+ my_bool intern_lock_locked; /* locked in ma_extra() */
my_bool append_insert_at_end; /* Set if concurrent insert */
my_bool quick_mode;
my_bool in_check_table; /* We are running check tables */
@@ -1418,6 +1420,9 @@ extern my_bool maria_page_crc_check_bitmap(int, PAGECACHE_IO_HOOK_ARGS *args);
extern my_bool maria_page_crc_check_data(int, PAGECACHE_IO_HOOK_ARGS *args);
extern my_bool maria_page_crc_check_index(int, PAGECACHE_IO_HOOK_ARGS *args);
extern my_bool maria_page_crc_check_none(int, PAGECACHE_IO_HOOK_ARGS *args);
+extern my_bool maria_page_crc_check(uchar *page, pgcache_page_no_t page_no,
+ MARIA_SHARE *share, uint32 no_crc_val,
+ int data_length);
extern my_bool maria_page_filler_set_bitmap(PAGECACHE_IO_HOOK_ARGS *args);
extern my_bool maria_page_filler_set_normal(PAGECACHE_IO_HOOK_ARGS *args);
extern my_bool maria_page_filler_set_none(PAGECACHE_IO_HOOK_ARGS *args);
diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
index 3e9d002ea43..24438f49c41 100644
--- a/storage/maria/maria_pack.c
+++ b/storage/maria/maria_pack.c
@@ -20,6 +20,8 @@
#endif
#include "maria_def.h"
+#include "trnman_public.h"
+#include "trnman.h"
#include <queues.h>
#include <my_tree.h>
#include "mysys_err.h"
@@ -30,13 +32,16 @@
#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
#endif
#include <my_getopt.h>
-#include <assert.h>
+#include <my_handler_errors.h>
#if SIZEOF_LONG_LONG > 4
#define BITS_SAVED 64
#else
#define BITS_SAVED 32
#endif
+#ifndef MAX_INTERNAL_TRID
+#define MAX_INTERNAL_TRID 0xffffffffffffLL
+#endif
#define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */
#define HEAD_LENGTH 32
@@ -178,11 +183,6 @@ static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count);
static int fakecmp(my_off_t **count1, my_off_t **count2);
#endif
-
-static int error_on_write=0,test_only=0,verbose=0,silent=0,
- write_loop=0,force_pack=0, isamchk_neaded=0;
-static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
-static my_bool backup, opt_wait;
/*
tree_buff_length is somewhat arbitrary. The bigger it is the better
the chance to win in terms of compression factor. On the other hand,
@@ -190,6 +190,12 @@ static my_bool backup, opt_wait;
is coded with 16 bits in the header. Hence the limit is 2**16 - 1.
*/
static uint tree_buff_length= 65536 - MALLOC_OVERHEAD;
+
+static int error_on_write=0,test_only=0,verbose=0,silent=0,
+ write_loop=0,force_pack=0, isamchk_neaded=0;
+static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
+static my_bool backup, opt_wait;
+static my_bool opt_ignore_control_file, opt_require_control_file;
static char tmp_dir[FN_REFLEN]={0},*join_table;
static my_off_t intervall_length;
static ha_checksum glob_crc;
@@ -199,19 +205,52 @@ static HUFF_COUNTS *global_count;
static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static const char *load_default_groups[]= { "ariapack",0 };
- /* The main program */
+/*
+ Register handler error messages for usage with my_error()
+
+ NOTES
+ This is safe to call multiple times as my_error_register()
+ will ignore calls to register already registered error numbers.
+*/
+
+static const char **get_handler_error_messages(int e __attribute__((unused)))
+{
+ return handler_error_messages;
+}
+
+
+/* The main program */
int main(int argc, char **argv)
{
int error,ok;
PACK_MRG_INFO merge;
char **default_argv;
+ my_bool no_control_file= 0;
MY_INIT(argv[0]);
+ maria_data_root= (char *)".";
load_defaults_or_exit("my", load_default_groups, &argc, &argv);
default_argv= argv;
get_options(&argc,&argv);
+ my_error_register(get_handler_error_messages, HA_ERR_FIRST,
+ HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
+
+ if (!opt_ignore_control_file &&
+ (no_control_file= ma_control_file_open(FALSE,
+ (opt_require_control_file ||
+ !silent))) &&
+ opt_require_control_file)
+ {
+ error= 1;
+ goto end;
+ }
maria_init();
+ if (no_control_file || force_pack)
+ {
+ /* Assume that all rows exists */
+ trnman_init(MAX_INTERNAL_TRID-16);
+ }
error=ok=isamchk_neaded=0;
if (join_table)
@@ -239,9 +278,13 @@ int main(int argc, char **argv)
}
if (ok && isamchk_neaded && !silent)
puts("Remember to run aria_chk -rq on compressed tables");
+
+end:
fflush(stdout);
fflush(stderr);
free_defaults(default_argv);
+ my_error_unregister(HA_ERR_FIRST,
+ HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
maria_end();
my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
exit(error ? 2 : 0);
@@ -263,17 +306,29 @@ static struct my_option my_long_options[] =
{"character-sets-dir", OPT_CHARSETS_DIR_MP,
"Directory where character sets are.", (char**) &charsets_dir,
(char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"datadir", 'h',
+ "Path for control file (and logs if --logdir not used).",
+ &maria_data_root, 0, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f',
"Force packing of table even if it gets bigger or if tempfile exists.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ { "ignore-control-file", 0,
+ "Ignore the control file",
+ (uchar**)&opt_ignore_control_file, 0, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"join", 'j',
"Join all given tables into 'new_table_name'. All tables MUST have identical layouts.",
&join_table, &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
0, 0, 0},
{"help", '?', "Display this help and exit.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ { "require-control-file", 0,
+ "Abort if cannot find control file",
+ (uchar**)&opt_require_control_file, 0, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"silent", 's', "Be more silent.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"tmpdir", 'T', "Use temporary directory to store temporary table.",
@@ -396,6 +451,47 @@ static void get_options(int *argc,char ***argv)
}
+static void print_error(int error, const char *filename)
+{
+ switch (error) {
+ case HA_ERR_CRASHED:
+ fprintf(stderr, "'%s' doesn't have a correct index definition. You need to recreate it before you can do a repair",filename);
+ break;
+ case HA_ERR_NOT_A_TABLE:
+ fprintf(stderr, "'%s' is not a Aria table",filename);
+ break;
+ case HA_ERR_CRASHED_ON_USAGE:
+ fprintf(stderr, "'%s' is marked as crashed",filename);
+ break;
+ case HA_ERR_CRASHED_ON_REPAIR:
+ fprintf(stderr, "'%s' is marked as crashed after last repair",filename);
+ break;
+ case HA_ERR_OLD_FILE:
+ fprintf(stderr, "'%s' has transactions newer than registered in control file. If this is ok, please re-run with --ignore-control-file", filename);
+ break;
+ case HA_ERR_NEW_FILE:
+ fprintf(stderr, "'%s' uses new features not supported by this version of the Aria library", filename);
+ break;
+ case HA_ERR_END_OF_FILE:
+ fprintf(stderr, "Couldn't read complete header from '%s'", filename);
+ break;
+ case EAGAIN:
+ fprintf(stderr, "'%s' is locked. Use -w to wait until unlocked",filename);
+ break;
+ case ENOENT:
+ fprintf(stderr, "File '%s' doesn't exist",filename);
+ break;
+ case EACCES:
+ fprintf(stderr, "You don't have permission to use '%s'", filename);
+ break;
+ default:
+ fprintf(stderr, "%d when opening Aria table '%s'", error, filename);
+ break;
+ }
+ fputc('\n',stderr);
+}
+
+
static MARIA_HA *open_maria_file(char *name,int mode)
{
MARIA_HA *isam_file;
@@ -403,10 +499,10 @@ static MARIA_HA *open_maria_file(char *name,int mode)
DBUG_ENTER("open_maria_file");
if (!(isam_file=maria_open(name, mode, HA_OPEN_IGNORE_MOVED_STATE |
- (opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED))))
+ (opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
+ HA_OPEN_ABORT_IF_LOCKED))))
{
- fprintf(stderr, "%s gave error %d on open\n", name, my_errno);
+ print_error(my_errno, name);
DBUG_RETURN(0);
}
share=isam_file->s;
diff --git a/storage/maria/maria_read_log.c b/storage/maria/maria_read_log.c
index d9b5be30105..59d5c8abce8 100644
--- a/storage/maria/maria_read_log.c
+++ b/storage/maria/maria_read_log.c
@@ -31,6 +31,7 @@ const char *default_dbug_option= "d:t:o,/tmp/aria_read_log.trace";
#endif /* DBUG_OFF */
static my_bool opt_display_only, opt_apply, opt_apply_undo, opt_silent;
static my_bool opt_check;
+static my_bool opt_print_aria_log_control;
static const char *opt_tmpdir;
static ulong opt_translog_buffer_size;
static ulonglong opt_page_buffer_size;
@@ -59,6 +60,12 @@ int main(int argc, char **argv)
goto err;
}
maria_block_size= 0; /* Use block size from file */
+ if (opt_print_aria_log_control)
+ {
+ if (print_aria_log_control())
+ goto err;
+ goto end;
+ }
/* we don't want to create a control file, it MUST exist */
if (ma_control_file_open(FALSE, TRUE))
{
@@ -209,6 +216,10 @@ static struct my_option my_long_options[] =
&opt_page_buffer_size, &opt_page_buffer_size, 0,
GET_ULL, REQUIRED_ARG, PAGE_BUFFER_INIT,
PAGE_BUFFER_INIT, SIZE_T_MAX, MALLOC_OVERHEAD, (long) IO_SIZE, 0},
+ { "print-log-control-file", 'l',
+ "Print the content of the aria_log_control_file",
+ &opt_print_aria_log_control, &opt_print_aria_log_control, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{ "start-from-lsn", 'o', "Start reading log from this lsn",
&opt_start_from_lsn, &opt_start_from_lsn,
0, GET_ULL, REQUIRED_ARG, 0, 0, ~(longlong) 0, 0, 0, 0 },
@@ -249,7 +260,7 @@ static struct my_option my_long_options[] =
static void print_version(void)
{
- printf("%s Ver 1.3 for %s on %s\n",
+ printf("%s Ver 1.4 for %s on %s\n",
my_progname_short, SYSTEM_TYPE, MACHINE_TYPE);
}
@@ -261,7 +272,7 @@ static void usage(void)
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
puts("and you are welcome to modify and redistribute it under the GPL license\n");
- puts("Display and apply log records from a Aria transaction log");
+ puts("Display or apply log records from a Aria transaction log");
puts("found in the current directory (for now)");
#ifndef IDENTICAL_PAGES_AFTER_RECOVERY
puts("\nNote: Aria is compiled without -DIDENTICAL_PAGES_AFTER_RECOVERY\n"
@@ -269,8 +280,13 @@ static void usage(void)
"files created during normal execution. This should be ok, except for\n"
"test scripts that tries to compare files before and after recovery.");
#endif
- printf("\nUsage: %s OPTIONS\n", my_progname_short);
- puts("You need to use one of -d or -a");
+ printf("\nUsage: %s OPTIONS [-d | -a] -h `aria_log_directory`\n",
+ my_progname_short);
+ printf("or\n");
+ printf("Usage: %s OPTIONS -h `aria_log_directory` "
+ "--print-aria-log-control\n\n",
+ my_progname_short);
+
my_print_help(my_long_options);
print_defaults("my", load_default_groups);
my_print_variables(my_long_options);
@@ -339,12 +355,12 @@ static void get_options(int *argc,char ***argv)
need_help= 1;
fprintf(stderr, "Too many arguments given\n");
}
- if ((opt_display_only + opt_apply) != 1)
+ if ((opt_display_only + opt_apply + opt_print_aria_log_control) != 1)
{
need_help= 1;
fprintf(stderr,
- "You must use one and only one of the options 'display-only' or "
- "'apply'\n");
+ "You must use one and only one of the options 'display-only', \n"
+ "'print-log-control-file' and 'apply'\n");
}
if (need_help)
diff --git a/storage/maria/maria_rename.sh b/storage/maria/maria_rename.sh
deleted file mode 100755
index fb20e47e635..00000000000
--- a/storage/maria/maria_rename.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/sh
-
-replace myisam maria MYISAM MARIA MyISAM MARIA -- mysql-test/t/*maria*test mysql-test/r/*maria*result
-
-FILES=`echo sql/ha_maria.{cc,h} include/maria*h storage/maria/*.{c,h}`
-
-replace myisam maria MYISAM MARIA MyISAM MARIA myisam.h maria.h myisamdef.h maria_def.h mi_ maria_ ft_ maria_ft_ "Copyright (C) 2000" "Copyright (C) 2006" MI_ISAMINFO MARIA_INFO MI_CREATE_INFO MARIA_CREATE_INFO maria_isam_ maria_ MI_INFO MARIA_HA MI_ MARIA_ MARIACHK MARIA_CHK rt_index.h ma_rt_index.h rtree_ maria_rtree rt_key.h ma_rt_key.h rt_mbr.h ma_rt_mbr.h -- $FILES
-
-replace check_table_is_closed _ma_check_table_is_closed test_if_reopen _ma_test_if_reopen my_n_base_info_read maria_n_base_info_read update_auto_increment _ma_update_auto_increment save_pack_length _ma_save_packlength calc_pack_length _ma_calc_pack_length -- $FILES
-
-replace mi_ ma_ ft_ ma_ft_ rt_ ma_rt_ myisam maria myisamchk maria_chk myisampack maria_pack myisamlog maria_log -- storage/maria/Makefile.am
-
-#
-# Restore wrong replaces
-#
-
-replace maria_sint1korr mi_sint1korr maria_uint1korr mi_uint1korr maria_sint2korr mi_sint2korr maria_sint3korr mi_sint3korr maria_sint4korr mi_sint4korr maria_sint8korr mi_sint8korr maria_uint2korr mi_uint2korr maria_uint3korr mi_uint3korr maria_uint4korr mi_uint4korr maria_uint5korr mi_uint5korr maria_uint6korr mi_uint6korr maria_uint7korr mi_uint7korr maria_uint8korr mi_uint8korr maria_int1store mi_int1store maria_int2store mi_int2store maria_int3store mi_int3store maria_int4store mi_int4store maria_int5store mi_int5store maria_int6store mi_int6store maria_int7store mi_int7store maria_int8store mi_int8store maria_float4store mi_float4store maria_float4get mi_float4get maria_float8store mi_float8store maria_float8get mi_float8get maria_rowstore mi_rowstore maria_rowkorr mi_rowkorr maria_sizestore mi_sizestore maria_sizekorr mi_sizekorr _maria_maria_ _maria MARIA_MAX_POSSIBLE_KEY HA_MAX_POSSIBLE_KEY MARIA_MAX_KEY_BUFF HA_MAX_KEY_BUFF MARIA_MAX_KEY_SEG HA_MAX_KEY_SEG maria_ft_sintXkorr ft_sintXkorr maria_ft_intXstore ft_intXstore maria_ft_boolean_syntax ft_boolean_syntax maria_ft_min_word_len ft_min_word_len maria_ft_max_word_len ft_max_word_len -- $FILES
diff --git a/storage/maria/test_ma_backup.c b/storage/maria/test_ma_backup.c
new file mode 100644
index 00000000000..2a9a6704ecb
--- /dev/null
+++ b/storage/maria/test_ma_backup.c
@@ -0,0 +1,449 @@
+/* Copyright (C) 2018 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 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 Street, Fifth Floor, Boston, MA 02111-1301 USA */
+
+/* Code for doing backups of Aria tables */
+
+/******************************************************************************
+ Testing ma_backup interface
+ Table creation code is taken from ma_test1
+******************************************************************************/
+
+#define ROWS_IN_TEST 100000
+
+#include "maria_def.h"
+#include "ma_blockrec.h" /* PAGE_SUFFIX_SIZE */
+#include "ma_checkpoint.h"
+#include <aria_backup.h>
+
+static int silent;
+static int create_test_table(const char *table_name, int stage);
+static int copy_table(const char *table_name, int stage);
+static void create_record(uchar *record,uint rownr);
+
+int main(int argc __attribute__((unused)), char *argv[])
+{
+ int error= 1;
+ int i;
+ char buff[FN_REFLEN];
+#ifdef SAFE_MUTEX
+ safe_mutex_deadlock_detector= 1;
+#endif
+ MY_INIT(argv[0]);
+ maria_data_root= (char *)".";
+
+ /* Maria requires that we always have a page cache */
+ if (maria_init() ||
+ (init_pagecache(maria_pagecache, maria_block_size * 2000, 0, 0,
+ maria_block_size, 0, MY_WME) == 0) ||
+ ma_control_file_open(TRUE, TRUE) ||
+ (init_pagecache(maria_log_pagecache,
+ TRANSLOG_PAGECACHE_SIZE, 0, 0,
+ TRANSLOG_PAGE_SIZE, 0, MY_WME) == 0) ||
+ translog_init(maria_data_root, TRANSLOG_FILE_SIZE,
+ 0, 0, maria_log_pagecache,
+ TRANSLOG_DEFAULT_FLAGS, 0) ||
+ (trnman_init(0) || ma_checkpoint_init(0)))
+ {
+ fprintf(stderr, "Error in initialization\n");
+ exit(1);
+ }
+ init_thr_lock();
+
+ fn_format(buff, "test_copy", maria_data_root, "", MYF(0));
+
+ for (i= 0; i < 5 ; i++)
+ {
+ printf("Stage: %d\n", i);
+ fflush(stdout);
+ if (create_test_table(buff, i))
+ goto err;
+ if (copy_table(buff, i))
+ goto err;
+ }
+ error= 0;
+ printf("test ok\n");
+err:
+ if (error)
+ fprintf(stderr, "Test %i failed\n", i);
+ maria_end();
+ my_uuid_end();
+ my_end(MY_CHECK_ERROR);
+ exit(error);
+}
+
+
+/**
+ Example of how to read an Aria table
+*/
+
+static int copy_table(const char *table_name, int stage)
+{
+ char old_name[FN_REFLEN];
+ uchar *copy_buffer= 0;
+ ARIA_TABLE_CAPABILITIES cap;
+ ulonglong block;
+ File org_file= -1;
+ int error= 1;
+
+ strxmov(old_name, table_name, ".MAI", NullS);
+
+ if ((org_file= my_open(old_name,
+ O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
+ MYF(MY_WME))) < 0)
+ goto err;
+ if ((error= aria_get_capabilities(org_file, &cap)))
+ {
+ fprintf(stderr, "aria_get_capabilities failed: %d\n", error);
+ goto err;
+ }
+
+ printf("- Capabilities read. oneline_backup_safe: %d\n",
+ cap.online_backup_safe);
+ printf("- Copying index file\n");
+
+ copy_buffer= my_malloc(cap.block_size, MYF(0));
+ for (block= 0 ; ; block++)
+ {
+ if ((error= aria_read_index(org_file, &cap, block, copy_buffer) ==
+ HA_ERR_END_OF_FILE))
+ break;
+ if (error)
+ {
+ fprintf(stderr, "aria_read_index failed: %d\n", error);
+ goto err;
+ }
+ }
+ my_close(org_file, MYF(MY_WME));
+
+
+ printf("- Copying data file\n");
+ strxmov(old_name, table_name, ".MAD", NullS);
+ if ((org_file= my_open(old_name, O_RDONLY | O_SHARE | O_NOFOLLOW | O_CLOEXEC,
+ MYF(MY_WME))) < 0)
+ goto err;
+
+ for (block= 0 ; ; block++)
+ {
+ size_t length;
+ if ((error= aria_read_data(org_file, &cap, block, copy_buffer,
+ &length) == HA_ERR_END_OF_FILE))
+ break;
+ if (error)
+ {
+ fprintf(stderr, "aria_read_index failed: %d\n", error);
+ goto err;
+ }
+ }
+ error= 0;
+
+err:
+ my_free(copy_buffer);
+ if (org_file >= 0)
+ my_close(org_file, MYF(MY_WME));
+ if (error)
+ fprintf(stderr, "Failed in copy_table stage: %d\n", stage);
+ return error;
+}
+
+
+/* Code extracted from ma_test1.c */
+#define MAX_REC_LENGTH 1024
+
+static MARIA_COLUMNDEF recinfo[4];
+static MARIA_KEYDEF keyinfo[10];
+static HA_KEYSEG keyseg[10];
+static HA_KEYSEG uniqueseg[10];
+
+
+/**
+ Create a test table and fill it with some data
+*/
+
+static int create_test_table(const char *table_name, int type_of_table)
+{
+ MARIA_HA *file;
+ int i,error,uniques=0;
+ int key_field=FIELD_SKIP_PRESPACE,extra_field=FIELD_SKIP_ENDSPACE;
+ int key_type=HA_KEYTYPE_NUM;
+ int create_flag=0;
+ uint offset_to_key;
+ uint pack_seg=0, pack_keys= 0;
+ uint key_length;
+ uchar record[MAX_REC_LENGTH];
+ MARIA_UNIQUEDEF uniquedef;
+ MARIA_CREATE_INFO create_info;
+ enum data_file_type record_type= DYNAMIC_RECORD;
+ my_bool null_fields= 0, unique_key= 0;
+ my_bool opt_unique= 0;
+ my_bool transactional= 0;
+
+ key_length= 12;
+ switch (type_of_table) {
+ case 0:
+ break;
+ case 1:
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ break;
+ case 2: /* transactional */
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ record_type= BLOCK_RECORD;
+ transactional= 1;
+ break;
+ case 3: /* transactional */
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ record_type= BLOCK_RECORD;
+ transactional= 1;
+ key_field=FIELD_VARCHAR; /* varchar keys */
+ extra_field= FIELD_VARCHAR;
+ key_type= HA_KEYTYPE_VARTEXT1;
+ pack_seg|= HA_VAR_LENGTH_PART;
+ null_fields= 1;
+ break;
+ case 4: /* transactional */
+ create_flag|= HA_CREATE_CHECKSUM | HA_CREATE_PAGE_CHECKSUM;
+ record_type= BLOCK_RECORD;
+ transactional= 1;
+ key_field=FIELD_BLOB; /* blob key */
+ extra_field= FIELD_BLOB;
+ pack_seg|= HA_BLOB_PART;
+ key_type= HA_KEYTYPE_VARTEXT1;
+ break;
+ }
+
+
+ bzero((char*) recinfo,sizeof(recinfo));
+ bzero((char*) &create_info,sizeof(create_info));
+
+ /* First define 2 columns */
+ create_info.null_bytes= 1;
+ recinfo[0].type= key_field;
+ recinfo[0].length= (key_field == FIELD_BLOB ? 4+portable_sizeof_char_ptr :
+ key_length);
+ if (key_field == FIELD_VARCHAR)
+ recinfo[0].length+= HA_VARCHAR_PACKLENGTH(key_length);
+ recinfo[1].type=extra_field;
+ recinfo[1].length= (extra_field == FIELD_BLOB ? 4 + portable_sizeof_char_ptr : 24);
+ if (extra_field == FIELD_VARCHAR)
+ recinfo[1].length+= HA_VARCHAR_PACKLENGTH(recinfo[1].length);
+ recinfo[1].null_bit= null_fields ? 2 : 0;
+
+ if (opt_unique)
+ {
+ recinfo[2].type=FIELD_CHECK;
+ recinfo[2].length=MARIA_UNIQUE_HASH_LENGTH;
+ }
+
+ if (key_type == HA_KEYTYPE_VARTEXT1 &&
+ key_length > 255)
+ key_type= HA_KEYTYPE_VARTEXT2;
+
+ /* Define a key over the first column */
+ keyinfo[0].seg=keyseg;
+ keyinfo[0].keysegs=1;
+ keyinfo[0].block_length= 0; /* Default block length */
+ keyinfo[0].key_alg=HA_KEY_ALG_BTREE;
+ keyinfo[0].seg[0].type= key_type;
+ keyinfo[0].seg[0].flag= pack_seg;
+ keyinfo[0].seg[0].start=1;
+ keyinfo[0].seg[0].length=key_length;
+ keyinfo[0].seg[0].null_bit= null_fields ? 2 : 0;
+ keyinfo[0].seg[0].null_pos=0;
+ keyinfo[0].seg[0].language= default_charset_info->number;
+ if (pack_seg & HA_BLOB_PART)
+ {
+ keyinfo[0].seg[0].bit_start=4; /* Length of blob length */
+ }
+ keyinfo[0].flag = (uint8) (pack_keys | unique_key);
+
+ if (opt_unique)
+ {
+ uint start;
+ uniques=1;
+ bzero((char*) &uniquedef,sizeof(uniquedef));
+ bzero((char*) uniqueseg,sizeof(uniqueseg));
+ uniquedef.seg=uniqueseg;
+ uniquedef.keysegs=2;
+
+ /* Make a unique over all columns (except first NULL fields) */
+ for (i=0, start=1 ; i < 2 ; i++)
+ {
+ uniqueseg[i].start=start;
+ start+=recinfo[i].length;
+ uniqueseg[i].length=recinfo[i].length;
+ uniqueseg[i].language= default_charset_info->number;
+ }
+ uniqueseg[0].type= key_type;
+ uniqueseg[0].null_bit= null_fields ? 2 : 0;
+ uniqueseg[1].type= HA_KEYTYPE_TEXT;
+ if (extra_field == FIELD_BLOB)
+ {
+ uniqueseg[1].length=0; /* The whole blob */
+ uniqueseg[1].bit_start=4; /* long blob */
+ uniqueseg[1].flag|= HA_BLOB_PART;
+ }
+ else if (extra_field == FIELD_VARCHAR)
+ {
+ uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
+ uniqueseg[1].type= (HA_VARCHAR_PACKLENGTH(recinfo[1].length-1) == 1 ?
+ HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2);
+ }
+ }
+ else
+ uniques=0;
+
+ offset_to_key= MY_TEST(null_fields);
+ if (key_field == FIELD_BLOB || key_field == FIELD_VARCHAR)
+ offset_to_key+= 2;
+
+ if (!silent)
+ printf("- Creating Aria file\n");
+ create_info.max_rows= 0;
+ create_info.transactional= transactional;
+ if (maria_create(table_name, record_type, 1, keyinfo,2+opt_unique,recinfo,
+ uniques, &uniquedef, &create_info,
+ create_flag))
+ goto err;
+ if (!(file=maria_open(table_name,2,HA_OPEN_ABORT_IF_LOCKED)))
+ goto err;
+ if (!silent)
+ printf("- Writing key:s\n");
+
+ if (maria_begin(file))
+ goto err;
+ my_errno=0;
+ for (i= 0 ; i < ROWS_IN_TEST ; i++)
+ {
+ create_record(record,i);
+ if ((error=maria_write(file,record)))
+ goto err;
+ }
+
+ if (maria_commit(file) | maria_close(file))
+ goto err;
+ printf("- Data copied\n");
+ return 0;
+
+err:
+ printf("got error: %3d when using maria-database\n",my_errno);
+ return 1; /* skip warning */
+}
+
+
+static void create_key_part(uchar *key,uint rownr)
+{
+ if (keyinfo[0].seg[0].type == HA_KEYTYPE_NUM)
+ {
+ sprintf((char*) key,"%*d",keyinfo[0].seg[0].length,rownr);
+ }
+ else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT1 ||
+ keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT2)
+ { /* Alpha record */
+ /* Create a key that may be easily packed */
+ bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B');
+ sprintf((char*) key+keyinfo[0].seg[0].length-2,"%-2d",rownr % 100);
+ if ((rownr & 7) == 0)
+ {
+ /* Change the key to force a unpack of the next key */
+ bfill(key+3,keyinfo[0].seg[0].length-5,rownr < 10 ? 'a' : 'b');
+ }
+ }
+ else
+ { /* Alpha record */
+ if (keyinfo[0].seg[0].flag & HA_SPACE_PACK)
+ sprintf((char*) key,"%-*d",keyinfo[0].seg[0].length,rownr);
+ else
+ {
+ /* Create a key that may be easily packed */
+ bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B');
+ sprintf((char*) key+keyinfo[0].seg[0].length-2,"%-2d",rownr % 100);
+ if ((rownr & 7) == 0)
+ {
+ /* Change the key to force a unpack of the next key */
+ key[1]= (rownr < 10 ? 'a' : 'b');
+ }
+ }
+ }
+}
+
+
+static uchar blob_key[MAX_REC_LENGTH];
+static uchar blob_record[MAX_REC_LENGTH+20*20];
+
+
+static void create_record(uchar *record,uint rownr)
+{
+ uchar *pos;
+ bzero((char*) record,MAX_REC_LENGTH);
+ record[0]=1; /* delete marker */
+ if (rownr == 0 && keyinfo[0].seg[0].null_bit)
+ record[0]|=keyinfo[0].seg[0].null_bit; /* Null key */
+
+ pos=record+1;
+ if (recinfo[0].type == FIELD_BLOB)
+ {
+ size_t tmp;
+ uchar *ptr;
+ create_key_part(blob_key,rownr);
+ tmp=strlen((char*) blob_key);
+ int4store(pos,tmp);
+ ptr=blob_key;
+ memcpy(pos+4,&ptr,sizeof(char*));
+ pos+=recinfo[0].length;
+ }
+ else if (recinfo[0].type == FIELD_VARCHAR)
+ {
+ size_t tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[0].length-1);
+ create_key_part(pos+pack_length,rownr);
+ tmp= strlen((char*) pos+pack_length);
+ if (pack_length == 1)
+ *(uchar*) pos= (uchar) tmp;
+ else
+ int2store(pos,tmp);
+ pos+= recinfo[0].length;
+ }
+ else
+ {
+ create_key_part(pos,rownr);
+ pos+=recinfo[0].length;
+ }
+ if (recinfo[1].type == FIELD_BLOB)
+ {
+ size_t tmp;
+ uchar *ptr;;
+ sprintf((char*) blob_record,"... row: %d", rownr);
+ strappend((char*) blob_record, rownr % MAX_REC_LENGTH,'x');
+ tmp=strlen((char*) blob_record);
+ int4store(pos,tmp);
+ ptr=blob_record;
+ memcpy(pos+4,&ptr,sizeof(char*));
+ }
+ else if (recinfo[1].type == FIELD_VARCHAR)
+ {
+ size_t tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
+ sprintf((char*) pos+pack_length, "... row: %d", rownr);
+ tmp= strlen((char*) pos+pack_length);
+ if (pack_length == 1)
+ *pos= (uchar) tmp;
+ else
+ int2store(pos,tmp);
+ }
+ else
+ {
+ sprintf((char*) pos,"... row: %d", rownr);
+ strappend((char*) pos,recinfo[1].length,' ');
+ }
+}
+
+#include "ma_check_standalone.h"
diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c
index 85a87e928b9..6bc83a9ba88 100644
--- a/storage/maria/trnman.c
+++ b/storage/maria/trnman.c
@@ -413,6 +413,7 @@ my_bool trnman_end_trn(TRN *trn, my_bool commit)
/* if a rollback, all UNDO records should have been executed */
DBUG_ASSERT(commit || trn->undo_lsn == 0);
DBUG_ASSERT(trn != &dummy_transaction_object);
+ DBUG_ASSERT(trn->locked_tables == 0 && trn->used_instances == 0);
DBUG_PRINT("info", ("mysql_mutex_lock LOCK_trn_list"));
mysql_mutex_lock(&LOCK_trn_list);
@@ -529,6 +530,8 @@ static void trnman_free_trn(TRN *trn)
*/
union { TRN *trn; void *v; } tmp;
+ DBUG_ASSERT(trn != &dummy_transaction_object);
+
mysql_mutex_lock(&trn->state_lock);
trn->short_id= 0;
mysql_mutex_unlock(&trn->state_lock);
diff --git a/storage/maria/unittest/lockman-t.c b/storage/maria/unittest/lockman-t.c
index 669fd9ecc72..222618acf89 100644
--- a/storage/maria/unittest/lockman-t.c
+++ b/storage/maria/unittest/lockman-t.c
@@ -23,7 +23,6 @@
#include <my_global.h>
#include <my_sys.h>
-#include <my_atomic.h>
#include <lf.h>
#include "../lockman.h"
diff --git a/storage/maria/unittest/lockman1-t.c b/storage/maria/unittest/lockman1-t.c
index 2a3cb291e3d..986ac73e2f5 100644
--- a/storage/maria/unittest/lockman1-t.c
+++ b/storage/maria/unittest/lockman1-t.c
@@ -23,7 +23,6 @@
#include <my_global.h>
#include <my_sys.h>
-#include <my_atomic.h>
#include <lf.h>
#include "../lockman.h"
#include "../tablockman.h"
diff --git a/storage/maria/unittest/lockman2-t.c b/storage/maria/unittest/lockman2-t.c
index ee3e2d2bd6b..7f9ed3cc50e 100644
--- a/storage/maria/unittest/lockman2-t.c
+++ b/storage/maria/unittest/lockman2-t.c
@@ -23,7 +23,6 @@
#include <my_global.h>
#include <my_sys.h>
-#include <my_atomic.h>
#include <lf.h>
#include "../tablockman.h"
diff --git a/storage/maria/unittest/ma_test_all-t b/storage/maria/unittest/ma_test_all-t
index 18b26a7bd45..8858649fb5d 100755
--- a/storage/maria/unittest/ma_test_all-t
+++ b/storage/maria/unittest/ma_test_all-t
@@ -749,9 +749,10 @@ Options
--help Show this help and exit.
--abort-on-error Abort at once in case of error.
--number-of-tests Print the total number of tests and exit.
---run-tests=... Test number(s) that should be run. You can give just
- one number or a range. For example 45..89. To run a specific
- test alone, for example test 215, use --run-tests=215..215
+--run-tests=... Test range that should be run. You can give just
+ one number, to start tests from this test, or a range.
+ For example 45..89. To run a specific test alone,
+ for example test 215, use --run-tests=215..215
Use this option with caution, because some of the tests
might depend on previous ones.
--start-from=... Alias for --run-tests
diff --git a/storage/maria/unittest/ma_test_recovery.expected b/storage/maria/unittest/ma_test_recovery.expected
index 6aaff86e6cf..38e8e4d8e93 100644
--- a/storage/maria/unittest/ma_test_recovery.expected
+++ b/storage/maria/unittest/ma_test_recovery.expected
@@ -70,7 +70,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -79,7 +79,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -88,7 +88,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -99,7 +99,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -108,7 +108,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -117,7 +117,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -167,7 +167,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -176,7 +176,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -185,7 +185,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -196,7 +196,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -205,7 +205,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -214,7 +214,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -264,7 +264,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -273,7 +273,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -282,7 +282,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -293,7 +293,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -302,7 +302,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -311,7 +311,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -361,7 +361,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -370,7 +370,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -379,7 +379,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -390,7 +390,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -399,7 +399,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -408,7 +408,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -458,7 +458,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -467,7 +467,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -476,7 +476,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -487,7 +487,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -496,7 +496,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -505,7 +505,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -555,7 +555,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -564,7 +564,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -573,7 +573,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -584,7 +584,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -593,7 +593,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -602,7 +602,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -652,7 +652,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -661,7 +661,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -670,7 +670,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -681,7 +681,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -690,7 +690,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -699,7 +699,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -749,7 +749,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -758,7 +758,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -767,7 +767,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -778,7 +778,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -787,7 +787,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -796,7 +796,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -846,7 +846,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -855,7 +855,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -864,7 +864,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -875,7 +875,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -884,7 +884,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -893,7 +893,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -943,7 +943,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -952,7 +952,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -961,7 +961,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -972,7 +972,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -981,7 +981,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -990,7 +990,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1040,7 +1040,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1049,7 +1049,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1058,7 +1058,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1069,7 +1069,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1078,7 +1078,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1087,7 +1087,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1137,7 +1137,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1146,7 +1146,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1155,7 +1155,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1166,7 +1166,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1175,7 +1175,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1184,7 +1184,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1234,7 +1234,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1243,7 +1243,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1252,7 +1252,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1263,7 +1263,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1272,7 +1272,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1281,7 +1281,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1331,7 +1331,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1340,7 +1340,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1349,7 +1349,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1360,7 +1360,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1369,7 +1369,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1378,7 +1378,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1428,7 +1428,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1437,7 +1437,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1446,7 +1446,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1457,7 +1457,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1466,7 +1466,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1475,7 +1475,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1525,7 +1525,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1534,7 +1534,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1543,7 +1543,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1554,7 +1554,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1563,7 +1563,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
@@ -1572,7 +1572,7 @@ applying log
Differences in aria_chk -dvv, recovery not yet perfect !
========DIFF START=======
7c7
-< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled,movable
+< Status: checked,analyzed,optimized keys,sorted index pages,zerofilled
---
> Status: changed
========DIFF END=======
diff --git a/storage/maria/unittest/trnman-t.c b/storage/maria/unittest/trnman-t.c
index 00e84cb2456..3d19116dbbc 100644
--- a/storage/maria/unittest/trnman-t.c
+++ b/storage/maria/unittest/trnman-t.c
@@ -17,7 +17,6 @@
#include <my_global.h>
#include <my_sys.h>
-#include <my_atomic.h>
#include <lf.h>
#include <m_string.h>
#include "../trnman.h"
diff --git a/storage/mroonga/CMakeLists.txt b/storage/mroonga/CMakeLists.txt
index af95c13d275..35e0783595f 100644
--- a/storage/mroonga/CMakeLists.txt
+++ b/storage/mroonga/CMakeLists.txt
@@ -361,12 +361,7 @@ else()
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-unused-parameter")
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-strict-aliasing")
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-deprecated")
- if(("${MYSQL_VARIANT}" STREQUAL "MariaDB") OR
- ("${MYSQL_VARIANT}" STREQUAL "MySQL" AND
- ${MYSQL_VERSION} VERSION_LESS "5.7.0"))
- MY_CHECK_AND_SET_COMPILER_FLAG("-fno-exceptions")
- MY_CHECK_AND_SET_COMPILER_FLAG("-fno-rtti")
- endif()
+ MY_CHECK_AND_SET_COMPILER_FLAG("-fno-exceptions")
MY_CHECK_AND_SET_COMPILER_FLAG("-felide-constructors")
MY_CHECK_AND_SET_COMPILER_FLAG("-Wno-implicit-fallthrough")
endif()
diff --git a/storage/mroonga/ha_mroonga.cpp b/storage/mroonga/ha_mroonga.cpp
index 4e084400ed6..8638399717e 100644
--- a/storage/mroonga/ha_mroonga.cpp
+++ b/storage/mroonga/ha_mroonga.cpp
@@ -193,7 +193,7 @@ static mysql_mutex_t *mrn_LOCK_open;
#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex->table_list.first
#else
-# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex.table_list.first
+# define MRN_LEX_GET_TABLE_LIST(lex) (lex)->first_select_lex()->table_list.first
#endif
#if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
@@ -2856,6 +2856,7 @@ ulonglong ha_mroonga::wrapper_table_flags() const
#ifdef HA_CAN_VIRTUAL_COLUMNS
table_flags |= HA_CAN_VIRTUAL_COLUMNS;
#endif
+ table_flags |= HA_CAN_HASH_KEYS;
DBUG_RETURN(table_flags);
}
@@ -2891,6 +2892,7 @@ ulonglong ha_mroonga::storage_table_flags() const
#ifdef HA_CAN_VIRTUAL_COLUMNS
flags |= HA_CAN_VIRTUAL_COLUMNS;
#endif
+ flags |= HA_CAN_HASH_KEYS;
DBUG_RETURN(flags);
}
@@ -5850,7 +5852,7 @@ bool ha_mroonga::wrapper_have_target_index()
DBUG_RETURN(have_target_index);
}
-int ha_mroonga::wrapper_write_row(uchar *buf)
+int ha_mroonga::wrapper_write_row(const uchar *buf)
{
int error = 0;
THD *thd = ha_thd();
@@ -5879,7 +5881,7 @@ int ha_mroonga::wrapper_write_row(uchar *buf)
DBUG_RETURN(error);
}
-int ha_mroonga::wrapper_write_row_index(uchar *buf)
+int ha_mroonga::wrapper_write_row_index(const uchar *buf)
{
MRN_DBUG_ENTER_METHOD();
@@ -5966,7 +5968,7 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::storage_write_row(uchar *buf)
+int ha_mroonga::storage_write_row(const uchar *buf)
{
MRN_DBUG_ENTER_METHOD();
int error = 0;
@@ -6229,7 +6231,7 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::storage_write_row_multiple_column_index(uchar *buf,
+int ha_mroonga::storage_write_row_multiple_column_index(const uchar *buf,
grn_id record_id,
KEY *key_info,
grn_obj *index_column)
@@ -6266,7 +6268,7 @@ int ha_mroonga::storage_write_row_multiple_column_index(uchar *buf,
DBUG_RETURN(error);
}
-int ha_mroonga::storage_write_row_multiple_column_indexes(uchar *buf,
+int ha_mroonga::storage_write_row_multiple_column_indexes(const uchar *buf,
grn_id record_id)
{
MRN_DBUG_ENTER_METHOD();
@@ -6378,7 +6380,7 @@ int ha_mroonga::storage_write_row_unique_index(const uchar *buf,
DBUG_RETURN(0);
}
-int ha_mroonga::storage_write_row_unique_indexes(uchar *buf)
+int ha_mroonga::storage_write_row_unique_indexes(const uchar *buf)
{
int error = 0;
uint i;
@@ -6441,7 +6443,7 @@ err:
DBUG_RETURN(error);
}
-int ha_mroonga::write_row(uchar *buf)
+int ha_mroonga::write_row(const uchar *buf)
{
MRN_DBUG_ENTER_METHOD();
int error = 0;
@@ -10576,7 +10578,7 @@ int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf)
bool truncated = false;
Field_time *time_field = (Field_time *)field;
MYSQL_TIME mysql_time;
- time_field->get_time(&mysql_time);
+ time_field->get_date(&mysql_time, Time::Options(current_thd));
mrn::TimeConverter time_converter;
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
&truncated);
@@ -10596,7 +10598,7 @@ int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf)
bool truncated = false;
Field_datetime *datetime_field = (Field_datetime *)field;
MYSQL_TIME mysql_time;
- datetime_field->get_time(&mysql_time);
+ datetime_field->get_date(&mysql_time, Time::Options(current_thd));
mrn::TimeConverter time_converter;
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
&truncated);
@@ -10657,7 +10659,7 @@ int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf)
bool truncated = false;
Field_datetimef *datetimef_field = (Field_datetimef *)field;
MYSQL_TIME mysql_time;
- datetimef_field->get_time(&mysql_time);
+ datetimef_field->get_date(&mysql_time, Time::Options(current_thd));
mrn::TimeConverter time_converter;
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
&truncated);
@@ -10682,7 +10684,7 @@ int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf)
int error = 0;
bool truncated = false;
MYSQL_TIME mysql_time;
- field->get_time(&mysql_time);
+ field->get_date(&mysql_time, Time::Options(current_thd));
mrn::TimeConverter time_converter;
long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
&truncated);
@@ -10707,7 +10709,7 @@ int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf)
bool truncated = false;
Field_newdate *newdate_field = (Field_newdate *)field;
MYSQL_TIME mysql_date;
- newdate_field->get_time(&mysql_date);
+ newdate_field->get_date(&mysql_date, Time::Options(current_thd));
mrn::TimeConverter time_converter;
long long int time = time_converter.mysql_time_to_grn_time(&mysql_date,
&truncated);
@@ -11617,14 +11619,14 @@ int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key,
} else {
Field_timestamp_hires *timestamp_hires_field =
(Field_timestamp_hires *)field;
- uint fuzzy_date = 0;
uchar *ptr_backup = field->ptr;
uchar *null_ptr_backup = field->null_ptr;
TABLE *table_backup = field->table;
field->ptr = (uchar *)key;
field->null_ptr = (uchar *)(key - 1);
field->table = table;
- timestamp_hires_field->get_date(&mysql_time, fuzzy_date);
+ Temporal::Options opt(TIME_CONV_NONE, current_thd);
+ timestamp_hires_field->get_date(&mysql_time, opt);
field->ptr = ptr_backup;
field->null_ptr = null_ptr_backup;
field->table = table_backup;
@@ -11675,12 +11677,12 @@ int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key,
mysql_time.time_type = MYSQL_TIMESTAMP_TIME;
} else {
Field_time_hires *time_hires_field = (Field_time_hires *)field;
- uint fuzzy_date = 0;
uchar *ptr_backup = field->ptr;
uchar *null_ptr_backup = field->null_ptr;
field->ptr = (uchar *)key;
field->null_ptr = (uchar *)(key - 1);
- time_hires_field->get_date(&mysql_time, fuzzy_date);
+ Temporal::Options opt(TIME_CONV_NONE, current_thd);
+ time_hires_field->get_date(&mysql_time, opt);
field->ptr = ptr_backup;
field->null_ptr = null_ptr_backup;
}
@@ -11749,12 +11751,12 @@ int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key,
if (field->decimals() > 0) {
Field_datetime_hires *datetime_hires_field = (Field_datetime_hires *)field;
MYSQL_TIME mysql_time;
- uint fuzzy_date = 0;
uchar *ptr_backup = field->ptr;
uchar *null_ptr_backup = field->null_ptr;
field->ptr = (uchar *)key;
field->null_ptr = (uchar *)(key - 1);
- datetime_hires_field->get_date(&mysql_time, fuzzy_date);
+ Temporal::Options opt(TIME_CONV_NONE, current_thd);
+ datetime_hires_field->get_date(&mysql_time, opt);
field->ptr = ptr_backup;
field->null_ptr = null_ptr_backup;
mrn::TimeConverter time_converter;
diff --git a/storage/mroonga/ha_mroonga.hpp b/storage/mroonga/ha_mroonga.hpp
index e1dbb63178e..20626742bb7 100644
--- a/storage/mroonga/ha_mroonga.hpp
+++ b/storage/mroonga/ha_mroonga.hpp
@@ -451,7 +451,7 @@ public:
int extra_opt(enum ha_extra_function operation, ulong cache_size) mrn_override;
int delete_table(const char *name) mrn_override;
- int write_row(uchar *buf) mrn_override;
+ int write_row(const uchar *buf) mrn_override;
int update_row(const uchar *old_data, const uchar *new_data) mrn_override;
int delete_row(const uchar *buf) mrn_override;
@@ -913,20 +913,20 @@ private:
int storage_end_bulk_insert();
bool wrapper_is_target_index(KEY *key_info);
bool wrapper_have_target_index();
- int wrapper_write_row(uchar *buf);
- int wrapper_write_row_index(uchar *buf);
- int storage_write_row(uchar *buf);
- int storage_write_row_multiple_column_index(uchar *buf,
+ int wrapper_write_row(const uchar *buf);
+ int wrapper_write_row_index(const uchar *buf);
+ int storage_write_row(const uchar *buf);
+ int storage_write_row_multiple_column_index(const uchar *buf,
grn_id record_id,
KEY *key_info,
grn_obj *index_column);
- int storage_write_row_multiple_column_indexes(uchar *buf, grn_id record_id);
+ int storage_write_row_multiple_column_indexes(const uchar *buf, grn_id record_id);
int storage_write_row_unique_index(const uchar *buf,
KEY *key_info,
grn_obj *index_table,
grn_obj *index_column,
grn_id *key_id);
- int storage_write_row_unique_indexes(uchar *buf);
+ int storage_write_row_unique_indexes(const uchar *buf);
int wrapper_get_record_id(uchar *data, grn_id *record_id,
const char *context);
int wrapper_update_row(const uchar *old_data, const uchar *new_data);
diff --git a/storage/mroonga/lib/mrn_condition_converter.cpp b/storage/mroonga/lib/mrn_condition_converter.cpp
index b85070a0d6d..761dfc72ade 100644
--- a/storage/mroonga/lib/mrn_condition_converter.cpp
+++ b/storage/mroonga/lib/mrn_condition_converter.cpp
@@ -179,17 +179,17 @@ namespace mrn {
NormalizedType normalized_type = normalize_field_type(field_type);
switch (normalized_type) {
case STRING_TYPE:
- if (value_item->type() == Item::STRING_ITEM &&
+ if (value_item->is_of_type(Item::CONST_ITEM, STRING_RESULT) &&
func_type == Item_func::EQ_FUNC) {
convertable = have_index(field_item, GRN_OP_EQUAL);
}
break;
case INT_TYPE:
if (field_type == MYSQL_TYPE_ENUM) {
- convertable = (value_item->type() == Item::STRING_ITEM ||
- value_item->type() == Item::INT_ITEM);
+ convertable = value_item->is_of_type(Item::CONST_ITEM, STRING_RESULT) ||
+ value_item->is_of_type(Item::CONST_ITEM, INT_RESULT);
} else {
- convertable = value_item->type() == Item::INT_ITEM;
+ convertable = value_item->is_of_type(Item::CONST_ITEM, INT_RESULT);
}
break;
case TIME_TYPE:
@@ -215,14 +215,14 @@ namespace mrn {
NormalizedType normalized_type = normalize_field_type(field_type);
switch (normalized_type) {
case STRING_TYPE:
- if (min_item->type() == Item::STRING_ITEM &&
- max_item->type() == Item::STRING_ITEM) {
+ if (min_item->is_of_type(Item::CONST_ITEM, STRING_RESULT) &&
+ max_item->is_of_type(Item::CONST_ITEM, STRING_RESULT)) {
convertable = have_index(field_item, GRN_OP_LESS);
}
break;
case INT_TYPE:
- if (min_item->type() == Item::INT_ITEM &&
- max_item->type() == Item::INT_ITEM) {
+ if (min_item->is_of_type(Item::CONST_ITEM, INT_RESULT) &&
+ max_item->is_of_type(Item::CONST_ITEM, INT_RESULT)) {
convertable = have_index(field_item, GRN_OP_LESS);
}
break;
@@ -258,8 +258,11 @@ namespace mrn {
Item *real_value_item = value_item->real_item();
switch (field_item->field->type()) {
case MYSQL_TYPE_TIME:
- error = real_value_item->get_time(mysql_time);
+ {
+ THD *thd= current_thd;
+ error= real_value_item->get_date(thd, mysql_time, Time::Options(thd));
break;
+ }
case MYSQL_TYPE_YEAR:
mysql_time->year = static_cast<int>(value_item->val_int());
mysql_time->month = 1;
@@ -273,9 +276,13 @@ namespace mrn {
error = false;
break;
default:
- error = real_value_item->get_date(mysql_time, TIME_FUZZY_DATE);
+ {
+ THD *thd= current_thd;
+ Datetime::Options opt(TIME_FUZZY_DATES, thd);
+ error = real_value_item->get_date(thd, mysql_time, opt);
break;
}
+ }
DBUG_RETURN(error);
}
@@ -587,7 +594,7 @@ namespace mrn {
case INT_TYPE:
grn_obj_reinit(ctx_, &value_, GRN_DB_INT64, 0);
if (field_type == MYSQL_TYPE_ENUM) {
- if (const_item->type() == Item::STRING_ITEM) {
+ if (const_item->is_of_type(Item::CONST_ITEM, STRING_RESULT)) {
String *string;
string = const_item->val_str(NULL);
Field_enum *enum_field = static_cast<Field_enum *>(field_item->field);
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_between.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_between.result
index 9af4a4fedcc..c4b1dbf7141 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_between.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_between.result
@@ -9,6 +9,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE age BETWEEN 28 AND 30;
COUNT(*)
3
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater.result
index d5c033083cc..4eba1922134 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater.result
@@ -9,6 +9,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (1),(2),(3),(4),(5),(6);
SELECT COUNT(*) FROM users WHERE age > 29;
COUNT(*)
2
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater_equal.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater_equal.result
index 59b812d1484..4de49651b81 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater_equal.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_greater_equal.result
@@ -9,6 +9,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (1),(2),(3),(4),(5),(6);
SELECT COUNT(*) FROM users WHERE age >= 29;
COUNT(*)
3
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less.result
index b5e4fc1c3de..a57a3b8fa6f 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less.result
@@ -9,6 +9,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE age < 29;
COUNT(*)
2
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less_equal.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less_equal.result
index f062fe0092b..c770b63daf8 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less_equal.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_less_equal.result
@@ -9,6 +9,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE age <= 29;
COUNT(*)
3
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_not_equal.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_not_equal.result
index a1a123e7d5f..199edf9d758 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_not_equal.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_index_not_equal.result
@@ -14,5 +14,5 @@ COUNT(*)
2
SHOW STATUS LIKE 'mroonga_count_skip';
Variable_name Value
-Mroonga_count_skip 2
+Mroonga_count_skip 0
DROP TABLE users;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_between.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_between.result
index 68a0575ab97..26c8b6a9d94 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_between.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_between.result
@@ -8,6 +8,7 @@ INSERT INTO users (id) VALUES (2);
INSERT INTO users (id) VALUES (3);
INSERT INTO users (id) VALUES (4);
INSERT INTO users (id) VALUES (5);
+INSERT INTO users (id) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE id BETWEEN 2 AND 4;
COUNT(*)
3
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater.result
index 3ae04a0246f..fe9de9e631d 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater.result
@@ -8,6 +8,7 @@ INSERT INTO users (id) VALUES (2);
INSERT INTO users (id) VALUES (3);
INSERT INTO users (id) VALUES (4);
INSERT INTO users (id) VALUES (5);
+INSERT INTO users (id) VALUES (-1),(-2),(-3),(-4);
SELECT COUNT(*) FROM users WHERE id > 3;
COUNT(*)
2
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater_equal.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater_equal.result
index 0f0643110f0..2fa5213ea49 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater_equal.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_greater_equal.result
@@ -8,6 +8,7 @@ INSERT INTO users (id) VALUES (2);
INSERT INTO users (id) VALUES (3);
INSERT INTO users (id) VALUES (4);
INSERT INTO users (id) VALUES (5);
+INSERT INTO users (id) VALUES (-1),(-2),(-3),(-4);
SELECT COUNT(*) FROM users WHERE id >= 3;
COUNT(*)
3
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_not_equal.result b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_not_equal.result
index 64761c9565d..1b253a8edc6 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_not_equal.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/optimization_count_skip_primary_key_not_equal.result
@@ -13,5 +13,5 @@ COUNT(*)
4
SHOW STATUS LIKE 'mroonga_count_skip';
Variable_name Value
-Mroonga_count_skip 1
+Mroonga_count_skip 0
DROP TABLE users;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/r/variable_max_n_records_for_estimate_not_found_in_limit.result b/storage/mroonga/mysql-test/mroonga/storage/r/variable_max_n_records_for_estimate_not_found_in_limit.result
index e2d8a8de493..d318a654c6c 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/r/variable_max_n_records_for_estimate_not_found_in_limit.result
+++ b/storage/mroonga/mysql-test/mroonga/storage/r/variable_max_n_records_for_estimate_not_found_in_limit.result
@@ -6,6 +6,7 @@ INDEX (id)
INSERT INTO ids VALUES (1);
INSERT INTO ids VALUES (2);
INSERT INTO ids VALUES (3);
+INSERT INTO ids VALUES (4),(5),(6),(7);
DELETE FROM ids WHERE id < 2;
SET mroonga_max_n_records_for_estimate = 1;
EXPLAIN SELECT * FROM ids WHERE id > 0;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_between.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_between.test
index c3fb2bec507..76675fdeb76 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_between.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_between.test
@@ -32,6 +32,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE age BETWEEN 28 AND 30;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater.test
index 4b814e494f9..fb5c336cd4c 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater.test
@@ -32,6 +32,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (1),(2),(3),(4),(5),(6);
SELECT COUNT(*) FROM users WHERE age > 29;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater_equal.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater_equal.test
index f26ed636b5a..c897d8d88de 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater_equal.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_greater_equal.test
@@ -32,6 +32,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (1),(2),(3),(4),(5),(6);
SELECT COUNT(*) FROM users WHERE age >= 29;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less.test
index 0a7be348bd5..f03156d545b 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less.test
@@ -32,6 +32,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE age < 29;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less_equal.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less_equal.test
index 190d242d932..20863705bf4 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less_equal.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_index_less_equal.test
@@ -32,6 +32,7 @@ INSERT INTO users (age) VALUES (28);
INSERT INTO users (age) VALUES (29);
INSERT INTO users (age) VALUES (30);
INSERT INTO users (age) VALUES (31);
+INSERT INTO users (age) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE age <= 29;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_between.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_between.test
index 73754afda63..25d6c734fe1 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_between.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_between.test
@@ -31,6 +31,7 @@ INSERT INTO users (id) VALUES (2);
INSERT INTO users (id) VALUES (3);
INSERT INTO users (id) VALUES (4);
INSERT INTO users (id) VALUES (5);
+INSERT INTO users (id) VALUES (32),(33),(34),(35),(36),(37);
SELECT COUNT(*) FROM users WHERE id BETWEEN 2 AND 4;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater.test
index 44ba5ead9f2..f91cf19310f 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater.test
@@ -31,9 +31,9 @@ INSERT INTO users (id) VALUES (2);
INSERT INTO users (id) VALUES (3);
INSERT INTO users (id) VALUES (4);
INSERT INTO users (id) VALUES (5);
+INSERT INTO users (id) VALUES (-1),(-2),(-3),(-4);
SELECT COUNT(*) FROM users WHERE id > 3;
-
SHOW STATUS LIKE 'mroonga_count_skip';
DROP TABLE users;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater_equal.test b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater_equal.test
index 8d442692950..dd374012257 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater_equal.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/optimization_count_skip_primary_key_greater_equal.test
@@ -31,6 +31,7 @@ INSERT INTO users (id) VALUES (2);
INSERT INTO users (id) VALUES (3);
INSERT INTO users (id) VALUES (4);
INSERT INTO users (id) VALUES (5);
+INSERT INTO users (id) VALUES (-1),(-2),(-3),(-4);
SELECT COUNT(*) FROM users WHERE id >= 3;
diff --git a/storage/mroonga/mysql-test/mroonga/storage/t/variable_max_n_records_for_estimate_not_found_in_limit.test b/storage/mroonga/mysql-test/mroonga/storage/t/variable_max_n_records_for_estimate_not_found_in_limit.test
index d67a832ad95..79c75308c9f 100644
--- a/storage/mroonga/mysql-test/mroonga/storage/t/variable_max_n_records_for_estimate_not_found_in_limit.test
+++ b/storage/mroonga/mysql-test/mroonga/storage/t/variable_max_n_records_for_estimate_not_found_in_limit.test
@@ -29,6 +29,7 @@ CREATE TABLE ids (
INSERT INTO ids VALUES (1);
INSERT INTO ids VALUES (2);
INSERT INTO ids VALUES (3);
+INSERT INTO ids VALUES (4),(5),(6),(7);
DELETE FROM ids WHERE id < 2;
diff --git a/storage/mroonga/vendor/groonga/lib/ii.c b/storage/mroonga/vendor/groonga/lib/ii.c
index cd5559e6958..2abd074796c 100644
--- a/storage/mroonga/vendor/groonga/lib/ii.c
+++ b/storage/mroonga/vendor/groonga/lib/ii.c
@@ -4315,7 +4315,7 @@ grn_ii_remove(grn_ctx *ctx, const char *path)
if (!path || strlen(path) > PATH_MAX - 4) { return GRN_INVALID_ARGUMENT; }
if ((rc = grn_io_remove(ctx, path))) { goto exit; }
grn_snprintf(buffer, PATH_MAX, PATH_MAX,
- "%s.c", path);
+ "%-.256s.c", path);
rc = grn_io_remove(ctx, buffer);
exit :
return rc;
@@ -4331,12 +4331,12 @@ grn_ii_truncate(grn_ctx *ctx, grn_ii *ii)
uint32_t flags;
if ((io_segpath = grn_io_path(ii->seg)) && *io_segpath != '\0') {
if (!(segpath = GRN_STRDUP(io_segpath))) {
- ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_segpath);
+ ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%-.256s>", io_segpath);
return GRN_NO_MEMORY_AVAILABLE;
}
if ((io_chunkpath = grn_io_path(ii->chunk)) && *io_chunkpath != '\0') {
if (!(chunkpath = GRN_STRDUP(io_chunkpath))) {
- ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_chunkpath);
+ ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%-.256s>", io_chunkpath);
return GRN_NO_MEMORY_AVAILABLE;
}
} else {
@@ -5144,7 +5144,7 @@ grn_ii_cursor_set_min(grn_ctx *ctx, grn_ii_cursor *c, grn_id min)
c->stat |= CHUNK_USED;
GRN_LOG(ctx, GRN_LOG_DEBUG,
"[ii][cursor][min] skip: %p: min(%u->%u): chunk(%u->%u): "
- "chunk-used(%s->%s)",
+ "chunk-used(%-.256s->%-.256s)",
c,
old_min, min,
old_chunk, c->curr_chunk,
@@ -5205,7 +5205,7 @@ grn_ii_cursor_next_internal(grn_ctx *ctx, grn_ii_cursor *c,
}
GRN_TEXT_PUTC(ctx, &buf, ')');
GRN_TEXT_PUTC(ctx, &buf, '\0');
- GRN_LOG(ctx, GRN_LOG_DEBUG, "posting(%d):%s", count, GRN_TEXT_VALUE(&buf));
+ GRN_LOG(ctx, GRN_LOG_DEBUG, "posting(%d):%-.256s", count, GRN_TEXT_VALUE(&buf));
GRN_OBJ_FIN(ctx, &buf);
}
*/
@@ -6451,7 +6451,7 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
ERR(GRN_INVALID_ARGUMENT,
"[ii][column][update][new] invalid object: "
"<%.*s>: "
- "<%s>(%#x)",
+ "<%-.256s>(%#x)",
name_size, name,
grn_obj_type_to_string(type),
type);
@@ -6564,7 +6564,7 @@ grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section,
ERR(GRN_INVALID_ARGUMENT,
"[ii][column][update][old] invalid object: "
"<%.*s>: "
- "<%s>(%#x)",
+ "<%-.256s>(%#x)",
name_size, name,
grn_obj_type_to_string(type),
type);
@@ -7833,7 +7833,7 @@ grn_ii_select_cursor_open(grn_ctx *ctx,
default :
ERR(GRN_INVALID_ARGUMENT,
"[ii][select][cursor][open] "
- "EXACT, FUZZY, NEAR and NEAR2 are only supported mode: %s",
+ "EXACT, FUZZY, NEAR and NEAR2 are only supported mode: %-.256s",
grn_operator_to_string(mode));
break;
}
@@ -7841,7 +7841,7 @@ grn_ii_select_cursor_open(grn_ctx *ctx,
cursor = GRN_CALLOC(sizeof(grn_ii_select_cursor));
if (!cursor) {
ERR(ctx->rc,
- "[ii][select][cursor][open] failed to allocate cursor: %s",
+ "[ii][select][cursor][open] failed to allocate cursor: %-.256s",
ctx->errbuf);
return NULL;
}
@@ -7851,7 +7851,7 @@ grn_ii_select_cursor_open(grn_ctx *ctx,
if (!(cursor->tis = GRN_MALLOC(sizeof(token_info *) * string_len * 2))) {
ERR(ctx->rc,
- "[ii][select][cursor][open] failed to allocate token info container: %s",
+ "[ii][select][cursor][open] failed to allocate token info container: %-.256s",
ctx->errbuf);
GRN_FREE(cursor);
return NULL;
@@ -7891,7 +7891,7 @@ grn_ii_select_cursor_open(grn_ctx *ctx,
case GRN_OP_NEAR :
if (!(cursor->bt = bt_open(ctx, cursor->n_tis))) {
ERR(ctx->rc,
- "[ii][select][cursor][open] failed to allocate btree: %s",
+ "[ii][select][cursor][open] failed to allocate btree: %-.256s",
ctx->errbuf);
grn_ii_select_cursor_close(ctx, cursor);
return NULL;
@@ -8114,7 +8114,7 @@ grn_ii_parse_regexp_query(grn_ctx *ctx,
if (char_len == 0) {
GRN_OBJ_FIN(ctx, &buffer);
ERR(GRN_INVALID_ARGUMENT,
- "%s invalid encoding character: <%.*s|%#x|>",
+ "%-.256s invalid encoding character: <%.*s|%#x|>",
log_tag,
(int)(current - string), string,
*current);
@@ -8515,7 +8515,7 @@ grn_ii_select_sequential_search(grn_ctx *ctx,
onig_error_code_to_str(message, onig_result, error_info);
GRN_LOG(ctx, GRN_LOG_WARNING,
"[ii][select][sequential] "
- "failed to create regular expression object: %s",
+ "failed to create regular expression object: %-.256s",
message);
processed = GRN_FALSE;
}
@@ -10148,7 +10148,7 @@ grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii,
ii_buffer->block_buf = GRN_MALLOCN(grn_id, II_BUFFER_BLOCK_SIZE);
if (ii_buffer->block_buf) {
grn_snprintf(ii_buffer->tmpfpath, PATH_MAX, PATH_MAX,
- "%sXXXXXX", grn_io_path(ii->seg));
+ "%-.256sXXXXXX", grn_io_path(ii->seg));
ii_buffer->block_buf_size = II_BUFFER_BLOCK_SIZE;
ii_buffer->tmpfd = grn_mkstemp(ii_buffer->tmpfpath);
if (ii_buffer->tmpfd != -1) {
@@ -10161,7 +10161,7 @@ grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii,
}
return ii_buffer;
} else {
- SERR("failed grn_mkstemp(%s)",
+ SERR("failed grn_mkstemp(%-.256s)",
ii_buffer->tmpfpath);
}
GRN_FREE(ii_buffer->block_buf);
@@ -10308,7 +10308,7 @@ grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
ii_buffer->tmpfpath,
O_RDONLY | GRN_OPEN_FLAG_BINARY);
if (ii_buffer->tmpfd == -1) {
- ERRNO_ERR("failed to open path: <%s>", ii_buffer->tmpfpath);
+ ERRNO_ERR("failed to open path: <%-.256s>", ii_buffer->tmpfpath);
return ctx->rc;
}
{
@@ -10358,10 +10358,10 @@ grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
grn_close(ii_buffer->tmpfd);
if (grn_unlink(ii_buffer->tmpfpath) == 0) {
GRN_LOG(ctx, GRN_LOG_INFO,
- "[ii][buffer][commit] removed temporary path: <%s>",
+ "[ii][buffer][commit] removed temporary path: <%-.256s>",
ii_buffer->tmpfpath);
} else {
- ERRNO_ERR("[ii][buffer][commit] failed to remove temporary path: <%s>",
+ ERRNO_ERR("[ii][buffer][commit] failed to remove temporary path: <%-.256s>",
ii_buffer->tmpfpath);
}
ii_buffer->tmpfd = -1;
@@ -10385,10 +10385,10 @@ grn_ii_buffer_close(grn_ctx *ctx, grn_ii_buffer *ii_buffer)
grn_close(ii_buffer->tmpfd);
if (grn_unlink(ii_buffer->tmpfpath) == 0) {
GRN_LOG(ctx, GRN_LOG_INFO,
- "[ii][buffer][close] removed temporary path: <%s>",
+ "[ii][buffer][close] removed temporary path: <%-.256s>",
ii_buffer->tmpfpath);
} else {
- ERRNO_ERR("[ii][buffer][close] failed to remove temporary path: <%s>",
+ ERRNO_ERR("[ii][buffer][close] failed to remove temporary path: <%-.256s>",
ii_buffer->tmpfpath);
}
}
@@ -11468,10 +11468,10 @@ grn_ii_builder_fin(grn_ctx *ctx, grn_ii_builder *builder)
grn_close(builder->fd);
if (grn_unlink(builder->path) == 0) {
GRN_LOG(ctx, GRN_LOG_INFO,
- "[ii][builder][fin] removed path: <%s>",
+ "[ii][builder][fin] removed path: <%-.256s>",
builder->path);
} else {
- ERRNO_ERR("[ii][builder][fin] failed to remove path: <%s>",
+ ERRNO_ERR("[ii][builder][fin] failed to remove path: <%-.256s>",
builder->path);
}
}
@@ -11779,10 +11779,10 @@ static grn_rc
grn_ii_builder_create_file(grn_ctx *ctx, grn_ii_builder *builder)
{
grn_snprintf(builder->path, PATH_MAX, PATH_MAX,
- "%sXXXXXX", grn_io_path(builder->ii->seg));
+ "%-.256sXXXXXX", grn_io_path(builder->ii->seg));
builder->fd = grn_mkstemp(builder->path);
if (builder->fd == -1) {
- SERR("failed to create a temporary file: path = \"%s\"",
+ SERR("failed to create a temporary file: path = \"%-.256s\"",
builder->path);
return ctx->rc;
}
diff --git a/storage/mroonga/vendor/groonga/vendor/plugins/CMakeLists.txt b/storage/mroonga/vendor/groonga/vendor/plugins/CMakeLists.txt
index e4428b577f8..199baee8e86 100644
--- a/storage/mroonga/vendor/groonga/vendor/plugins/CMakeLists.txt
+++ b/storage/mroonga/vendor/groonga/vendor/plugins/CMakeLists.txt
@@ -15,11 +15,12 @@
file(GLOB
PLUGIN_CMAKE_LISTS_LIST
+ RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/*/CMakeLists.txt")
if(PLUGIN_CMAKE_LISTS_LIST)
foreach(PLUGIN_CMAKE_LISTS "${PLUGIN_CMAKE_LISTS_LIST}")
string(REGEX REPLACE
- "(^${CMAKE_CURRENT_SOURCE_DIR}/+|/+CMakeLists\\.txt$)" ""
+ "(/+CMakeLists\\.txt$)" ""
PLUGIN_DIR
"${PLUGIN_CMAKE_LISTS}")
add_subdirectory("${PLUGIN_DIR}")
diff --git a/storage/myisam/TODO b/storage/myisam/TODO
deleted file mode 100644
index cad9486e1bb..00000000000
--- a/storage/myisam/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-
-- Let packisam find the optimal way to store keys.
-- kill when using 'myisamchk' should remove all temporary files.
-- Text search index
- (Sergei A. Golub is working on this)
-- Add '%' packed to myisamchk for compressed tables with blobs.
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index fd2e8fd9425..f5f36266347 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -96,6 +96,10 @@ static MYSQL_THDVAR_ENUM(stats_method, PLUGIN_VAR_RQCMDARG,
"and NULLS_IGNORED", NULL, NULL,
MI_STATS_METHOD_NULLS_NOT_EQUAL, &myisam_stats_method_typelib);
+const char *MI_CHECK_INFO= "info";
+const char *MI_CHECK_WARNING= "warning";
+const char *MI_CHECK_ERROR= "error";
+
#ifndef DBUG_OFF
/**
Causes the thread to wait in a spin lock for a query kill signal.
@@ -130,6 +134,20 @@ static handler *myisam_create_handler(handlerton *hton,
return new (mem_root) ha_myisam(hton, table);
}
+
+static void mi_check_print(HA_CHECK *param, const char* msg_type,
+ const char *msgbuf)
+{
+ if (msg_type == MI_CHECK_INFO)
+ sql_print_information("%s.%s: %s", param->db_name, param->table_name,
+ msgbuf);
+ else if (msg_type == MI_CHECK_WARNING)
+ sql_print_warning("%s.%s: %s", param->db_name, param->table_name,
+ msgbuf);
+ else
+ sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+}
+
// collect errors printed by mi_check routines
static void mi_check_print_msg(HA_CHECK *param, const char* msg_type,
@@ -151,16 +169,21 @@ static void mi_check_print_msg(HA_CHECK *param, const char* msg_type,
if (!thd->vio_ok())
{
- sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+ mi_check_print(param, msg_type, msgbuf);
return;
}
if (param->testflag & (T_CREATE_MISSING_KEYS | T_SAFE_REPAIR |
T_AUTO_REPAIR))
{
- my_message(ER_NOT_KEYFILE, msgbuf, MYF(MY_WME));
+ myf flag= 0;
+ if (msg_type == MI_CHECK_INFO)
+ flag= ME_NOTE;
+ else if (msg_type == MI_CHECK_WARNING)
+ flag= ME_WARNING;
+ my_message(ER_NOT_KEYFILE, msgbuf, MYF(flag));
if (thd->variables.log_warnings > 2 && ! thd->log_all_errors)
- sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+ mi_check_print(param, msg_type, msgbuf);
return;
}
length=(uint) (strxmov(name, param->db_name,".",param->table_name,NullS) -
@@ -185,7 +208,7 @@ static void mi_check_print_msg(HA_CHECK *param, const char* msg_type,
sql_print_error("Failed on my_net_write, writing to stderr instead: %s\n",
msgbuf);
else if (thd->variables.log_warnings > 2)
- sql_print_error("%s.%s: %s", param->db_name, param->table_name, msgbuf);
+ mi_check_print(param, msg_type, msgbuf);
if (param->need_print_msg_lock)
mysql_mutex_unlock(&param->print_msg_mutex);
@@ -592,7 +615,7 @@ void mi_check_print_error(HA_CHECK *param, const char *fmt,...)
return;
va_list args;
va_start(args, fmt);
- mi_check_print_msg(param, "error", fmt, args);
+ mi_check_print_msg(param, MI_CHECK_ERROR, fmt, args);
va_end(args);
}
@@ -600,7 +623,7 @@ void mi_check_print_info(HA_CHECK *param, const char *fmt,...)
{
va_list args;
va_start(args, fmt);
- mi_check_print_msg(param, "info", fmt, args);
+ mi_check_print_msg(param, MI_CHECK_INFO, fmt, args);
param->note_printed= 1;
va_end(args);
}
@@ -611,7 +634,7 @@ void mi_check_print_warning(HA_CHECK *param, const char *fmt,...)
param->out_flag|= O_DATA_LOST;
va_list args;
va_start(args, fmt);
- mi_check_print_msg(param, "warning", fmt, args);
+ mi_check_print_msg(param, MI_CHECK_WARNING, fmt, args);
va_end(args);
}
@@ -747,7 +770,8 @@ ulong ha_myisam::index_flags(uint inx, uint part, bool all_parts) const
else
{
flags= HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
- HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN;
+ HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN |
+ HA_DO_RANGE_FILTER_PUSHDOWN;
}
return flags;
}
@@ -910,7 +934,7 @@ int ha_myisam::close(void)
return mi_close(tmp);
}
-int ha_myisam::write_row(uchar *buf)
+int ha_myisam::write_row(const uchar *buf)
{
/*
If we have an auto_increment column and we are writing a changed row
@@ -951,7 +975,6 @@ void ha_myisam::setup_vcols_for_repair(HA_CHECK *param)
DBUG_ASSERT(file->s->base.reclength < file->s->vreclength);
param->fix_record= compute_vcols;
table->use_all_columns();
- table->vcol_set= &table->s->all_set;
}
void ha_myisam::restore_vcos_after_repair()
@@ -1042,6 +1065,15 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt)
mysql_mutex_unlock(&share->intern_lock);
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
HA_STATUS_CONST);
+ /*
+ Write a 'table is ok' message to error log if table is ok and
+ we have written to error log that table was getting checked
+ */
+ if (!error && !(table->db_stat & HA_READ_ONLY) &&
+ !mi_is_crashed(file) && thd->error_printed_to_log &&
+ (param->warning_printed || param->error_printed ||
+ param->note_printed))
+ mi_check_print_info(param, "Table is fixed");
}
}
else if (!mi_is_crashed(file) && !thd->killed)
@@ -1718,7 +1750,35 @@ void ha_myisam::start_bulk_insert(ha_rows rows, uint flags)
else
{
my_bool all_keys= MY_TEST(flags & HA_CREATE_UNIQUE_INDEX_BY_SORT);
- mi_disable_indexes_for_rebuild(file, rows, all_keys);
+ MYISAM_SHARE *share=file->s;
+ MI_KEYDEF *key=share->keyinfo;
+ uint i;
+ /*
+ Deactivate all indexes that can be recreated fast.
+ These include packed keys on which sorting will use more temporary
+ space than the max allowed file length or for which the unpacked keys
+ will take much more space than packed keys.
+ Note that 'rows' may be zero for the case when we don't know how many
+ rows we will put into the file.
+ Long Unique Index (HA_KEY_ALG_LONG_HASH) will not be disabled because
+ there unique property is enforced at the time of ha_write_row
+ (check_duplicate_long_entries). So we need active index at the time of
+ insert.
+ */
+ DBUG_ASSERT(file->state->records == 0 &&
+ (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
+ for (i=0 ; i < share->base.keys ; i++,key++)
+ {
+ if (!(key->flag & (HA_SPATIAL | HA_AUTO_KEY)) &&
+ ! mi_too_big_key_for_sort(key,rows) && file->s->base.auto_key != i+1 &&
+ (all_keys || !(key->flag & HA_NOSAME)) &&
+ table->key_info[i].algorithm != HA_KEY_ALG_LONG_HASH)
+ {
+ mi_clear_key_active(share->state.key_map, i);
+ file->update|= HA_STATE_CHANGED;
+ file->create_unique_index_by_sort= all_keys;
+ }
+ }
}
}
else
@@ -1816,7 +1876,7 @@ bool ha_myisam::check_and_repair(THD *thd)
sql_print_information("Making backup of index file %s with extension '%s'",
file->s->index_file_name, buff);
mi_make_backup_of_index(file, check_opt.start_time,
- MYF(MY_WME | ME_JUST_WARNING));
+ MYF(MY_WME | ME_WARNING));
}
check_opt.flags=
(((myisam_recover_options &
@@ -1854,6 +1914,9 @@ int ha_myisam::index_init(uint idx, bool sorted)
active_index=idx;
if (pushed_idx_cond_keyno == idx)
mi_set_index_cond_func(file, handler_index_cond_check, this);
+ if (pushed_rowid_filter)
+ mi_set_rowid_filter_func(file, handler_rowid_filter_check,
+ handler_rowid_filter_is_active, this);
return 0;
}
@@ -1865,6 +1928,7 @@ int ha_myisam::index_end()
//pushed_idx_cond_keyno= MAX_KEY;
mi_set_index_cond_func(file, NULL, 0);
in_range_check_pushed_down= FALSE;
+ mi_set_rowid_filter_func(file, NULL, NULL, 0);
ds_mrr.dsmrr_close();
#if !defined(DBUG_OFF) && defined(SQL_SELECT_FIXED_FOR_UPDATE)
file->update&= ~HA_STATE_AKTIV; // Forget active row
@@ -1900,6 +1964,9 @@ int ha_myisam::index_read_idx_map(uchar *buf, uint index, const uchar *key,
end_range= NULL;
if (index == pushed_idx_cond_keyno)
mi_set_index_cond_func(file, handler_index_cond_check, this);
+ if (pushed_rowid_filter)
+ mi_set_rowid_filter_func(file, handler_rowid_filter_check,
+ handler_rowid_filter_is_active, this);
res= mi_rkey(file, buf, index, key, keypart_map, find_flag);
mi_set_index_cond_func(file, NULL, 0);
return res;
@@ -2560,6 +2627,14 @@ Item *ha_myisam::idx_cond_push(uint keyno_arg, Item* idx_cond_arg)
return NULL;
}
+bool ha_myisam::rowid_filter_push(Rowid_filter* rowid_filter)
+{
+ pushed_rowid_filter= rowid_filter;
+ mi_set_rowid_filter_func(file, handler_rowid_filter_check,
+ handler_rowid_filter_is_active, this);
+ return false;
+}
+
struct st_mysql_storage_engine myisam_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
@@ -2650,7 +2725,7 @@ my_bool ha_myisam::register_query_cache_table(THD *thd, const char *table_name,
If the table size is unknown the SELECT statement can't be cached.
- When concurrent inserts are disabled at table open, mi_open()
+ When concurrent inserts are disabled at table open, mi_ondopen()
does not assign a get_status() function. In this case the local
("current") status is never updated. We would wrongly think that
we cannot cache the statement.
diff --git a/storage/myisam/ha_myisam.h b/storage/myisam/ha_myisam.h
index c6e26cf0030..0af4215e8f9 100644
--- a/storage/myisam/ha_myisam.h
+++ b/storage/myisam/ha_myisam.h
@@ -69,7 +69,7 @@ class ha_myisam: public handler
void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
int open(const char *name, int mode, uint test_if_locked);
int close(void);
- int write_row(uchar * buf);
+ int write_row(const uchar * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
@@ -171,6 +171,8 @@ public:
/* Index condition pushdown implementation */
Item *idx_cond_push(uint keyno, Item* idx_cond);
+ bool rowid_filter_push(Rowid_filter* rowid_filter);
+
private:
DsMrr_impl ds_mrr;
friend ICP_RESULT index_cond_func_myisam(void *arg);
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index eac50c4a04c..3f3c60a4249 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -99,6 +99,9 @@ int chk_status(HA_CHECK *param, register MI_INFO *info)
{
MYISAM_SHARE *share=info->s;
+ /* Protection for HA_EXTRA_FLUSH */
+ mysql_mutex_lock(&share->intern_lock);
+
if (mi_is_crashed_on_repair(info))
mi_check_print_warning(param,
"Table is marked as crashed and last repair failed");
@@ -118,6 +121,7 @@ int chk_status(HA_CHECK *param, register MI_INFO *info)
if (param->testflag & T_UPDATE_STATE)
param->warning_printed=save;
}
+ mysql_mutex_unlock(&share->intern_lock);
return 0;
}
@@ -4663,7 +4667,7 @@ static ha_checksum mi_byte_checksum(const uchar *buf, uint length)
return crc;
}
-static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
+my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
{
uint key_maxlength=key->maxlength;
if (key->flag & HA_FULLTEXT)
@@ -4678,38 +4682,6 @@ static my_bool mi_too_big_key_for_sort(MI_KEYDEF *key, ha_rows rows)
}
/*
- Deactivate all indexes that can be recreated fast.
- These include packed keys on which sorting will use more temporary
- space than the max allowed file length or for which the unpacked keys
- will take much more space than packed keys.
- Note that 'rows' may be zero for the case when we don't know how many
- rows we will put into the file.
- */
-
-void mi_disable_indexes_for_rebuild(MI_INFO *info, ha_rows rows,
- my_bool all_keys)
-{
- MYISAM_SHARE *share=info->s;
- MI_KEYDEF *key=share->keyinfo;
- uint i;
-
- DBUG_ASSERT(info->state->records == 0 &&
- (!rows || rows >= MI_MIN_ROWS_TO_DISABLE_INDEXES));
- for (i=0 ; i < share->base.keys ; i++,key++)
- {
- if (!(key->flag & (HA_SPATIAL | HA_AUTO_KEY)) &&
- ! mi_too_big_key_for_sort(key,rows) && info->s->base.auto_key != i+1 &&
- (all_keys || !(key->flag & HA_NOSAME)))
- {
- mi_clear_key_active(share->state.key_map, i);
- info->update|= HA_STATE_CHANGED;
- info->create_unique_index_by_sort= all_keys;
- }
- }
-}
-
-
-/*
Return TRUE if we can use repair by sorting
One can set the force argument to force to use sorting
even if the temporary file would be quite big!
@@ -4779,7 +4751,7 @@ static int replace_data_file(HA_CHECK *param, MI_INFO *info, File new_file)
my_create_backup_name(buff, "", param->backup_time);
my_printf_error(ER_GET_ERRMSG,
"Making backup of data file %s with extension '%s'",
- MYF(ME_JUST_INFO | ME_NOREFRESH), share->data_file_name,
+ MYF(ME_NOTE | ME_ERROR_LOG), share->data_file_name,
buff);
}
diff --git a/storage/myisam/mi_extra.c b/storage/myisam/mi_extra.c
index 07592ced5db..d1bf903bd46 100644
--- a/storage/myisam/mi_extra.c
+++ b/storage/myisam/mi_extra.c
@@ -331,7 +331,11 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (!share->temporary)
flush_key_blocks(share->key_cache, share->kfile, &share->dirty_part_map,
FLUSH_KEEP);
+ mysql_mutex_lock(&share->intern_lock);
+ /* Tell mi_lock_database() that we locked the intern_lock mutex */
+ info->intern_lock_locked= 1;
_mi_decrement_open_count(info);
+ info->intern_lock_locked= 0;
if (share->not_flushed)
{
share->not_flushed=0;
@@ -348,6 +352,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
}
if (share->base.blobs)
mi_alloc_rec_buff(info, -1, &info->rec_buff);
+ mysql_mutex_unlock(&share->intern_lock);
break;
case HA_EXTRA_NORMAL: /* These aren't in use */
info->quick_mode=0;
@@ -417,6 +422,16 @@ void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func,
info->index_cond_func_arg= func_arg;
}
+void mi_set_rowid_filter_func(MI_INFO *info,
+ rowid_filter_func_t check_func,
+ rowid_filter_func_t is_active_func,
+ void *func_arg)
+{
+ info->rowid_filter_func= check_func;
+ info->rowid_filter_is_active_func= is_active_func;
+ info->rowid_filter_func_arg= func_arg;
+}
+
/*
Start/Stop Inserting Duplicates Into a Table, WL#1648.
*/
diff --git a/storage/myisam/mi_info.c b/storage/myisam/mi_info.c
index 29d2283bc85..50cb5439472 100644
--- a/storage/myisam/mi_info.c
+++ b/storage/myisam/mi_info.c
@@ -127,7 +127,7 @@ void mi_report_error(int errcode, const char *file_name)
if ((lgt= strlen(file_name)) > 64)
file_name+= lgt - 64;
- my_error(errcode, MYF(ME_NOREFRESH), file_name);
+ my_error(errcode, MYF(ME_ERROR_LOG), file_name);
DBUG_VOID_RETURN;
}
diff --git a/storage/myisam/mi_key.c b/storage/myisam/mi_key.c
index c18b832be0f..dd838a05ada 100644
--- a/storage/myisam/mi_key.c
+++ b/storage/myisam/mi_key.c
@@ -529,6 +529,19 @@ ICP_RESULT mi_check_index_cond(register MI_INFO *info, uint keynr,
return res;
}
+
+int mi_check_rowid_filter(MI_INFO *info)
+{
+ return info->rowid_filter_func(info->rowid_filter_func_arg);
+}
+
+int mi_check_rowid_filter_is_active(MI_INFO *info)
+{
+ if (info->rowid_filter_is_active_func == NULL)
+ return 0;
+ return info->rowid_filter_is_active_func(info->rowid_filter_func_arg);
+}
+
/*
Retrieve auto_increment info
diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c
index 55185b67535..713ba0a3851 100644
--- a/storage/myisam/mi_locking.c
+++ b/storage/myisam/mi_locking.c
@@ -53,7 +53,8 @@ int mi_lock_database(MI_INFO *info, int lock_type)
error= 0;
DBUG_EXECUTE_IF ("mi_lock_database_failure", error= EINVAL;);
- mysql_mutex_lock(&share->intern_lock);
+ if (!info->intern_lock_locked)
+ mysql_mutex_lock(&share->intern_lock);
if (share->kfile >= 0) /* May only be false on windows */
{
switch (lock_type) {
@@ -261,7 +262,8 @@ int mi_lock_database(MI_INFO *info, int lock_type)
}
}
#endif
- mysql_mutex_unlock(&share->intern_lock);
+ if (!info->intern_lock_locked)
+ mysql_mutex_unlock(&share->intern_lock);
if (mark_crashed)
mi_mark_crashed(info);
DBUG_RETURN(error);
diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c
index de76c4cee93..7292f3c83b8 100644
--- a/storage/myisam/mi_range.c
+++ b/storage/myisam/mi_range.c
@@ -1,5 +1,6 @@
/*
Copyright (c) 2000, 2011, Oracle and/or its affiliates
+ Copyright (c) 2010, 2020, 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
@@ -22,9 +23,10 @@
#include "myisamdef.h"
#include "rt_index.h"
-static ha_rows _mi_record_pos(MI_INFO *, const uchar *, key_part_map,
- enum ha_rkey_function);
-static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,my_off_t);
+static double _mi_record_pos(MI_INFO *, const uchar *, key_part_map,
+ enum ha_rkey_function);
+static double _mi_search_pos(MI_INFO *,MI_KEYDEF *,uchar *, uint,uint,
+ my_off_t,my_bool);
static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *);
/*
@@ -48,7 +50,8 @@ static uint _mi_keynr(MI_INFO *info,MI_KEYDEF *,uchar *, uchar *,uint *);
ha_rows mi_records_in_range(MI_INFO *info, int inx,
key_range *min_key, key_range *max_key)
{
- ha_rows start_pos,end_pos,res;
+ ha_rows res;
+ double start_pos,end_pos,diff;
DBUG_ENTER("mi_records_in_range");
if ((inx = _mi_check_index(info,inx)) < 0)
@@ -94,16 +97,27 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx,
#endif
case HA_KEY_ALG_BTREE:
default:
- start_pos= (min_key ? _mi_record_pos(info, min_key->key,
- min_key->keypart_map, min_key->flag)
- : (ha_rows) 0);
+ start_pos= (min_key ?_mi_record_pos(info, min_key->key,
+ min_key->keypart_map, min_key->flag)
+ : (double) 0);
end_pos= (max_key ? _mi_record_pos(info, max_key->key,
max_key->keypart_map, max_key->flag)
- : info->state->records + (ha_rows) 1);
+ : (double) info->state->records);
res= (end_pos < start_pos ? (ha_rows) 0 :
- (end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
- if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
+ (end_pos == start_pos ? (ha_rows) 1 : (ha_rows) (end_pos-start_pos)));
+ if (start_pos == (double) HA_POS_ERROR || end_pos == (double) HA_POS_ERROR)
res=HA_POS_ERROR;
+ else
+ {
+ diff= end_pos - start_pos;
+ if (diff >= 0)
+ {
+ if (!(res= (ha_rows) (diff + 0.5)))
+ res= 1;
+ }
+ else
+ res= 0;
+ }
}
if (info->s->concurrent_insert)
@@ -115,11 +129,25 @@ ha_rows mi_records_in_range(MI_INFO *info, int inx,
}
- /* Find relative position (in records) for key in index-tree */
+/*
+ To find an approximate relative position of a key tuple among all index
+ key tuples would not be hard if we considered B-trees where all key
+ tuples were contained only in leaf nodes. If we consider a B-tree where
+ key tuples are stored also in non-leaf nodes we have to convert such
+ tree into the tree of the first type. The transformation procedure is
+ simple: the key tuple k goes alter the last key tuple in the most right
+ sub-tree pointer to which is coupled with k. As a result of this
+ transformation each leaf node except the most right one in the tree will
+ contain one extra key tuple following those originally belonging to
+ the leaf.
+*/
+
+
+/* Find relative position (in records) for key in index-tree */
-static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
- key_part_map keypart_map,
- enum ha_rkey_function search_flag)
+static double _mi_record_pos(MI_INFO *info, const uchar *key,
+ key_part_map keypart_map,
+ enum ha_rkey_function search_flag)
{
uint inx=(uint) info->lastinx, nextflag, key_len;
MI_KEYDEF *keyinfo=info->s->keyinfo+inx;
@@ -175,13 +203,13 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
*/
pos=_mi_search_pos(info,keyinfo,key_buff,key_len,
nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE,
- info->s->state.key_root[inx]);
+ info->s->state.key_root[inx], TRUE);
if (pos >= 0.0)
{
- DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records)));
- DBUG_RETURN((ulong) (pos*info->state->records+0.5));
+ DBUG_PRINT("exit",("pos: %g",(pos*info->state->records)));
+ DBUG_RETURN(pos*info->state->records);
}
- DBUG_RETURN(HA_POS_ERROR);
+ DBUG_RETURN((double) (HA_POS_ERROR));
}
@@ -191,7 +219,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
static double _mi_search_pos(register MI_INFO *info,
register MI_KEYDEF *keyinfo,
uchar *key, uint key_len, uint nextflag,
- register my_off_t pos)
+ register my_off_t pos, my_bool last_in_level)
{
int flag;
uint nod_flag,keynr,UNINIT_VAR(max_keynr);
@@ -222,7 +250,8 @@ static double _mi_search_pos(register MI_INFO *info,
if (flag > 0 && ! nod_flag)
offset= 1.0;
else if ((offset=_mi_search_pos(info,keyinfo,key,key_len,nextflag,
- _mi_kpos(nod_flag,keypos))) < 0)
+ _mi_kpos(nod_flag,keypos),
+ last_in_level && after_key)) < 0)
DBUG_RETURN(offset);
}
else
@@ -241,13 +270,15 @@ static double _mi_search_pos(register MI_INFO *info,
Matches keynr + [0-1]
*/
if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
- _mi_kpos(nod_flag,keypos))) < 0)
+ _mi_kpos(nod_flag,keypos),
+ last_in_level && after_key)) < 0)
DBUG_RETURN(offset); /* Read error */
}
}
DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d",
keynr,offset,max_keynr,nod_flag,flag));
- DBUG_RETURN((keynr+offset)/(max_keynr+1));
+ DBUG_RETURN((keynr+offset-MY_TEST(!nod_flag))/
+ (max_keynr+MY_TEST(nod_flag || !last_in_level)));
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
DBUG_RETURN (-1.0);
diff --git a/storage/myisam/mi_rkey.c b/storage/myisam/mi_rkey.c
index 897138e4f62..8ef1d917f38 100644
--- a/storage/myisam/mi_rkey.c
+++ b/storage/myisam/mi_rkey.c
@@ -120,7 +120,9 @@ int mi_rkey(MI_INFO *info, uchar *buf, int inx, const uchar *key,
(search_flag != HA_READ_KEY_EXACT ||
last_used_keyseg != keyinfo->seg + keyinfo->keysegs)) ||
(info->index_cond_func &&
- (res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
+ (res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) ||
+ (mi_check_rowid_filter_is_active(info) &&
+ !mi_check_rowid_filter(info)))
{
uint not_used[2];
/*
diff --git a/storage/myisam/mi_rnext.c b/storage/myisam/mi_rnext.c
index 4b4e1893a61..9f5f4702ed2 100644
--- a/storage/myisam/mi_rnext.c
+++ b/storage/myisam/mi_rnext.c
@@ -102,7 +102,9 @@ int mi_rnext(MI_INFO *info, uchar *buf, int inx)
while ((info->s->concurrent_insert &&
info->lastpos >= info->state->data_file_length) ||
(info->index_cond_func &&
- (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
+ (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) ||
+ (mi_check_rowid_filter_is_active(info) &&
+ !mi_check_rowid_filter(info)))
{
/*
If we are at the last key on the key page, allow writers to
diff --git a/storage/myisam/mi_rnext_same.c b/storage/myisam/mi_rnext_same.c
index ed9e3c55b2f..ee6b962c8c3 100644
--- a/storage/myisam/mi_rnext_same.c
+++ b/storage/myisam/mi_rnext_same.c
@@ -95,7 +95,9 @@ int mi_rnext_same(MI_INFO *info, uchar *buf)
*/
if (info->lastpos < info->state->data_file_length &&
(!info->index_cond_func ||
- (icp_res= mi_check_index_cond(info, inx, buf)) != ICP_NO_MATCH))
+ (icp_res= mi_check_index_cond(info, inx, buf)) != ICP_NO_MATCH) &&
+ (!mi_check_rowid_filter_is_active(info) ||
+ mi_check_rowid_filter(info)))
break;
}
}
diff --git a/storage/myisam/mi_rprev.c b/storage/myisam/mi_rprev.c
index 765f8a5d79f..cac0d672765 100644
--- a/storage/myisam/mi_rprev.c
+++ b/storage/myisam/mi_rprev.c
@@ -59,7 +59,9 @@ int mi_rprev(MI_INFO *info, uchar *buf, int inx)
while ((share->concurrent_insert &&
info->lastpos >= info->state->data_file_length) ||
(info->index_cond_func &&
- (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH))
+ (icp_res= mi_check_index_cond(info, inx, buf)) == ICP_NO_MATCH) ||
+ (mi_check_rowid_filter_is_active(info) &&
+ !mi_check_rowid_filter(info)))
{
/*
If we are at the last (i.e. first?) key on the key page,
diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c
index f08dea77354..7345ab1604d 100644
--- a/storage/myisam/mi_write.c
+++ b/storage/myisam/mi_write.c
@@ -40,7 +40,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr,uchar *key,
/* Write new record to database */
-int mi_write(MI_INFO *info, uchar *record)
+int mi_write(MI_INFO *info, const uchar *record)
{
MYISAM_SHARE *share=info->s;
uint i;
diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h
index d02d2d78c5d..f7b61ae638c 100644
--- a/storage/myisam/myisamdef.h
+++ b/storage/myisam/myisamdef.h
@@ -296,6 +296,7 @@ struct st_myisam_info
uint preload_buff_size; /* When preloading indexes */
myf lock_wait; /* is 0 or MY_SHORT_WAIT */
my_bool was_locked; /* Was locked in panic */
+ my_bool intern_lock_locked; /* locked in mi_extra() */
my_bool append_insert_at_end; /* Set if concurrent insert */
my_bool quick_mode;
/* If info->buff can't be used for rnext */
@@ -305,6 +306,9 @@ struct st_myisam_info
my_bool create_unique_index_by_sort;
index_cond_func_t index_cond_func; /* Index condition function */
void *index_cond_func_arg; /* parameter for the func */
+ rowid_filter_func_t rowid_filter_func; /* rowid filter check function */
+ rowid_filter_func_t rowid_filter_is_active_func; /* is activefunction */
+ void *rowid_filter_func_arg; /* parameter for the func */
THR_LOCK_DATA lock;
uchar *rtree_recursion_state; /* For RTREE */
int rtree_recursion_depth;
@@ -711,8 +715,6 @@ void mi_restore_status(void *param);
void mi_copy_status(void *to, void *from);
my_bool mi_check_status(void *param);
void mi_fix_status(MI_INFO *org_table, MI_INFO *new_table);
-void mi_disable_indexes_for_rebuild(MI_INFO *info, ha_rows rows,
- my_bool all_keys);
extern MI_INFO *test_if_reopen(char *filename);
my_bool check_table_is_closed(const char *name, const char *where);
int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share);
@@ -724,14 +726,20 @@ int mi_munmap_file(MI_INFO *info);
void mi_remap_file(MI_INFO *info, my_off_t size);
ICP_RESULT mi_check_index_cond(MI_INFO *info, uint keynr, uchar *record);
+int mi_check_rowid_filter(MI_INFO *info);
+int mi_check_rowid_filter_is_active(MI_INFO *info);
/* Functions needed by mi_check */
int killed_ptr(HA_CHECK *param);
void mi_check_print_error(HA_CHECK *param, const char *fmt, ...);
void mi_check_print_warning(HA_CHECK *param, const char *fmt, ...);
void mi_check_print_info(HA_CHECK *param, const char *fmt, ...);
pthread_handler_t thr_find_all_keys(void *arg);
-extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t func,
+extern void mi_set_index_cond_func(MI_INFO *info, index_cond_func_t check_func,
void *func_arg);
+extern void mi_set_rowid_filter_func(MI_INFO *info,
+ rowid_filter_func_t check_func,
+ rowid_filter_func_t is_active_func,
+ void *func_arg);
int flush_blocks(HA_CHECK *param, KEY_CACHE *key_cache, File file,
ulonglong *dirty_part_map);
diff --git a/storage/myisam/myisamlog.c b/storage/myisam/myisamlog.c
index 8e8b75817c0..9bef2be929f 100644
--- a/storage/myisam/myisamlog.c
+++ b/storage/myisam/myisamlog.c
@@ -750,7 +750,8 @@ static int test_when_accessed (struct file_info *key,
}
-static int file_info_free(void* arg, TREE_FREE mode, void *unused)
+static int file_info_free(void* arg, TREE_FREE mode __attribute__((unused)),
+ void *unused __attribute__((unused)))
{
struct file_info *fileinfo= arg;
DBUG_ENTER("file_info_free");
diff --git a/storage/myisam/myisampack.c b/storage/myisam/myisampack.c
index 5d122cb9d97..ba6744ae815 100644
--- a/storage/myisam/myisampack.c
+++ b/storage/myisam/myisampack.c
@@ -2148,7 +2148,7 @@ static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
*/
if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2)))
{
- my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATALERROR),
+ my_error(EE_OUTOFMEMORY, MYF(ME_BELL+ME_FATAL),
sizeof(uint)*length*2);
return 0;
}
diff --git a/storage/myisam/sort.c b/storage/myisam/sort.c
index 13b8f17ea0f..e586543363b 100644
--- a/storage/myisam/sort.c
+++ b/storage/myisam/sort.c
@@ -28,12 +28,10 @@
/* static variables */
-#undef MYF_RW
#undef DISK_BUFFER_SIZE
#define MERGEBUFF 15
#define MERGEBUFF2 31
-#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
#define DISK_BUFFER_SIZE (IO_SIZE*128)
/* How many keys we can keep in memory */
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index 8f5e65084ce..14036a31b8c 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -1088,7 +1088,7 @@ int ha_myisammrg::close(void)
DBUG_RETURN(rc);
}
-int ha_myisammrg::write_row(uchar * buf)
+int ha_myisammrg::write_row(const uchar * buf)
{
DBUG_ENTER("ha_myisammrg::write_row");
DBUG_ASSERT(this->file->children_attached);
diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h
index 7cb2b0f1993..b7cbd6c7d12 100644
--- a/storage/myisammrg/ha_myisammrg.h
+++ b/storage/myisammrg/ha_myisammrg.h
@@ -111,7 +111,7 @@ public:
int detach_children(void);
virtual handler *clone(const char *name, MEM_ROOT *mem_root);
int close(void);
- int write_row(uchar * buf);
+ int write_row(const uchar * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
diff --git a/storage/myisammrg/myrg_write.c b/storage/myisammrg/myrg_write.c
index eb496911a52..e511d60d634 100644
--- a/storage/myisammrg/myrg_write.c
+++ b/storage/myisammrg/myrg_write.c
@@ -18,7 +18,7 @@
#include "myrg_def.h"
-int myrg_write(register MYRG_INFO *info, uchar *rec)
+int myrg_write(register MYRG_INFO *info, const uchar *rec)
{
/* [phi] MERGE_WRITE_DISABLED is handled by the else case */
if (info->merge_insert_method == MERGE_INSERT_TO_FIRST)
diff --git a/storage/oqgraph/CMakeLists.txt b/storage/oqgraph/CMakeLists.txt
index 638ac00dc01..68582e2802d 100644
--- a/storage/oqgraph/CMakeLists.txt
+++ b/storage/oqgraph/CMakeLists.txt
@@ -1,6 +1,6 @@
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
-FUNCTION(CHECK_OQGRAPH)
+MACRO(CHECK_OQGRAPH)
MESSAGE(STATUS "Configuring OQGraph")
FIND_PACKAGE(Boost 1.40.0)
IF(NOT Boost_FOUND)
@@ -17,27 +17,8 @@ IF(NOT Judy_FOUND)
RETURN()
ENDIF()
INCLUDE_DIRECTORIES(${Judy_INCLUDE_DIR})
-
-IF(MSVC)
-# # lp:756966 OQGRAPH on Win64 does not compile
-# IF (CMAKE_SIZEOF_VOID_P EQUAL 8)
-# SET(OQGRAPH_OK 0 CACHE INTERNAL "")
-# ELSE()
- SET(OQGRAPH_OK 1 CACHE INTERNAL "")
-# ENDIF()
-ELSE()
-# See if that works. On old gcc it'll fail because of -fno-rtti
-SET(CMAKE_REQUIRED_INCLUDES "${Boost_INCLUDE_DIRS}")
-CHECK_CXX_SOURCE_COMPILES(
-"
-#define BOOST_NO_RTTI 1
-#define BOOST_NO_TYPEID 1
-#include <boost/config.hpp>
-#include <boost/property_map/property_map.hpp>
-int main() { return 0; }
-" OQGRAPH_OK)
-ENDIF()
-ENDFUNCTION()
+SET(OQGRAPH_OK 1)
+ENDMACRO()
IF(NOT DEFINED OQGRAPH_OK)
CHECK_OQGRAPH()
@@ -57,7 +38,7 @@ IF(MSVC)
ADD_DEFINITIONS(-DJU_WIN)
ELSE(MSVC)
# Fix lp bug 1221555 with -fpermissive, so that errors in gcc 4.7 become warnings for the time being
- STRING(REPLACE "-fno-exceptions" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+ STRING(REPLACE "-fno-exceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -fno-strict-aliasing -fpermissive")
ENDIF(MSVC)
diff --git a/storage/oqgraph/ha_oqgraph.cc b/storage/oqgraph/ha_oqgraph.cc
index 3cb47e204a0..fd715c57a1f 100644
--- a/storage/oqgraph/ha_oqgraph.cc
+++ b/storage/oqgraph/ha_oqgraph.cc
@@ -799,7 +799,7 @@ void ha_oqgraph::update_key_stats()
}
-int ha_oqgraph::write_row(byte * buf)
+int ha_oqgraph::write_row(const byte * buf)
{
return HA_ERR_TABLE_READONLY;
}
@@ -1211,7 +1211,7 @@ ha_rows ha_oqgraph::records_in_range(uint inx, key_range *min_key,
min_key->flag != HA_READ_KEY_EXACT ||
max_key->flag != HA_READ_AFTER_KEY)
{
- if (min_key->length == key->key_part[0].store_length && !key->key_part[0].field->is_null()) /* ensure select * from x where latch is null is consistent with no latch */
+ if (min_key && min_key->length == key->key_part[0].store_length && !key->key_part[0].field->is_null()) /* ensure select * from x where latch is null is consistent with no latch */
{
// If latch is not null and equals 0, return # nodes
diff --git a/storage/oqgraph/ha_oqgraph.h b/storage/oqgraph/ha_oqgraph.h
index d0ac8d7e18c..0c0af6def97 100644
--- a/storage/oqgraph/ha_oqgraph.h
+++ b/storage/oqgraph/ha_oqgraph.h
@@ -83,7 +83,7 @@ public:
int open(const char *name, int mode, uint test_if_locked);
int close(void);
- int write_row(byte * buf);
+ int write_row(const byte * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const byte * buf);
int index_read(byte * buf, const byte * key,
diff --git a/storage/oqgraph/oqgraph_thunk.cc b/storage/oqgraph/oqgraph_thunk.cc
index 5d3f03beaf8..bd577ecfc12 100644
--- a/storage/oqgraph/oqgraph_thunk.cc
+++ b/storage/oqgraph/oqgraph_thunk.cc
@@ -109,7 +109,7 @@ const std::string& oqgraph3::cursor::record_position() const
if (_graph->_cursor->_index >= 0)
{
key_copy((uchar*) _graph->_cursor->_key.data(), table.record[0],
- table.s->key_info + _index, table.s->key_info[_index].key_length, true);
+ table.key_info + _index, table.key_info[_index].key_length, true);
}
_graph->_stale= false;
@@ -184,7 +184,7 @@ int oqgraph3::cursor::restore_position()
if (int rc= table.file->ha_index_read_map(
table.record[0], (const uchar*) _key.data(),
(key_part_map)(1 << _parts) - 1,
- table.s->key_info[_index].user_defined_key_parts == _parts ?
+ table.key_info[_index].user_defined_key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{
table.file->ha_index_end();
@@ -368,7 +368,7 @@ int oqgraph3::cursor::seek_to(
if (!destid)
{
int i= 0;
- for( ::KEY *key_info= table.s->key_info,
+ for( ::KEY *key_info= table.key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
@@ -399,7 +399,7 @@ int oqgraph3::cursor::seek_to(
else if (!origid)
{
int i= 0;
- for( ::KEY *key_info= table.s->key_info,
+ for( ::KEY *key_info= table.key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
@@ -430,7 +430,7 @@ int oqgraph3::cursor::seek_to(
else
{
int i= 0;
- for( ::KEY *key_info= table.s->key_info,
+ for( ::KEY *key_info= table.key_info,
*key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i)
{
@@ -485,7 +485,7 @@ int oqgraph3::cursor::seek_to(
if (int rc= table.file->ha_index_read_map(
table.record[0], (uchar*) _key.data(),
(key_part_map) ((1U << _parts) - 1),
- table.s->key_info[_index].user_defined_key_parts == _parts ?
+ table.key_info[_index].user_defined_key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{
table.file->ha_index_end();
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index 0754bb5a7e7..8860046fa26 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -27,7 +27,6 @@
#include "sql_plugin.h"
#include "my_pthread.h"
-#include "my_atomic.h"
#include "ha_perfschema.h"
#include "pfs_engine_table.h"
#include "pfs_column_values.h"
@@ -258,7 +257,7 @@ int ha_perfschema::close(void)
DBUG_RETURN(0);
}
-int ha_perfschema::write_row(uchar *buf)
+int ha_perfschema::write_row(const uchar *buf)
{
int result;
diff --git a/storage/perfschema/ha_perfschema.h b/storage/perfschema/ha_perfschema.h
index dd57ff31088..18ac035831d 100644
--- a/storage/perfschema/ha_perfschema.h
+++ b/storage/perfschema/ha_perfschema.h
@@ -127,7 +127,7 @@ public:
@param buf the row to write
@return 0 on success
*/
- int write_row(uchar *buf);
+ int write_row(const uchar *buf);
void use_hidden_primary_key();
diff --git a/storage/perfschema/pfs_engine_table.cc b/storage/perfschema/pfs_engine_table.cc
index 08ad7d31c88..144ebcddff4 100644
--- a/storage/perfschema/pfs_engine_table.cc
+++ b/storage/perfschema/pfs_engine_table.cc
@@ -185,7 +185,7 @@ ha_rows PFS_engine_table_share::get_row_count(void) const
return m_records;
}
-int PFS_engine_table_share::write_row(TABLE *table, unsigned char *buf,
+int PFS_engine_table_share::write_row(TABLE *table, const unsigned char *buf,
Field **fields) const
{
my_bitmap_map *org_bitmap;
diff --git a/storage/perfschema/pfs_engine_table.h b/storage/perfschema/pfs_engine_table.h
index 52ad203db24..03a2b6a9d28 100644
--- a/storage/perfschema/pfs_engine_table.h
+++ b/storage/perfschema/pfs_engine_table.h
@@ -207,7 +207,7 @@ protected:
typedef PFS_engine_table* (*pfs_open_table_t)(void);
/** Callback to write a row. */
typedef int (*pfs_write_row_t)(TABLE *table,
- unsigned char *buf, Field **fields);
+ const unsigned char *buf, Field **fields);
/** Callback to delete all rows. */
typedef int (*pfs_delete_all_rows_t)(void);
/** Callback to get a row count. */
@@ -224,7 +224,7 @@ struct PFS_engine_table_share
/** Get the row count. */
ha_rows get_row_count(void) const;
/** Write a row. */
- int write_row(TABLE *table, unsigned char *buf, Field **fields) const;
+ int write_row(TABLE *table, const unsigned char *buf, Field **fields) const;
/** Table name. */
LEX_STRING m_name;
diff --git a/storage/perfschema/pfs_server.h b/storage/perfschema/pfs_server.h
index 3457a91d376..9f904e6545b 100644
--- a/storage/perfschema/pfs_server.h
+++ b/storage/perfschema/pfs_server.h
@@ -35,7 +35,7 @@
#define PFS_MAX_RWLOCK_CLASS 40
#endif
#ifndef PFS_MAX_COND_CLASS
- #define PFS_MAX_COND_CLASS 80
+ #define PFS_MAX_COND_CLASS 90
#endif
#ifndef PFS_MAX_THREAD_CLASS
#define PFS_MAX_THREAD_CLASS 50
diff --git a/storage/perfschema/table_setup_actors.cc b/storage/perfschema/table_setup_actors.cc
index 71c384d0555..b05f6ad004b 100644
--- a/storage/perfschema/table_setup_actors.cc
+++ b/storage/perfschema/table_setup_actors.cc
@@ -59,7 +59,7 @@ PFS_engine_table* table_setup_actors::create()
return new table_setup_actors();
}
-int table_setup_actors::write_row(TABLE *table, unsigned char *buf,
+int table_setup_actors::write_row(TABLE *table, const unsigned char *buf,
Field **fields)
{
Field *f;
diff --git a/storage/perfschema/table_setup_actors.h b/storage/perfschema/table_setup_actors.h
index 748c57850b0..6bfc480a9c5 100644
--- a/storage/perfschema/table_setup_actors.h
+++ b/storage/perfschema/table_setup_actors.h
@@ -62,7 +62,7 @@ public:
static PFS_engine_table_share m_share;
/** Table builder. */
static PFS_engine_table* create();
- static int write_row(TABLE *table, unsigned char *buf, Field **fields);
+ static int write_row(TABLE *table, const unsigned char *buf, Field **fields);
static int delete_all_rows();
static ha_rows get_row_count();
diff --git a/storage/perfschema/table_setup_objects.cc b/storage/perfschema/table_setup_objects.cc
index af6481ae98c..f3d11b7f26f 100644
--- a/storage/perfschema/table_setup_objects.cc
+++ b/storage/perfschema/table_setup_objects.cc
@@ -73,7 +73,7 @@ PFS_engine_table* table_setup_objects::create(void)
return new table_setup_objects();
}
-int table_setup_objects::write_row(TABLE *table, unsigned char *buf,
+int table_setup_objects::write_row(TABLE *table, const unsigned char *buf,
Field **fields)
{
int result;
diff --git a/storage/perfschema/table_setup_objects.h b/storage/perfschema/table_setup_objects.h
index 560346c577f..570acc865ad 100644
--- a/storage/perfschema/table_setup_objects.h
+++ b/storage/perfschema/table_setup_objects.h
@@ -65,7 +65,7 @@ public:
static PFS_engine_table_share m_share;
/** Table builder. */
static PFS_engine_table* create();
- static int write_row(TABLE *table, unsigned char *buf, Field **fields);
+ static int write_row(TABLE *table, const unsigned char *buf, Field **fields);
static int delete_all_rows();
static ha_rows get_row_count();
diff --git a/storage/perfschema/unittest/pfs_server_stubs.cc b/storage/perfschema/unittest/pfs_server_stubs.cc
index db1600faf9f..0cabce37e51 100644
--- a/storage/perfschema/unittest/pfs_server_stubs.cc
+++ b/storage/perfschema/unittest/pfs_server_stubs.cc
@@ -31,8 +31,6 @@
struct sql_digest_storage;
-volatile bool ready_to_exit= false;
-
uint lower_case_table_names= 0;
CHARSET_INFO *files_charset_info= NULL;
CHARSET_INFO *system_charset_info= NULL;
diff --git a/storage/rocksdb/CMakeLists.txt b/storage/rocksdb/CMakeLists.txt
index 3a707d8c02b..f4f23ff08c6 100644
--- a/storage/rocksdb/CMakeLists.txt
+++ b/storage/rocksdb/CMakeLists.txt
@@ -192,26 +192,6 @@ TARGET_LINK_LIBRARIES(rocksdb rocksdb_aux_lib)
NAMES liblz4${PIC_EXT}.a lz4
HINTS ${WITH_LZ4}/lib)
-IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-
- # MARIAROCKS_NOT_YET: Add -frtti flag when compiling RocksDB files.
- # TODO: is this the right way to do this?
- # - SQL layer and storage/rocksdb/*.cc are compiled with -fnortti
- # - RocksDB files are compiled with "-fnortti ... -frtti"
- # - This causes RocksDB headers to be compiled with different settings:
- # = with RTTI when compiling RocksDB
- # = without RTTI when compiling storage/rocksdb/*.cc
- #
- # (facebook/mysql-5.6 just compiles everything without -f*rtti, which means
- # everything is compiled with -frtti)
- #
- # (also had to add -frtti above, because something that event_listener.cc
- # includes requires it. So, now everything in MariaRocks is compiled with
- # -frtti)
- set_source_files_properties(event_listener.cc rdb_cf_options.cc rdb_sst_info.cc
- PROPERTIES COMPILE_FLAGS -frtti)
-ENDIF()
-
CHECK_FUNCTION_EXISTS(sched_getcpu HAVE_SCHED_GETCPU)
IF(HAVE_SCHED_GETCPU)
ADD_DEFINITIONS(-DHAVE_SCHED_GETCPU=1)
@@ -256,9 +236,6 @@ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/myrocks_hotbackup.py
${CMAKE_CURRENT_BINARY_DIR}/myrocks_hotbackup @ONLY)
INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/myrocks_hotbackup COMPONENT rocksdb-engine)
-IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- SET_TARGET_PROPERTIES(rocksdb_tools sst_dump mysql_ldb PROPERTIES COMPILE_FLAGS "-frtti -Wno-error")
-ENDIF()
IF(MSVC)
# RocksDB, the storage engine, overdoes "const" by adding
# additional const qualifiers to parameters of the overriden virtual functions
@@ -271,6 +248,8 @@ IF(MSVC)
IF(CMAKE_SIZEOF_VOID_P EQUAL 8)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267")
ENDIF()
+ELSEIF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+ SET_TARGET_PROPERTIES(rocksdb_tools sst_dump mysql_ldb PROPERTIES COMPILE_FLAGS "-Wno-error")
ENDIF()
# Enable ZSTD if available. Upstream rocksdb cmake will use WITH_ZSTD and set
diff --git a/storage/rocksdb/build_rocksdb.cmake b/storage/rocksdb/build_rocksdb.cmake
index 4b12baee9f8..51d775ce06d 100644
--- a/storage/rocksdb/build_rocksdb.cmake
+++ b/storage/rocksdb/build_rocksdb.cmake
@@ -490,5 +490,5 @@ list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/build_version.cc)
ADD_CONVENIENCE_LIBRARY(rocksdblib ${SOURCES})
target_link_libraries(rocksdblib ${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set_target_properties(rocksdblib PROPERTIES COMPILE_FLAGS "-fPIC -fno-builtin-memcmp -frtti -Wno-error")
+ set_target_properties(rocksdblib PROPERTIES COMPILE_FLAGS "-fPIC -fno-builtin-memcmp -Wno-error")
endif()
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index d7d1b1665f7..ca7880779e8 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -7199,7 +7199,7 @@ int ha_rocksdb::create_cfs(
tbl_def_arg->full_tablename().c_str(),
table_arg->key_info[i].key_part[part].field->field_name.str);
- my_error(ER_INTERNAL_ERROR, MYF(ME_JUST_WARNING), buf);
+ my_error(ER_INTERNAL_ERROR, MYF(ME_WARNING), buf);
}
}
}
@@ -8750,7 +8750,7 @@ int ha_rocksdb::check(THD *const thd, HA_CHECK_OPT *const check_opt) {
int res;
// NO_LINT_DEBUG
sql_print_verbose_info("CHECKTABLE %s: Checking index %s", table_name,
- table->key_info[keyno].name);
+ table->key_info[keyno].name.str);
while (1) {
if (!rows) {
res = index_first(table->record[0]);
@@ -9538,7 +9538,7 @@ const std::string ha_rocksdb::get_table_comment(const TABLE *const table_arg) {
HA_EXIT_SUCCESS OK
other HA_ERR error code (can be SE-specific)
*/
-int ha_rocksdb::write_row(uchar *const buf) {
+int ha_rocksdb::write_row(const uchar *const buf) {
DBUG_ENTER_FUNC();
DBUG_ASSERT(buf != nullptr);
@@ -10976,11 +10976,15 @@ int ha_rocksdb::info(uint flag) {
stats.records += m_table_handler->m_mtcache_count;
stats.data_file_length += m_table_handler->m_mtcache_size;
}
+
+ // Do like InnoDB does. stats.records=0 confuses the optimizer
+ if (stats.records == 0 && !(flag & (HA_STATUS_TIME | HA_STATUS_OPEN))) {
+ stats.records++;
+ }
}
- if (rocksdb_debug_optimizer_n_rows > 0) {
+ if (rocksdb_debug_optimizer_n_rows > 0)
stats.records = rocksdb_debug_optimizer_n_rows;
- }
if (stats.records != 0) {
stats.mean_rec_length = stats.data_file_length / stats.records;
diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h
index cadbd9abfe9..448900c5a91 100644
--- a/storage/rocksdb/ha_rocksdb.h
+++ b/storage/rocksdb/ha_rocksdb.h
@@ -640,7 +640,7 @@ public:
MY_ATTRIBUTE((__warn_unused_result__));
int close(void) override MY_ATTRIBUTE((__warn_unused_result__));
- int write_row(uchar *const buf) override
+ int write_row(const uchar *const buf) override
MY_ATTRIBUTE((__warn_unused_result__));
int update_row(const uchar *const old_data, const uchar *const new_data) override
MY_ATTRIBUTE((__warn_unused_result__));
@@ -739,6 +739,7 @@ public:
const TABLE *old_table_arg, const Rdb_tbl_def *old_tbl_def_arg) const
MY_ATTRIBUTE((__nonnull__));
+ using handler::compare_key_parts;
int compare_key_parts(const KEY *const old_key,
const KEY *const new_key) const
MY_ATTRIBUTE((__nonnull__, __warn_unused_result__));
diff --git a/storage/rocksdb/mysql-test/rocksdb/include/use_direct_io_option.inc b/storage/rocksdb/mysql-test/rocksdb/include/use_direct_io_option.inc
index da16e1c9c3b..6e427f26fd6 100644
--- a/storage/rocksdb/mysql-test/rocksdb/include/use_direct_io_option.inc
+++ b/storage/rocksdb/mysql-test/rocksdb/include/use_direct_io_option.inc
@@ -6,6 +6,7 @@
--source include/have_direct_io.inc
--echo Checking direct reads
+--let $restart_noprint=2
--let $_mysqld_option=$io_option
--source include/restart_mysqld_with_option.inc
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result
index 3ba0f30a22d..20f84dd5563 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/add_index_inplace.result
@@ -391,33 +391,46 @@ set global rocksdb_force_flush_memtable_now=1;
ALTER TABLE t1 ADD INDEX kj(j), ALGORITHM=INPLACE;
larger
1
+# restart
larger
1
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
larger
1
+# restart
larger
1
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
select 1300 < 1300 * 1.5 as "same";
same
@@ -478,6 +491,7 @@ INSERT INTO t1 (a, b) VALUES (4, 20);
set global rocksdb_force_flush_memtable_now=1;
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
SHOW INDEX in t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key.result b/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key.result
index a8d5c07072c..96d25b2e669 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key.result
@@ -62,6 +62,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -171,6 +172,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -254,6 +256,7 @@ SHOW COLUMNS IN t1;
Field Type Null Key Default Extra
a int(11) YES NULL
b char(8) YES NULL
+# restart
INSERT INTO t1 (a,b) VALUES (35,'foo');
INSERT INTO t1 (a,b) VALUES (35,'foo');
INSERT INTO t1 (a,b) VALUES (36,'foo');
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key_with_sk.result b/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key_with_sk.result
index 5d947603ec5..27722b23927 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key_with_sk.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/allow_no_primary_key_with_sk.result
@@ -63,6 +63,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -147,6 +148,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -228,6 +230,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -311,6 +314,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -401,6 +405,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -484,6 +489,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -568,6 +574,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -747,6 +754,7 @@ a b
123 bbb
321 ccc
321 ccc
+# restart
INSERT INTO t1 (a,b) VALUES (45,'bob');
SELECT * FROM t1;
a b
@@ -788,6 +796,7 @@ t1 CREATE TABLE `t1` (
`i` int(11) NOT NULL AUTO_INCREMENT,
KEY `i` (`i`)
) ENGINE=ROCKSDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
+# restart
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result b/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result
index b666a17c81c..3459b6f189b 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/analyze_table.result
@@ -5,26 +5,32 @@ CREATE TABLE t2 (pk INT PRIMARY KEY, a INT(11), b CHAR(8)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (3,3,'c');
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t2 VALUES (1,4,'d');
ANALYZE NO_WRITE_TO_BINLOG TABLE t2;
Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
INSERT INTO t1 VALUES (4,5,'e');
INSERT INTO t2 VALUES (2,6,'f');
ANALYZE LOCAL TABLE t1, t2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
DROP TABLE t1, t2;
CREATE TABLE t1 (pk INT PRIMARY KEY, a INT(11), KEY(a)) ENGINE=rocksdb;
INSERT INTO t1 VALUES (1,1),(2,2),(3,4),(4,7);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1 VALUES (5,8),(6,10),(7,11),(8,12);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
DROP TABLE t1;
#
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_secondary.result b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_secondary.result
index 100bc5fd638..c6dcb023e06 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_secondary.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_secondary.result
@@ -6,6 +6,7 @@ pk a
3 1
2 2
1 3
+# restart
INSERT INTO t1 (pk) VALUES (4);
SELECT * FROM t1;
pk a
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result
index a14ffdec2e3..6bd6cea97de 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/autoinc_vars_thread_2.result
@@ -92,5 +92,7 @@ disconnect con2;
disconnect con1;
disconnect con0;
SELECT * FROM t1 ORDER BY pk INTO OUTFILE <output_file>;
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
All pk values matched their expected values
DROP TABLE t1;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter3.result b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter3.result
index f3c4fdf1040..d447b480f44 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter3.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter3.result
@@ -1,3 +1,4 @@
+# restart
CREATE TABLE `linktable` (
`id1` bigint(20) unsigned NOT NULL DEFAULT '0',
`id1_type` int(10) unsigned NOT NULL DEFAULT '0',
@@ -92,6 +93,7 @@ select case when variable_value-@c = 0 then 'true' else 'false' end from informa
case when variable_value-@c = 0 then 'true' else 'false' end
true
DROP TABLE linktable;
+# restart
#
# bloom filter prefix is 20 byte
# Create a key which is longer than that, so that we see that
@@ -116,6 +118,7 @@ insert into t1 values (10,1,1,0x12FFFFFFFFFF,1);
insert into t1 values (11,1,1,0x12FFFFFFFFFF,1);
insert into t1 values (20,2,2,0x12FFFFFFFFFF,1);
insert into t1 values (21,2,2,0x12FFFFFFFFFF,1);
+# restart
explain
select * from t1 where kp0=1 and kp1=1 and kp2=0x12FFFFFFFFFF order by kp3 desc;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result
index 1f4d1a641a2..c4a1c5f4668 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bloomfilter4.result
@@ -20,6 +20,8 @@ END IF;
SET id1_cond = id1_cond + 1;
END WHILE;
END//
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
"Skipping bloom filter"
SET session rocksdb_skip_bloom_filter_on_read=1;
CALL select_test();
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result
index 98db48d772f..b8a98efa55e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load.result
@@ -45,8 +45,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL 0 N
t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned 0 N
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
@@ -73,5 +76,6 @@ count(b)
2500000
longfilenamethatvalidatesthatthiswillgetdeleted.bulk_load.tmp
test.bulk_load.tmp
+# restart
disconnect other;
DROP TABLE t1, t2, t3;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_errors.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_errors.result
index 4ea8cbccc1e..995da9e88eb 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_errors.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_errors.result
@@ -86,6 +86,7 @@ INSERT INTO t1 VALUES(51479+0.333333333,1);
DROP TABLE t1;
SET @@global.table_open_cache=@orig_table_open_cache;
FOUND 1 /RocksDB: Error [0-9]+ finalizing bulk load while closing handler/ in rocksdb.bulk_load_errors.3.err
+# restart
CREATE TABLE t1 (pk INT, PRIMARY KEY (pk)) ENGINE=ROCKSDB;
CREATE TABLE t2 (pk INT, PRIMARY KEY (pk)) ENGINE=ROCKSDB;
SET rocksdb_bulk_load=1;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result
index d894e2e371a..56b1a8322cc 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf.result
@@ -45,8 +45,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL 0 N
t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned 0 N
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
@@ -73,5 +76,6 @@ count(b)
2500000
longfilenamethatvalidatesthatthiswillgetdeleted.bulk_load.tmp
test.bulk_load.tmp
+# restart
disconnect other;
DROP TABLE t1, t2, t3;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result
index 90402a87005..1a260c69fa3 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_cf_and_data.result
@@ -45,8 +45,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL 0 N
t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned 0 N
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
@@ -73,5 +76,6 @@ count(b)
2500000
longfilenamethatvalidatesthatthiswillgetdeleted.bulk_load.tmp
test.bulk_load.tmp
+# restart
disconnect other;
DROP TABLE t1, t2, t3;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result
index 5a5a334a71f..e216fb1cc45 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_rev_data.result
@@ -45,8 +45,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL 0 N
t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_bin NULL partitioned 0 N
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
@@ -73,5 +76,6 @@ count(b)
2500000
longfilenamethatvalidatesthatthiswillgetdeleted.bulk_load.tmp
test.bulk_load.tmp
+# restart
disconnect other;
DROP TABLE t1, t2, t3;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result
index 65b20296127..63d07a25961 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted.result
@@ -77,8 +77,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL 0 N
t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL partitioned 0 N
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result
index aa97afb9b72..a6e0793f5d1 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/bulk_load_unsorted_rev.result
@@ -77,8 +77,11 @@ t2 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL 0 N
t3 ROCKSDB 10 Fixed 2500000 # # # # 0 NULL # # NULL latin1_swedish_ci NULL partitioned 0 N
ANALYZE TABLE t1, t2, t3;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
SHOW TABLE STATUS WHERE name LIKE 't%';
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result b/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result
index d037c636a16..dcaca8b72bc 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/cardinality.result
@@ -1,3 +1,5 @@
+# restart
+set use_stat_tables= 'COMPLEMENTARY';
CREATE TABLE t0 (id int PRIMARY KEY, a int, INDEX ix_a (a)) engine=rocksdb;
insert into t0 values (0, 0),(1, 1),(2, 2),(3, 3),(4, 4),
(5, 4),(6, 4),(7, 4),(8, 4),(9, 4);
@@ -66,6 +68,7 @@ SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema
table_name table_rows
t1 100000
restarting...
+# restart
show index in t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t1 0 PRIMARY 1 id A 100000 NULL NULL LSMTREE
@@ -88,6 +91,7 @@ ENGINE=ROCKSDB;
SET GLOBAL rocksdb_force_flush_memtable_now = 1;
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
cardinality of the columns after 'a' must be equal to the cardinality of column 'a'
SELECT CARDINALITY INTO @c FROM information_schema.statistics WHERE TABLE_NAME='t2' AND INDEX_NAME='c' AND COLUMN_NAME='a';
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/compression_zstd.result b/storage/rocksdb/mysql-test/rocksdb/r/compression_zstd.result
index 62a6dbbdaca..2c1cab7fcac 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/compression_zstd.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/compression_zstd.result
@@ -1,2 +1,3 @@
+# restart: --rocksdb_default_cf_options=compression_per_level=kZSTDNotFinalCompression;compression_opts=-14:4:0;
create table t (id int primary key) engine=rocksdb;
drop table t;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result b/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result
index dfa5c5b2590..668f7e8f47e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/drop_index_inplace.result
@@ -57,6 +57,7 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`a`),
KEY `kc` (`c`)
) ENGINE=ROCKSDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1
+# restart
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -117,6 +118,7 @@ SHOW INDEX IN t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t1 0 PRIMARY 1 a A 0 NULL NULL LSMTREE
t1 0 kc 1 c A 0 NULL NULL YES LSMTREE
+# restart
INSERT INTO t1 (b,c) VALUES (1,2);
INSERT INTO t1 (b,c) VALUES (3,4);
INSERT INTO t1 (b,c) VALUES (5,6);
@@ -139,6 +141,7 @@ INSERT INTO t1 (col1,col2,col3) VALUES (1,2,3);
ALTER TABLE t1 ADD KEY idx ( col1, col2 );
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
ALTER TABLE t1 DROP COLUMN col2;
ALTER TABLE t1 DROP COLUMN col3;
@@ -148,6 +151,7 @@ INSERT INTO t1 (col1,col2,col3) VALUES (1,2,3);
ALTER TABLE t1 ADD KEY idx ( col1, col2 );
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
ALTER TABLE t1 DROP COLUMN col2;
ALTER TABLE t1 DROP COLUMN col3;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/drop_table2.result b/storage/rocksdb/mysql-test/rocksdb/r/drop_table2.result
index fad2939d206..aec4138c722 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/drop_table2.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/drop_table2.result
@@ -10,6 +10,7 @@ call mtr.add_suppression("Column family 'rev:cf2' not found");
set global rocksdb_compact_cf = 'cf1';
set global rocksdb_compact_cf = 'rev:cf2';
set global rocksdb_signal_drop_index_thread = 1;
+# restart
CREATE TABLE t1 (
a int not null,
b int not null,
@@ -38,10 +39,12 @@ DELETE FROM t1;
DELETE FROM t2;
DELETE FROM t3;
DELETE FROM t4;
+# restart
DELETE FROM t1;
DELETE FROM t4;
DELETE FROM t1;
DELETE FROM t4;
+# restart
CREATE TABLE t5 (
a int not null,
b int not null,
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/drop_table3.result b/storage/rocksdb/mysql-test/rocksdb/r/drop_table3.result
index 7a33fa83cb4..954e6079bba 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/drop_table3.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/drop_table3.result
@@ -6,6 +6,7 @@ call mtr.add_suppression("Column family 'rev:cf2' not found");
set global rocksdb_compact_cf = 'cf1';
set global rocksdb_compact_cf = 'rev:cf2';
set global rocksdb_signal_drop_index_thread = 1;
+# restart
CREATE TABLE t1 (
a int not null,
b int not null,
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result
index e6a3dee961c..6507aa43ae1 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/group_min_max.result
@@ -42,6 +42,7 @@ create index idx_t1_1 on t1 (a1,a2,b,c);
create index idx_t1_2 on t1 (a1,a2,b);
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
drop table if exists t2;
create table t2 (
@@ -70,6 +71,7 @@ create index idx_t2_1 on t2 (a1,a2,b,c);
create index idx_t2_2 on t2 (a1,a2,b);
analyze table t2;
Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
drop table if exists t3;
create table t3 (
@@ -132,37 +134,38 @@ create index idx_t3_1 on t3 (a1,a2,b,c);
create index idx_t3_2 on t3 (a1,a2,b);
analyze table t3;
Table Op Msg_type Msg_text
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
explain select a1, min(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
explain select a1, max(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 65 NULL 63 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 65 NULL 5 Using index for group-by
explain select a1, min(a2), max(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
explain select a1, a2, b, min(c), max(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
explain select a1,a2,b,max(c),min(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
explain select a1,a2,b,max(c),min(c) from t2 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL idx_t2_1 # NULL # Using index for group-by
explain select min(a2), a1, max(a2), min(a2), a1 from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
explain select a1, b, min(c), a1, max(c), b, a2, max(c), max(c) from t1 group by a1, a2, b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
explain select min(a2) from t1 group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using index for group-by
explain select a2, min(c), max(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
select a1, min(a2) from t1 group by a1;
a1 min(a2)
a a
@@ -289,37 +292,37 @@ b i421 l421
b m422 p422
explain select a1,a2,b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1, max(c) from t1 where a1 >= 'c' or a1 < 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where a1 >= 'c' or a2 < 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where a1 = 'z' or a1 = 'b' or a1 = 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,min(c),max(c) from t1 where a1 >= 'b' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1, max(c) from t1 where a1 in ('a','b','d') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
@@ -681,97 +684,97 @@ d p422
# So the following results are not very meaningful, but are still kept here
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 5 Using where; Using index for group-by
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 5 Using where; Using index for group-by
explain select a1,max(c),min(c) from t1 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,a2,b, max(c) from t1 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t1 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,a2, max(c) from t1 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using where; Using index for group-by
explain select a1,a2, max(c) from t1 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 63 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 6 Using where; Using index for group-by
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 63 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 6 Using where; Using index for group-by
explain select a1,max(c),min(c) from t2 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b, max(c) from t2 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2, max(c) from t2 where (b = 'b') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by
explain select a1,a2, max(c) from t2 where (b = 'b' or b = 'a') group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range NULL idx_t3_1 6 NULL 63 Using where; Using index for group-by
+1 SIMPLE t3 range NULL idx_t3_1 6 NULL 4 Using where; Using index for group-by
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 192 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 192 Using where; Using index
explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 range NULL idx_t3_1 6 NULL 63 Using where; Using index for group-by
+1 SIMPLE t3 range NULL idx_t3_1 6 NULL 4 Using where; Using index for group-by
explain select a1,max(c),min(c) from t3 where (a2 = 'a' or a2 = 'b') and (b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 192 Using where; Using index
explain select a1,max(c),min(c) from t3 where (a2 = 'a') and (b = 'b' or b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t3 index NULL idx_t3_1 10 NULL 1000 Using where; Using index
+1 SIMPLE t3 index NULL idx_t3_1 10 NULL 192 Using where; Using index
select a1,a2,b,max(c),min(c) from t1 where (a2 = 'a') and (b = 'b') group by a1;
a1 a2 b max(c) min(c)
a a b h112 e112
@@ -1014,25 +1017,25 @@ b h212 a211
c h312 a311
explain select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 63 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 6 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t2 where (a2 = 'a' or a2 = 'b') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c) from t2 where (a2 = 'a') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL 63 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 6 Using where; Using index for group-by
explain select a1,a2,b,max(c) from t2 where (a2 = 'a' or a2 = 'b') and b is NULL group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,min(c) from t2 where b is NULL group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
explain select a1,a2,b,max(c) from t2 where b is NULL group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 146 NULL 10 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where b is NULL group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 10 Using where; Using index for group-by
select a1,a2,b,min(c) from t2 where (a2 = 'a') and b is NULL group by a1;
a1 a2 b min(c)
a a NULL a777
@@ -1070,49 +1073,49 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL idx_t1_1 147 NULL # Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c > 'f123') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'f123') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c < 'a0') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c < 'k321') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'k321') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'a0') or (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b1') or (c <= 'g1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c > 'b111') and (c <= 'g112') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c < 'c5') or (c = 'g412') or (c = 'k421') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where ((c > 'b111') and (c <= 'g112')) or ((c > 'd000') and (c <= 'i110')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (c between 'b111' and 'g112') or (c between 'd000' and 'i110') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b, max(c) from t2 where (c > 'b1') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
@@ -1579,36 +1582,36 @@ explain select a1,a2,b,min(c),max(c) from t1
where exists ( select * from t2 where t2.c = t1.c )
group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index NULL idx_t1_1 163 NULL 1000 Using index
+1 PRIMARY t1 index NULL idx_t1_1 163 NULL 128 Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 16 func 1
-2 MATERIALIZED t2 index NULL idx_t2_1 163 NULL 1000 Using index
+2 MATERIALIZED t2 index NULL idx_t2_1 163 NULL 164 Using index
explain select a1,a2,b,min(c),max(c) from t1
where exists ( select * from t2 where t2.c > 'b1' )
group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 index NULL idx_t1_1 163 NULL 1000 Using index
-2 SUBQUERY t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 PRIMARY t1 index NULL idx_t1_1 163 NULL 128 Using index
+2 SUBQUERY t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (c > 'b111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t1 where (a2 >= 'b') and (b = 'a') and (c > 'b111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c < 'h112') or (c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where ((a1 > 'a') or (a1 < '9')) and ((a2 >= 'b') and (a2 < 'z')) and (b = 'a') and ((c = 'j121') or (c > 'k121' and c < 'm122') or (c > 'o122') or (c < 'h112') or (c = 'c111')) group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c) from t1 where (ord(a1) > 97) and (ord(a2) + ord(a1) > 194) and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,min(c),max(c) from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 163 NULL # Using where; Using index for group-by
@@ -1713,25 +1716,25 @@ select a1,a2,b,min(c) from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') grou
a1 a2 b min(c)
explain select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121' or c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select a1,a2,b from t2 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by
explain select a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by
explain select a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
@@ -1740,7 +1743,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by
select a1,a2,b from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
a1 a2 b
a a b
@@ -1788,50 +1791,50 @@ select a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1
a1 a2 b
explain select distinct a1,a2,b from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using index for group-by
explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain extended select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 501 100.00 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 65 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select distinct `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where `test`.`t1`.`b` = 'a' and `test`.`t1`.`c` = 'i121' and `test`.`t1`.`a2` >= 'b'
explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select distinct b from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 5 Using where; Using index for group-by
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'e';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 5 Using where; Using index for group-by
explain select distinct a1,a2,b from t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using index for group-by
explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by
explain extended select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t2 range NULL idx_t2_1 163 NULL 501 100.00 Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_1 163 NULL 83 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select distinct `test`.`t2`.`a1` AS `a1`,`test`.`t2`.`a2` AS `a2`,`test`.`t2`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t2` where `test`.`t2`.`b` = 'a' and `test`.`t2`.`c` = 'i121' and `test`.`t2`.`a2` >= 'b'
explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by
explain select distinct b from t2 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_2 146 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_2 146 NULL 164 Using where; Using index
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL 63 Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 129 NULL 6 Using where; Using index for group-by
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'e';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL 63 Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 129 NULL 6 Using where; Using index for group-by
select distinct a1,a2,b from t1;
a1 a2 b
a a a
@@ -1960,46 +1963,46 @@ c e
d e
explain select distinct a1,a2,b from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using index for group-by
explain select distinct a1,a2,b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select distinct a1,a2,b,c from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 17 Using where; Using index for group-by
explain select distinct a1,a2,b from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select distinct b from t1 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by; Using temporary; Using filesort
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using where; Using index for group-by; Using temporary; Using filesort
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'b' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 5 Using where; Using index for group-by
explain select distinct a1 from t1 where a1 in ('a', 'd') and a2 = 'e' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 5 Using where; Using index for group-by
explain select distinct a1,a2,b from t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using index for group-by
explain select distinct a1,a2,b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by
explain select distinct a1,a2,b,c from t2 where (a2 >= 'b') and (b = 'a') and (c = 'i121') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range NULL idx_t2_1 163 NULL # Using where; Using index for group-by
explain select distinct a1,a2,b from t2 where (a1 > 'a') and (a2 > 'a') and (b = 'c') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 146 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 146 NULL # Using where; Using index for group-by
explain select distinct b from t2 where (a2 >= 'b') and (b = 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL idx_t2_1 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
+1 SIMPLE t2 range NULL idx_t2_2 146 NULL # Using where; Using index for group-by; Using temporary; Using filesort
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'b' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 129 NULL # Using where; Using index for group-by
explain select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'e' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_1 129 NULL # Using where; Using index for group-by
+1 SIMPLE t2 range idx_t2_0,idx_t2_1,idx_t2_2 idx_t2_2 129 NULL # Using where; Using index for group-by
select distinct a1,a2,b from t1;
a1 a2 b
a a a
@@ -2082,21 +2085,21 @@ select distinct a1 from t2 where a1 in ('a', 'd') and a2 = 'e' group by a1;
a1
explain select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_2 147 NULL 17 Using where; Using index for group-by
explain select count(distinct a1,a2,b,c) from t1 where (a2 >= 'b') and (b = 'a') and (c = 'i121');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 163 NULL 501 Using where; Using index for group-by (scanning)
+1 SIMPLE t1 range NULL idx_t1_1 163 NULL 65 Using where; Using index for group-by
explain extended select count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a') and (b = 'c');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 100.00 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 17 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `count(distinct a1,a2,b)` from `test`.`t1` where `test`.`t1`.`b` = 'c' and `test`.`t1`.`a1` > 'a' and `test`.`t1`.`a2` > 'a'
explain select count(distinct b) from t1 where (a2 >= 'b') and (b = 'a');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
explain extended select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 100.00 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 147 NULL 17 100.00 Using where; Using index for group-by
Warnings:
Note 1003 select 98 + count(distinct `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`) AS `98 + count(distinct a1,a2,b)` from `test`.`t1` where `test`.`t1`.`a1` > 'a' and `test`.`t1`.`a2` > 'a'
select count(distinct a1,a2,b) from t1 where (a2 >= 'b') and (b = 'a');
@@ -2116,19 +2119,19 @@ select 98 + count(distinct a1,a2,b) from t1 where (a1 > 'a') and (a2 > 'a');
104
explain select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select concat(a1,min(c)),b from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select concat(a1,min(c)),b,max(c) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select concat(a1,a2),b,min(c),max(c) from t1 where a1 < 'd' group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 251 Using where; Using index for group-by
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
explain select concat(ord(min(b)),ord(max(b))),min(b),max(b) from t1 group by a1,a2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 147 NULL 126 Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 147 NULL 9 Using index for group-by
select a1,a2,b, concat(min(c), max(c)) from t1 where a1 < 'd' group by a1,a2,b;
a1 a2 b concat(min(c), max(c))
a a a a111d111
@@ -2197,83 +2200,83 @@ concat(ord(min(b)),ord(max(b))) min(b) max(b)
9798 a b
explain select a1,a2,b,d,min(c),max(c) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128
explain select a1,a2,b,d from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128
explain extended select a1,a2,min(b),max(b) from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 1000 100.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 128 99.22 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,min(`test`.`t1`.`b`) AS `min(b)`,max(`test`.`t1`.`b`) AS `max(b)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`
explain extended select a1,a2,b,min(c),max(c) from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 130 NULL 1000 100.00 Using where
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 130 NULL 128 75.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,min(`test`.`t1`.`c`) AS `min(c)`,max(`test`.`t1`.`c`) AS `max(c)` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain extended select a1,a2,b,c from t1
where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (d > 'xy2') group by a1,a2,b,c;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 1000 100.00 Using where
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 128 75.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b`,`test`.`t1`.`c` AS `c` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`d` > 'xy2' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`,`test`.`t1`.`c`
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b < 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b < 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b <= 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b <= 'b' and b >= 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain extended select a1,a2,b from t1 where (a1 = 'b' or a1 = 'd' or a1 = 'a' or a1 = 'c') and (a2 > 'a') and (c > 'a111') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 1000 100.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 130 NULL 128 99.22 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,`test`.`t1`.`b` AS `b` from `test`.`t1` where (`test`.`t1`.`a1` = 'b' or `test`.`t1`.`a1` = 'd' or `test`.`t1`.`a1` = 'a' or `test`.`t1`.`a1` = 'c') and `test`.`t1`.`a2` > 'a' and `test`.`t1`.`c` > 'a111' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
select a1,a2,min(b),c from t2 where (a2 = 'a') and (c = 'a111') group by a1;
a1 a2 min(b) c
a a a a111
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'b') or (b = 'a') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t2
where (c > 'a000') and (c <= 'd999') and (c like '_8__') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1, a2, b, c, min(d), max(d) from t1 group by a1,a2,b,c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_1 163 NULL 1000
+1 SIMPLE t1 index NULL idx_t1_1 163 NULL 128
explain select a1,a2,count(a2) from t1 group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using index
explain extended select a1,a2,count(a2) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1000 100.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 128 100.00 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2`,count(`test`.`t1`.`a2`) AS `count(a2)` from `test`.`t1` where `test`.`t1`.`a1` > 'a' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain extended select sum(ord(a1)) from t1 where (a1 > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 1000 100.00 Using where; Using index
+1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_2 65 NULL 128 100.00 Using where; Using index
Warnings:
Note 1003 select sum(ord(`test`.`t1`.`a1`)) AS `sum(ord(a1))` from `test`.`t1` where `test`.`t1`.`a1` > 'a' group by `test`.`t1`.`a1`,`test`.`t1`.`a2`,`test`.`t1`.`b`
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,max(c),min(c) from t2 where (a2 = 'a') and (b = 'a' or b = 'b') group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL idx_t2_1 163 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select distinct(a1) from t1 where ord(a2) = 98;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL idx_t1_2 147 NULL 1000 Using where; Using index
+1 SIMPLE t1 index NULL idx_t1_2 147 NULL 128 Using where; Using index
select distinct(a1) from t1 where ord(a2) = 98;
a1
a
@@ -2282,7 +2285,7 @@ c
d
explain select a1 from t1 where a2 = 'b' group by a1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by
select a1 from t1 where a2 = 'b' group by a1;
a1
a
@@ -2291,7 +2294,7 @@ c
d
explain select distinct a1 from t1 where a2 = 'b';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx_t1_1 130 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range NULL idx_t1_1 130 NULL 5 Using where; Using index for group-by
select distinct a1 from t1 where a2 = 'b';
a1
a
@@ -2463,10 +2466,11 @@ CREATE TABLE t1 (a int, b int, PRIMARY KEY (a,b), KEY b (b)) engine=RocksDB;
INSERT INTO t1 VALUES (1,1),(1,2),(1,0),(1,3);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
explain SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,b PRIMARY 8 NULL 501 Using where; Using index for group-by
+1 SIMPLE t1 range PRIMARY,b PRIMARY 8 NULL 2 Using where; Using index for group-by
SELECT MAX(b), a FROM t1 WHERE b < 2 AND a = 1 GROUP BY a;
MAX(b) a
1 1
@@ -2477,10 +2481,11 @@ CREATE TABLE t2 (a int, b int, c int, PRIMARY KEY (a,b,c)) engine=RocksDB;
INSERT INTO t2 SELECT a,b,b FROM t1;
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
explain SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY PRIMARY 12 NULL 251 Using where; Using index for group-by
+1 SIMPLE t2 range PRIMARY PRIMARY 12 NULL 2 Using where; Using index for group-by
SELECT MIN(c) FROM t2 WHERE b = 2 and a = 1 and c > 1 GROUP BY a;
MIN(c)
2
@@ -2490,10 +2495,11 @@ INSERT INTO t1 (a, b) VALUES (1,1), (1,2), (1,3), (1,4), (1,5),
(2,2), (2,3), (2,1), (3,1), (4,1), (4,2), (4,3), (4,4), (4,5), (4,6);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 6 Using index for group-by
FLUSH STATUS;
SELECT max(b), a FROM t1 GROUP BY a;
max(b) a
@@ -2508,7 +2514,7 @@ Handler_read_next 0
Handler_read_retry 0
EXPLAIN SELECT max(b), a FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 6 Using index for group-by
FLUSH STATUS;
CREATE TABLE t2 engine=RocksDB SELECT max(b), a FROM t1 GROUP BY a;
SHOW STATUS LIKE 'handler_read__e%';
@@ -2544,54 +2550,54 @@ Handler_read_retry 0
EXPLAIN (SELECT max(b), a FROM t1 GROUP BY a) UNION
(SELECT max(b), a FROM t1 GROUP BY a);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1 range NULL a 5 NULL 251 Using index for group-by
-2 UNION t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY t1 range NULL a 5 NULL 6 Using index for group-by
+2 UNION t1 range NULL a 5 NULL 6 Using index for group-by
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using index
-2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 6 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 1000 Using index
+1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer index NULL a 10 NULL 1000 Using index
-2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY t1 range a a 5 NULL 6 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 251
-1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 4 Using index
-2 MATERIALIZED t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 6
+1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 3 Using index
+2 MATERIALIZED t1 range a a 5 NULL 6 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer range NULL a 5 NULL 251 Using index for group-by
-2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY t1_outer range NULL a 5 NULL 6 Using index for group-by
+2 SUBQUERY t1 range a a 5 NULL 6 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
AND t1_outer1.b = t1_outer2.b;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer1 ref a a 5 const 4 Using where; Using index
-1 PRIMARY t1_outer2 index NULL a 10 NULL 1000 Using where; Using index; Using join buffer (flat, BNL join)
-2 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index
+1 PRIMARY t1_outer1 ref a a 10 const,test.t1_outer2.b 1 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 6 Using where; Using index for group-by
EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t1_outer2 index NULL a 10 NULL 1000 Using index
-2 SUBQUERY t1_outer index NULL a 10 NULL 1000 Using index
-3 SUBQUERY t1 range NULL a 5 NULL 251 Using index for group-by
+1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1_outer index NULL a 10 NULL 15 Using index
+3 SUBQUERY t1 range a a 5 NULL 6 Using where; Using index for group-by
CREATE TABLE t3 LIKE t1;
FLUSH STATUS;
INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
SHOW STATUS LIKE 'handler_read__e%';
Variable_name Value
-Handler_read_key 8
+Handler_read_key 13
Handler_read_next 0
Handler_read_retry 0
DELETE FROM t3;
@@ -2626,10 +2632,11 @@ INSERT INTO t1 VALUES
(4), (2), (1), (2), (2), (4), (1), (4);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN SELECT DISTINCT(a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx 5 NULL 4 Using index for group-by
SELECT DISTINCT(a) FROM t1;
a
1
@@ -2637,7 +2644,7 @@ a
4
EXPLAIN SELECT SQL_BIG_RESULT DISTINCT(a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL idx 5 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL idx 5 NULL 4 Using index for group-by
SELECT SQL_BIG_RESULT DISTINCT(a) FROM t1;
a
1
@@ -2650,11 +2657,12 @@ INSERT INTO t1 SELECT a + 1, b FROM t1;
INSERT INTO t1 SELECT a + 2, b FROM t1;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a DESC;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 1000 Using temporary; Using filesort
+1 SIMPLE t1 ALL NULL NULL NULL NULL 12 Using temporary; Using filesort
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a DESC;
a MIN(b) MAX(b)
4 1 3
@@ -2665,7 +2673,7 @@ CREATE INDEX break_it ON t1 (a, b);
EXPLAIN
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL break_it 10 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL break_it 10 NULL 4 Using index for group-by
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a;
a MIN(b) MAX(b)
1 1 3
@@ -2675,7 +2683,7 @@ a MIN(b) MAX(b)
EXPLAIN
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a DESC;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL break_it 10 NULL 251 Using index for group-by; Using temporary; Using filesort
+1 SIMPLE t1 range NULL break_it 10 NULL 4 Using index for group-by; Using temporary; Using filesort
SELECT a, MIN(b), MAX(b) FROM t1 GROUP BY a ORDER BY a DESC;
a MIN(b) MAX(b)
4 1 3
@@ -2685,7 +2693,7 @@ a MIN(b) MAX(b)
EXPLAIN
SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL break_it 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL break_it 10 NULL 12 Using index
SELECT a, MIN(b), MAX(b), AVG(b) FROM t1 GROUP BY a ORDER BY a DESC;
a MIN(b) MAX(b) AVG(b)
4 1 3 2.0000
@@ -2706,6 +2714,7 @@ insert into t1 (a,b) values
insert into t1 (a,b) select a, max(b)+1 from t1 where a = 0 group by a;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
select * from t1;
a b
@@ -2768,7 +2777,7 @@ a b
3 13
explain extended select sql_buffer_result a, max(b)+1 from t1 where a = 0 group by a;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 ref PRIMARY,index PRIMARY 4 const 15 100.00 Using index; Using temporary
+1 SIMPLE t1 ref PRIMARY,index PRIMARY 4 const 15 6.67 Using index; Using temporary
Warnings:
Note 1003 select sql_buffer_result `test`.`t1`.`a` AS `a`,max(`test`.`t1`.`b`) + 1 AS `max(b)+1` from `test`.`t1` where `test`.`t1`.`a` = 0 group by `test`.`t1`.`a`
drop table t1;
@@ -2780,10 +2789,11 @@ INSERT INTO t1 SELECT * FROM t1;
INSERT INTO t1 SELECT a,b,c+1,d FROM t1;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN SELECT DISTINCT c FROM t1 WHERE d=4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL foo 10 NULL 63 Using where; Using index for group-by
+1 SIMPLE t1 range NULL foo 10 NULL 3 Using where; Using index for group-by
SELECT DISTINCT c FROM t1 WHERE d=4;
c
1
@@ -2799,13 +2809,14 @@ INSERT INTO t SELECT * FROM t;
INSERT INTO t SELECT * FROM t;
ANALYZE TABLE t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
# test MIN
#should use range with index for group by
EXPLAIN
SELECT a, MIN(b) FROM t WHERE b <> 0 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range NULL a 10 NULL 251 Using where; Using index for group-by
+1 SIMPLE t range NULL a 10 NULL 2 Using where; Using index for group-by
#should return 1 row
SELECT a, MIN(b) FROM t WHERE b <> 0 GROUP BY a;
a MIN(b)
@@ -2815,7 +2826,7 @@ a MIN(b)
EXPLAIN
SELECT a, MAX(b) FROM t WHERE b <> 1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range NULL a 10 NULL 251 Using where; Using index for group-by
+1 SIMPLE t range NULL a 10 NULL 2 Using where; Using index for group-by
#should return 1 row
SELECT a, MAX(b) FROM t WHERE b <> 1 GROUP BY a;
a MAX(b)
@@ -2826,7 +2837,7 @@ INSERT INTO t SELECT a, 2 FROM t;
EXPLAIN
SELECT a, MAX(b) FROM t WHERE b > 0 AND b < 2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range NULL a 10 NULL 251 Using where; Using index for group-by
+1 SIMPLE t range NULL a 10 NULL 2 Using where; Using index for group-by
#should return 1 row
SELECT a, MAX(b) FROM t WHERE b > 0 AND b < 2 GROUP BY a;
a MAX(b)
@@ -2841,6 +2852,7 @@ INSERT INTO t VALUES (2,0), (2,0), (2,1), (2,1);
INSERT INTO t SELECT * FROM t;
ANALYZE TABLE t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
SELECT a, MAX(b) FROM t WHERE 0=b+0 GROUP BY a;
a MAX(b)
@@ -2862,6 +2874,7 @@ CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL, KEY (b)) engine=RocksDB;
INSERT INTO t1 VALUES(1,1),(2,1);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
SELECT 1 AS c, b FROM t1 WHERE b IN (1,2) GROUP BY c, b;
c b
@@ -2880,6 +2893,7 @@ CREATE TABLE t1 ( a INT, KEY (a) ) engine=RocksDB;
INSERT INTO t1 VALUES (1), (2), (3);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = NULL;
@@ -2940,7 +2954,7 @@ NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
id select_type table type possible_keys key key_len ref rows Extra
-x x x x x x x x x Using where; Using index
+x x x x x x x x x Impossible WHERE noticed after reading const tables
x x x x x x x x x Using where; Using index
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
MIN( a )
@@ -2955,6 +2969,7 @@ NULL
INSERT INTO t1 VALUES (NULL), (NULL);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = NULL;
@@ -3015,7 +3030,7 @@ NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
id select_type table type possible_keys key key_len ref rows Extra
-x x x x x x x x x Using where; Using index
+x x x x x x x x x Impossible WHERE noticed after reading const tables
x x x x x x x x x Using where; Using index
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
MIN( a )
@@ -3033,6 +3048,7 @@ CREATE TABLE t1 ( a INT NOT NULL PRIMARY KEY) engine=RocksDB;
INSERT INTO t1 VALUES (1), (2), (3);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
#
# NULL-safe operator test disabled for non-NULL indexed columns.
@@ -3097,7 +3113,7 @@ NULL
EXPLAIN
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
id select_type table type possible_keys key key_len ref rows Extra
-x x x x x x x x x Using where; Using index
+x x x x x x x x x Impossible WHERE noticed after reading const tables
x x x x x x x x x Using where; Using index
SELECT MIN( a ) FROM t1 WHERE a = (SELECT a FROM t1 WHERE a < 0);
MIN( a )
@@ -3133,6 +3149,7 @@ INSERT INTO t1 SELECT a, b + 4, 1 FROM t1;
INSERT INTO t1 SELECT a + 1, b, 1 FROM t1;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CREATE TABLE t2 (a INT, b INT, c INT, d INT, e INT, f INT, KEY (a,b,c)) engine=RocksDB;
INSERT INTO t2 VALUES (1,1,1,1,1,1), (1,2,1,1,1,1), (1,3,1,1,1,1),
@@ -3141,48 +3158,49 @@ INSERT INTO t2 SELECT a, b + 4, c,d,e,f FROM t2;
INSERT INTO t2 SELECT a + 1, b, c,d,e,f FROM t2;
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 3 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1;
COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a,b) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 10 NULL 17 Using index for group-by
SELECT COUNT(DISTINCT a,b) FROM t1;
COUNT(DISTINCT a,b)
16
EXPLAIN SELECT COUNT(DISTINCT b,a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 10 NULL 17 Using index for group-by
SELECT COUNT(DISTINCT b,a) FROM t1;
COUNT(DISTINCT b,a)
16
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT COUNT(DISTINCT b) FROM t1;
COUNT(DISTINCT b)
8
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 3 Using index for group-by
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY a;
COUNT(DISTINCT a)
1
1
EXPLAIN SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 10 NULL 17 Using index for group-by
SELECT COUNT(DISTINCT b) FROM t1 GROUP BY a;
COUNT(DISTINCT b)
8
8
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 10 NULL 1000 Using index; Using filesort
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index; Using filesort
SELECT COUNT(DISTINCT a) FROM t1 GROUP BY b;
COUNT(DISTINCT a)
2
@@ -3195,94 +3213,94 @@ COUNT(DISTINCT a)
2
EXPLAIN SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT DISTINCT COUNT(DISTINCT a) FROM t1;
COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a, b + 0) FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT COUNT(DISTINCT a, b + 0) FROM t1;
COUNT(DISTINCT a, b + 0)
16
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 10 NULL 1000 Using index
+1 SIMPLE t1 index NULL a 10 NULL 16 Using index
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT b) < 10;
COUNT(DISTINCT a)
2
EXPLAIN SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t1 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a) FROM t1 HAVING COUNT(DISTINCT c) < 10;
COUNT(DISTINCT a)
2
EXPLAIN SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 3 Using index for group-by
SELECT 1 FROM t1 HAVING COUNT(DISTINCT a) < 10;
1
1
EXPLAIN SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 10 NULL 501 Using index for group-by
+1 SIMPLE t1 range NULL a 10 NULL 17 Using index for group-by
SELECT 1 FROM t1 GROUP BY a HAVING COUNT(DISTINCT b) > 1;
1
1
1
EXPLAIN SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1_1 index NULL a 10 NULL 1000 Using index; Using temporary; Using filesort
-1 SIMPLE t1_2 index NULL a 10 NULL 1000 Using index; Using join buffer (flat, BNL join)
+1 SIMPLE t1_1 index NULL a 10 NULL 16 Using index; Using temporary; Using filesort
+1 SIMPLE t1_2 index NULL a 10 NULL 16 Using index; Using join buffer (flat, BNL join)
SELECT COUNT(DISTINCT t1_1.a) FROM t1 t1_1, t1 t1_2 GROUP BY t1_1.a;
COUNT(DISTINCT t1_1.a)
1
1
EXPLAIN SELECT COUNT(DISTINCT a), 12 FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range NULL a 5 NULL 251 Using index for group-by
+1 SIMPLE t1 range NULL a 5 NULL 3 Using index for group-by
SELECT COUNT(DISTINCT a), 12 FROM t1;
COUNT(DISTINCT a) 12
2 12
EXPLAIN SELECT COUNT(DISTINCT a, b, c) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 15 NULL 501 Using index for group-by
+1 SIMPLE t2 range NULL a 15 NULL 17 Using index for group-by
SELECT COUNT(DISTINCT a, b, c) FROM t2;
COUNT(DISTINCT a, b, c)
16
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 5 NULL 126 Using index for group-by
+1 SIMPLE t2 range NULL a 5 NULL 3 Using index for group-by
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT a) FROM t2;
COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT a)
2 3 1.5000
EXPLAIN SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a), SUM(DISTINCT a), AVG(DISTINCT f) FROM t2;
COUNT(DISTINCT a) SUM(DISTINCT a) AVG(DISTINCT f)
2 3 1.0000
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 10 NULL 251 Using index for group-by
+1 SIMPLE t2 range NULL a 10 NULL 17 Using index for group-by
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, a) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, a)
16 16
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, f) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, f)
16 8
EXPLAIN SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16
SELECT COUNT(DISTINCT a, b), COUNT(DISTINCT b, d) FROM t2;
COUNT(DISTINCT a, b) COUNT(DISTINCT b, d)
16 8
EXPLAIN SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 15 NULL 501 Using index for group-by
+1 SIMPLE t2 range NULL a 15 NULL 17 Using index for group-by
SELECT a, c, COUNT(DISTINCT c, a, b) FROM t2 GROUP BY a, b, c;
a c COUNT(DISTINCT c, a, b)
1 1 1
@@ -3304,41 +3322,41 @@ a c COUNT(DISTINCT c, a, b)
EXPLAIN SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range a a 15 NULL 501 Using where; Using index for group-by
+1 SIMPLE t2 range a a 15 NULL 17 Using where; Using index for group-by
SELECT COUNT(DISTINCT c, a, b) FROM t2
WHERE a > 5 AND b BETWEEN 10 AND 20 GROUP BY a, b, c;
COUNT(DISTINCT c, a, b)
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref a a 5 const 1000 Using where; Using index
+1 SIMPLE t2 ref a a 5 const 16 Using where; Using index
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 WHERE a = 5
GROUP BY b;
COUNT(DISTINCT b) SUM(DISTINCT b)
EXPLAIN SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 10 NULL 251 Using index for group-by
+1 SIMPLE t2 range NULL a 10 NULL 17 Using index for group-by
SELECT a, COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
a COUNT(DISTINCT b) SUM(DISTINCT b)
1 8 36
2 8 36
EXPLAIN SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 10 NULL 251 Using index for group-by
+1 SIMPLE t2 range NULL a 10 NULL 17 Using index for group-by
SELECT COUNT(DISTINCT b), SUM(DISTINCT b) FROM t2 GROUP BY a;
COUNT(DISTINCT b) SUM(DISTINCT b)
8 36
8 36
EXPLAIN SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 1000 Using where
+1 SIMPLE t2 ALL NULL NULL NULL NULL 16 Using where
SELECT COUNT(DISTINCT a, b) FROM t2 WHERE c = 13 AND d = 42;
COUNT(DISTINCT a, b)
0
EXPLAIN SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 15 NULL 126 Using where; Using index for group-by
+1 SIMPLE t2 range NULL a 15 NULL 3 Using where; Using index for group-by
SELECT a, COUNT(DISTINCT a), SUM(DISTINCT a) FROM t2
WHERE b = 13 AND c = 42 GROUP BY a;
a COUNT(DISTINCT a) SUM(DISTINCT a)
@@ -3346,20 +3364,20 @@ a COUNT(DISTINCT a) SUM(DISTINCT a)
# the second part of count(..) is defined by a constant predicate
EXPLAIN SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL a 15 NULL 1000 Using where; Using index
+1 SIMPLE t2 index NULL a 15 NULL 16 Using where; Using index
SELECT COUNT(DISTINCT a, b), SUM(DISTINCT a) FROM t2 WHERE b = 42;
COUNT(DISTINCT a, b) SUM(DISTINCT a)
0 NULL
EXPLAIN SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL a 15 NULL 1000 Using index
+1 SIMPLE t2 index NULL a 15 NULL 16 Using index
SELECT SUM(DISTINCT a), MAX(b) FROM t2 GROUP BY a;
SUM(DISTINCT a) MAX(b)
1 8
2 8
EXPLAIN SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range NULL a 15 NULL 501 Using index for group-by
+1 SIMPLE t2 range NULL a 15 NULL 17 Using index for group-by
SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
42 * (a + c + COUNT(DISTINCT c, a, b))
126
@@ -3380,7 +3398,7 @@ SELECT 42 * (a + c + COUNT(DISTINCT c, a, b)) FROM t2 GROUP BY a, b, c;
168
EXPLAIN SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 index NULL a 15 NULL 1000 Using index
+1 SIMPLE t2 index NULL a 15 NULL 16 Using index
SELECT (SUM(DISTINCT a) + MAX(b)) FROM t2 GROUP BY a;
(SUM(DISTINCT a) + MAX(b))
9
@@ -3400,6 +3418,7 @@ insert into t1 values(1,'A'),(1 , 'B'), (1, 'C'), (2, 'A'),
(3, 'A'), (3, 'B'), (3, 'C'), (3, 'D');
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
f1 COUNT(DISTINCT f2)
@@ -3408,7 +3427,7 @@ f1 COUNT(DISTINCT f2)
3 4
explain SELECT f1, COUNT(DISTINCT f2) FROM t1 GROUP BY f1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 5 NULL 1000 Using index
+1 SIMPLE t1 index NULL PRIMARY 5 NULL 8 Using index
drop table t1;
# End of test#50539.
#
@@ -3419,9 +3438,11 @@ CREATE TABLE t (a INT, b INT, KEY(a,b)) engine=RocksDB;
INSERT INTO t VALUES (1,1), (2,2), (3,3), (4,4), (1,0), (3,2), (4,5);
ANALYZE TABLE t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
ANALYZE TABLE t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
a SUM(DISTINCT a) MIN(b)
@@ -3431,7 +3452,7 @@ a SUM(DISTINCT a) MIN(b)
4 4 4
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b) FROM t GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index NULL a 10 NULL 1000 Using index
+1 SIMPLE t index NULL a 10 NULL 7 Using index
SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
a SUM(DISTINCT a) MAX(b)
1 1 1
@@ -3440,7 +3461,7 @@ a SUM(DISTINCT a) MAX(b)
4 4 5
EXPLAIN SELECT a, SUM(DISTINCT a), MAX(b) FROM t GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index NULL a 10 NULL 1000 Using index
+1 SIMPLE t index NULL a 10 NULL 7 Using index
SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
a MAX(b)
1 1
@@ -3449,13 +3470,13 @@ a MAX(b)
4 5
EXPLAIN SELECT a, MAX(b) FROM t GROUP BY a HAVING SUM(DISTINCT a);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index NULL a 10 NULL 1000 Using index
+1 SIMPLE t index NULL a 10 NULL 7 Using index
SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
SUM(DISTINCT a) MIN(b) MAX(b)
10 0 5
EXPLAIN SELECT SUM(DISTINCT a), MIN(b), MAX(b) FROM t;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index NULL a 10 NULL 1000 Using index
+1 SIMPLE t index NULL a 10 NULL 7 Using index
SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
a SUM(DISTINCT a) MIN(b) MAX(b)
1 1 0 1
@@ -3464,7 +3485,7 @@ a SUM(DISTINCT a) MIN(b) MAX(b)
4 4 4 5
EXPLAIN SELECT a, SUM(DISTINCT a), MIN(b), MAX(b) FROM t GROUP BY a;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t index NULL a 10 NULL 1000 Using index
+1 SIMPLE t index NULL a 10 NULL 7 Using index
DROP TABLE t;
#
# Bug#18109609: LOOSE INDEX SCAN IS NOT USED WHEN IT SHOULD
@@ -3480,10 +3501,11 @@ INSERT INTO t1(c1,c2) VALUES
(4,14), (4,15), (4,16), (4,17), (4,18), (4,19), (4,20),(5,5);
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
EXPLAIN SELECT MAX(c2), c1 FROM t1 WHERE c1 = 4 GROUP BY c1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref c1 c1 5 const 1000 Using index
+1 SIMPLE t1 ref c1 c1 5 const 28 Using index
FLUSH STATUS;
SELECT MAX(c2), c1 FROM t1 WHERE c1 = 4 GROUP BY c1;
MAX(c2) c1
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result
index 7fb9055083b..7c4f57b61bd 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb.result
@@ -28,6 +28,7 @@ insert into t1 values (1, 100, 100), (1, 200, 200), (1, 300, 300);
set global rocksdb_force_flush_memtable_now=1;
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
explain select * from t1 where key1 = 1;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result
index 4603e049724..efe4eaf2141 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/index_merge_rocksdb2.result
@@ -23,10 +23,11 @@ INDEX i8(key8)
);
analyze table t0;
Table Op Msg_type Msg_text
+test.t0 analyze status Engine-independent statistics collected
test.t0 analyze status OK
explain select * from t0 where key1 < 3 or key1 > 1020;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t0 range i1 i1 4 NULL 4 Using index condition; Using where
+1 SIMPLE t0 range i1 i1 4 NULL 4 Using index condition
explain
select * from t0 where key1 < 3 or key2 > 1020;
id select_type table type possible_keys key key_len ref rows Extra
@@ -286,7 +287,7 @@ id select_type table type possible_keys key key_len ref rows Extra
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
explain select * from (select * from t1 where key1 = 3 or key2 =3) as Z where key8 >5;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range i1,i2,i8 i8 4 NULL 2 Using index condition; Using where
+1 SIMPLE t1 index_merge i1,i2,i8 i1,i2 4,4 NULL 4 Using union(i1,i2); Using where
create table t3 like t0;
insert into t3 select * from t0;
alter table t3 add key9 int not null, add index i9(key9);
@@ -826,6 +827,7 @@ insert into t1 (key1a, key1b, key2a, key2b, key3a, key3b)
select key1a, key1b, key2a, key2b, key3a, key3b from t1;
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
select count(*) from t1;
count(*)
@@ -1330,7 +1332,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail2ok key1 4 const 2 Using where
explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok PRIMARY,key1 4,4 NULL ROWS Using union(PRIMARY,key1); Using where
+1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok pktail2ok,key1 8,4 NULL ROWS Using sort_union(pktail2ok,key1); Using where
explain select * from t1 where pktail3bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail3bad EITHER_KEY 4 const ROWS Using where
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result
index 61f005c1758..578a26b3e4f 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/innodb_i_s_tables_disabled.result
@@ -56,7 +56,6 @@ buffer_pages_written buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NUL
buffer_index_pages_written buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of index pages written (innodb_index_pages_written)
buffer_non_index_pages_written buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of non index pages written (innodb_non_index_pages_written)
buffer_pages_read buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of pages read (innodb_pages_read)
-buffer_pages0_read buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of page 0 read (innodb_pages0_read)
buffer_index_sec_rec_cluster_reads buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of secondary record reads triggered cluster read
buffer_index_sec_rec_cluster_reads_avoided buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Number of secondary record reads avoided triggering cluster read
buffer_data_reads buffer 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled status_counter Amount of data read in bytes (innodb_data_reads)
@@ -165,7 +164,6 @@ trx_nl_ro_commits transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL N
trx_commits_insert_update transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of transactions committed with inserts and updates
trx_rollbacks transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of transactions rolled back
trx_rollbacks_savepoint transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of transactions rolled back to savepoint
-trx_rollback_active transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of resurrected active transactions rolled back
trx_active_transactions transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of active transactions
trx_rseg_history_len transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled value Length of the TRX_RSEG_HISTORY list
trx_undo_slots_used transaction 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL disabled counter Number of undo slots used
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/issue884.result b/storage/rocksdb/mysql-test/rocksdb/r/issue884.result
index acfaca96d68..60c9674516a 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/issue884.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/issue884.result
@@ -18,6 +18,7 @@ key n (n),
key d (d, a)
) engine = rocksdb default charset = latin1;
Table Op Msg_type Msg_text
+test.test analyze status Engine-independent statistics collected
test.test analyze status OK
explain
select * from test where d = 10 and a = 10 and b = 2;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/max_open_files.result b/storage/rocksdb/mysql-test/rocksdb/r/max_open_files.result
index 5d34f4e9640..d3aac194bc4 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/max_open_files.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/max_open_files.result
@@ -19,3 +19,4 @@ SELECT @@global.rocksdb_max_open_files;
SELECT FLOOR(@@global.open_files_limit / 2) = @@global.rocksdb_max_open_files;
FLOOR(@@global.open_files_limit / 2) = @@global.rocksdb_max_open_files
1
+# restart
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/misc.result b/storage/rocksdb/mysql-test/rocksdb/r/misc.result
index 6087928b80f..b2e5d04f6f8 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/misc.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/misc.result
@@ -46,6 +46,8 @@ db User NULL NULL
event db NULL NULL
event name NULL NULL
func name NULL NULL
+global_priv Host NULL NULL
+global_priv User NULL NULL
gtid_slave_pos domain_id NULL NULL
gtid_slave_pos sub_id NULL NULL
help_category help_category_id NULL NULL
@@ -56,8 +58,6 @@ help_relation help_keyword_id NULL NULL
help_relation help_topic_id NULL NULL
help_topic help_topic_id NULL NULL
help_topic name NULL NULL
-host Db NULL NULL
-host Host NULL NULL
index_stats db_name NULL NULL
index_stats index_name NULL NULL
index_stats prefix_arity NULL NULL
@@ -92,5 +92,3 @@ time_zone_transition Time_zone_id NULL NULL
time_zone_transition Transition_time NULL NULL
time_zone_transition_type Time_zone_id NULL NULL
time_zone_transition_type Transition_type_id NULL NULL
-user Host NULL NULL
-user User NULL NULL
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result b/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result
index 3a631d2925b..6ea13872033 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/no_merge_sort.result
@@ -1,63 +1,123 @@
Warnings:
Note 1051 Unknown table 'test.ti_nk'
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
skip_merge_sort
true
DROP TABLE ti_nk;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/partition.result b/storage/rocksdb/mysql-test/rocksdb/r/partition.result
index 1ba966e9e07..a7f2a6112c1 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/partition.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/partition.result
@@ -46,6 +46,7 @@ CREATE TABLE t1 (i INT, j INT, k INT, PRIMARY KEY (i)) ENGINE = ROCKSDB PARTITIO
Table Op Msg_type Msg_text
test.t1 optimize status OK
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
Table Op Msg_type Msg_text
test.t1 repair status OK
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result b/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result
index 89ebe760384..ce3d7d9147e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/records_in_range.result
@@ -1,3 +1,4 @@
+# restart
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (
i INT,
@@ -144,7 +145,7 @@ Warnings:
Note 1003 select `test`.`t1`.`i` AS `i`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`b` >= 500 and `test`.`t1`.`b` <= 500
explain extended select * from t1 where a< 750 and b> 500 and b< 750;
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE t1 range ka,kb ka 5 NULL 1000 100.00 Using index condition; Using where
+1 SIMPLE t1 range ka,kb ka 5 NULL 1000 5.00 Using index condition; Using where
Warnings:
Note 1003 select `test`.`t1`.`i` AS `i`,`test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` where `test`.`t1`.`a` < 750 and `test`.`t1`.`b` > 500 and `test`.`t1`.`b` < 750
drop index ka on t1;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result
index e00872f2903..f2f9adebf46 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb.result
@@ -1405,6 +1405,7 @@ create table t1 (i int primary key auto_increment) engine=RocksDB;
insert into t1 values (null);
insert into t1 values (null);
SET GLOBAL ROCKSDB_PAUSE_BACKGROUND_WORK = @ORIG_PAUSE_BACKGROUND_WORK;
+# restart
SET @ORIG_PAUSE_BACKGROUND_WORK = @@ROCKSDB_PAUSE_BACKGROUND_WORK;
SET GLOBAL ROCKSDB_PAUSE_BACKGROUND_WORK = 1;
insert into t1 values (null);
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_options.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_options.result
index 6c3d85b760c..80b6301a07c 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_options.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_options.result
@@ -7,6 +7,7 @@ primary key (a) comment 'z') engine=rocksdb;
insert into t1 values (1);
insert into t2 values (2);
insert into t3 values (2);
+# restart
Default options for all column families:
@@ -32,6 +33,7 @@ z WRITE_BUFFER_SIZE 12582912
__system__ MAX_BYTES_FOR_LEVEL_MULTIPLIER 10.000000
__system__ TARGET_FILE_SIZE_BASE 1048576
__system__ WRITE_BUFFER_SIZE 12582912
+# restart: --rocksdb_override_cf_options=cf1={write_buffer_size=8m;target_file_size_base=2m};cf2={write_buffer_size=16m;max_bytes_for_level_multiplier=8};z={target_file_size_base=4m};
Individualized options for column families:
@@ -57,5 +59,6 @@ z WRITE_BUFFER_SIZE 12582912
__system__ MAX_BYTES_FOR_LEVEL_MULTIPLIER 10.000000
__system__ TARGET_FILE_SIZE_BASE 1048576
__system__ WRITE_BUFFER_SIZE 12582912
+# restart: --rocksdb_override_cf_options=cf1={write_buffer_size=8m;target_file_size_base=2m};cf2={write_buffer_size=16m;max_bytes_for_level_multiplier=8};z={target_file_size_base=4m};
drop table t1,t2,t3;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result
index ed226f0d8ba..32bb70a7464 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_cf_per_partition.result
@@ -350,6 +350,8 @@ cf_name
another_cf_for_p5
ANALYZE TABLE t2;
Table Op Msg_type Msg_text
+test.t2 analyze status Engine-independent statistics collected
+test.t2 analyze Warning Engine-independent statistics are not collected for column 'col5'
test.t2 analyze status OK
EXPLAIN PARTITIONS SELECT * FROM t2 WHERE col3 = 0x4 AND col2 = 0x34567;
id select_type table partitions type possible_keys key key_len ref rows Extra
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_checksums.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_checksums.result
index aae6de12f6a..e4b757ef3b0 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_checksums.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_checksums.result
@@ -125,4 +125,5 @@ set session debug_dbug= "-d,myrocks_simulate_bad_key_checksum1";
set @@global.rocksdb_store_row_debug_checksums=@save_rocksdb_store_row_debug_checksums;
set @@global.rocksdb_verify_row_debug_checksums=@save_rocksdb_verify_row_debug_checksums;
set @@global.rocksdb_checksums_pct=@save_rocksdb_checksums_pct;
+# restart
drop table t2,t3,t4;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_parts.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_parts.result
index 2fde11c2a08..70bef39eceb 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_parts.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_parts.result
@@ -131,6 +131,7 @@ DROP DATABASE db3;
CREATE TABLE t1 (a INT) ENGINE=RocksDB PARTITION BY HASH(a) PARTITIONS 2;
INSERT INTO t1 (a) VALUES (1),(2);
ALTER TABLE t1 ADD PARTITION PARTITIONS 2;
+# restart
SELECT 1;
1
1
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result
index a925c21e188..bcda9341f1f 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/rocksdb_range2.result
@@ -1,13 +1,14 @@
create table t1 (id1 bigint, id2 bigint, c1 bigint, c2 bigint, c3 bigint, c4 bigint, c5 bigint, c6 bigint, c7 bigint, primary key (id1, id2), index i(c1, c2));
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
select count(*) from t1;
count(*)
10000
explain select c1 from t1 where c1 > 5 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range i i 9 NULL # Using where; Using index
+1 SIMPLE t1 index i i 18 NULL # Using where; Using index
drop table t1;
#
# MDEV-17414: MyROCKS order desc limit 1 fails
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/select.result b/storage/rocksdb/mysql-test/rocksdb/r/select.result
index fc3825d5377..7ea43adc9ea 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/select.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/select.result
@@ -115,6 +115,8 @@ SELECT t1.a, t2.b FROM t2, t1 WHERE t1.a = t2.a ORDER BY t2.b, t1.a
INTO OUTFILE '<DATADIR>/select.out'
CHARACTER SET utf8
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '''';
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
200,'bar'
200,'bar'
100,'foobar'
@@ -126,8 +128,12 @@ INTO DUMPFILE '<DATADIR>/select.dump';
ERROR 42000: Result consisted of more than one row
SELECT t1.*, t2.* FROM t1, t2 ORDER BY t2.b, t1.a, t2.a, t1.b, t1.pk, t2.pk LIMIT 1
INTO DUMPFILE '<DATADIR>/select.dump';
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
1z2200bar3
SELECT MIN(a), MAX(a) FROM t1 INTO @min, @max;
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
SELECT @min, @max;
@min @max
1 200
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/show_table_status.result b/storage/rocksdb/mysql-test/rocksdb/r/show_table_status.result
index d95549be4c1..139d323bb1a 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/show_table_status.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/show_table_status.result
@@ -114,6 +114,7 @@ from information_schema.tables
where table_schema=database() and table_name='t1';
select sleep(2);
sleep(2) 0
+# restart
select
create_time=(select create_time from t2) /* should not change */,
update_time
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/skip_validate_tmp_table.result b/storage/rocksdb/mysql-test/rocksdb/r/skip_validate_tmp_table.result
index 92906f22b1e..d67c4cbbbc7 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/skip_validate_tmp_table.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/skip_validate_tmp_table.result
@@ -1,4 +1,5 @@
create table t1 (pk int primary key) engine=rocksdb;
+# restart
show tables;
Tables_in_test
#mysql50#t1#sql-test
@@ -11,6 +12,7 @@ show tables;
Tables_in_test
#mysql50#t1#sql-test
t2
+# restart
show tables;
Tables_in_test
create table t2 (pk int primary key) engine=rocksdb;
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/statistics.result b/storage/rocksdb/mysql-test/rocksdb/r/statistics.result
index 579c4adc11d..1d0993527c9 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/statistics.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/statistics.result
@@ -37,6 +37,7 @@ table_name data_length>0 index_length>0
t1 1 1
t2 1 1
t3 1 1
+# restart
SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema = DATABASE();
table_name table_rows
t1 1000
@@ -49,8 +50,11 @@ t2 1 1
t3 1 1
analyze table t1,t2,t3,t4,t5;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
+test.t2 analyze status Engine-independent statistics collected
test.t2 analyze status OK
+test.t3 analyze status Engine-independent statistics collected
test.t3 analyze status OK
test.t4 analyze Error Table 'test.t4' doesn't exist
test.t4 analyze status Operation failed
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/truncate_table3.result b/storage/rocksdb/mysql-test/rocksdb/r/truncate_table3.result
index eda560fefdb..7c5631a2c97 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/truncate_table3.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/truncate_table3.result
@@ -6,6 +6,7 @@ call mtr.add_suppression("Column family 'rev:cf2' not found");
set global rocksdb_compact_cf = 'cf1';
set global rocksdb_compact_cf = 'rev:cf2';
set global rocksdb_signal_drop_index_thread = 1;
+# restart
CREATE TABLE t1 (
a int not null,
b int not null,
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_char_indexes.result b/storage/rocksdb/mysql-test/rocksdb/r/type_char_indexes.result
index 413c3f69f23..3a99e6a1ac8 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/type_char_indexes.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/type_char_indexes.result
@@ -45,7 +45,7 @@ t1 1 v16 1 v16 A 500 NULL NULL YES LSMTREE
INSERT INTO t1 (c,c20,v16,v128,pk) VALUES ('a','char1','varchar1a','varchar1b','1'),('a','char2','varchar2a','varchar2b','2'),('b','char3','varchar1a','varchar1b','3'),('c','char4','varchar3a','varchar3b','4');
EXPLAIN SELECT SUBSTRING(v16,0,3) FROM t1 WHERE v16 LIKE 'varchar%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index v16 v16 21 NULL # Using where; Using index
+1 SIMPLE t1 range v16 v16 19 NULL # Using where; Using index
SELECT SUBSTRING(v16,7,3) FROM t1 WHERE v16 LIKE 'varchar%';
SUBSTRING(v16,7,3)
r1a
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_date_time_indexes.result b/storage/rocksdb/mysql-test/rocksdb/r/type_date_time_indexes.result
index 120d0d81b55..77d07035a96 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/type_date_time_indexes.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/type_date_time_indexes.result
@@ -62,7 +62,7 @@ INSERT INTO t1 (d,dt,ts,t,y,pk) VALUES
(DATE(@tm),@tm,TIMESTAMP(@tm),TIME(@tm),YEAR(@tm),'12:05:00');
EXPLAIN SELECT ts FROM t1 WHERE ts > NOW();
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index ts ts 5 NULL # Using where; Using index
+1 SIMPLE t1 range ts ts 5 NULL # Using where; Using index
SELECT ts FROM t1 WHERE ts > NOW();
ts
EXPLAIN SELECT ts FROM t1 USE INDEX () WHERE ts > NOW();
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result b/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result
index 3a8cf9ed21a..668a927669a 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/type_decimal.result
@@ -25,6 +25,7 @@ insert into t1 select pk+10000, 9.0, 9.0, 'extra-data' from t1;
insert into t1 select pk+100000, 9.0, 9.0, 'extra-data' from t1;
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
# The following can't use index-only:
explain select * from t1 where col1 between -8 and 8;
@@ -34,7 +35,7 @@ id select_type table type possible_keys key key_len ref rows Extra
explain
select col1, col2 from t1 where col1 between -8 and 8;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index key1 key1 6 NULL # Using where; Using index
+1 SIMPLE t1 range key1 key1 3 NULL # Using where; Using index
select col1, col2 from t1 where col1 between -8 and 8;
col1 col2
0.3 2.5
@@ -46,7 +47,7 @@ insert into t1 values (10, -8.4, NULL, 'row2-with-null');
explain
select col1, col2 from t1 force index(key1) where col1 is null or col1 < -7;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index key1 key1 6 NULL # Using where; Using index
+1 SIMPLE t1 range key1 key1 3 NULL # Using where; Using index
select col1, col2 from t1 force index(key1) where col1 is null or col1 < -7;
col1 col2
NULL 0.9
@@ -88,11 +89,12 @@ insert into t1 select pk+10000, col1+20000, col2+20000, 'extra-data' from t1;
insert into t1 select pk+100000, col1+20000, col2+20000, 'extra-data' from t1;
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
explain
select col1, col2 from t1 force index(key1) where col1 between -800 and 800;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index key1 key1 14 NULL # Using where; Using index
+1 SIMPLE t1 range key1 key1 7 NULL # Using where; Using index
select col1, col2 from t1 force index(key1) where col1 between -800 and 800;
col1 col2
-700.002000 100.006000
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result b/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result
index a7e086fde66..4c5ef47590a 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/type_varchar.result
@@ -191,6 +191,7 @@ insert into t1 values (2, 'a', 'a');
insert into t1 values (3, 'a \t', 'a-tab');
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
# Must show 'using index' for latin1_bin and utf8_bin:
explain
@@ -306,6 +307,7 @@ insert into t1 values (2, 'a', 'a');
insert into t1 values (3, 'a \t', 'a-tab');
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
# Must show 'using index' for latin1_bin and utf8_bin:
explain
@@ -421,6 +423,7 @@ insert into t1 values (2, 'a', 'a');
insert into t1 values (3, 'a \t', 'a-tab');
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
# Must show 'using index' for latin1_bin and utf8_bin:
explain
@@ -536,6 +539,7 @@ insert into t1 values (2, 'a', 'a');
insert into t1 values (3, 'a \t', 'a-tab');
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
# Must show 'using index' for latin1_bin and utf8_bin:
explain
@@ -651,6 +655,7 @@ insert into t1 values (2, 'a', 'a');
insert into t1 values (3, 'a \t', 'a-tab');
analyze table t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
# Must show 'using index' for latin1_bin and utf8_bin:
explain
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/use_direct_reads_writes.result b/storage/rocksdb/mysql-test/rocksdb/r/use_direct_reads_writes.result
index e8456457cdd..eda49c58d7e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/use_direct_reads_writes.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/use_direct_reads_writes.result
@@ -5,10 +5,13 @@ select plugin_name, plugin_type from information_schema.plugins where plugin_nam
plugin_name plugin_type
ROCKSDB STORAGE ENGINE
Checking direct reads
+# restart
FOUND 1 /enable both use_direct_reads/ in use_direct_reads_writes.err
Checking direct writes
+# restart
FOUND 1 /enable both use_direct_io_for_flush_and_compaction/ in use_direct_reads_writes.err
Checking rocksdb_flush_log_at_trx_commit
+# restart
FOUND 1 /rocksdb_flush_log_at_trx_commit needs to be/ in use_direct_reads_writes.err
Validate flush_log settings when direct writes is enabled
set global rocksdb_flush_log_at_trx_commit=0;
@@ -16,3 +19,4 @@ set global rocksdb_flush_log_at_trx_commit=1;
ERROR 42000: Variable 'rocksdb_flush_log_at_trx_commit' can't be set to the value of '1'
set global rocksdb_flush_log_at_trx_commit=2;
ERROR 42000: Variable 'rocksdb_flush_log_at_trx_commit' can't be set to the value of '2'
+# restart
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/xa.result b/storage/rocksdb/mysql-test/rocksdb/r/xa.result
index 30cfe94e0b7..12ae2b474b6 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/xa.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/xa.result
@@ -18,6 +18,7 @@ XA PREPARE 'xa2';
connection default;
SELECT * FROM t1;
a
+# restart
connect con3,localhost,root,,test;
XA RECOVER;
formatID gtrid_length bqual_length data
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test
index 67b2d5f96d7..e084b57fbda 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test
+++ b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test
@@ -1,6 +1,8 @@
--source include/have_rocksdb.inc
--source include/not_valgrind.inc
+--let $restart_noprint=2
+
--echo #
--echo # Test how MyRocks behaves when RocksDB reports corrupted data.
--echo #
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test b/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test
index b17548063d9..99e28f3b55e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test
+++ b/storage/rocksdb/mysql-test/rocksdb/t/autoinc_debug.test
@@ -3,6 +3,8 @@
--source include/have_log_bin.inc
--source include/not_valgrind.inc
+--let $restart_noprint=2
+
--echo #
--echo # Testing upgrading from server without merges for auto_increment
--echo # to new server with such support.
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/cardinality.test b/storage/rocksdb/mysql-test/rocksdb/t/cardinality.test
index 21e4b49e560..1dcb176e4fa 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/cardinality.test
+++ b/storage/rocksdb/mysql-test/rocksdb/t/cardinality.test
@@ -2,6 +2,8 @@
--source include/restart_mysqld.inc
+set use_stat_tables= 'COMPLEMENTARY';
+
# Test memtable cardinality statistics
CREATE TABLE t0 (id int PRIMARY KEY, a int, INDEX ix_a (a)) engine=rocksdb;
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def
index 9b4dbd3c20d..11c9c08c36e 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/disabled.def
+++ b/storage/rocksdb/mysql-test/rocksdb/t/disabled.def
@@ -94,3 +94,4 @@ information_schema: MDEV-14372: unstable testcase
mysqlbinlog_gtid_skip_empty_trans_rocksdb : MariaRocks: requires GTIDs
drop_table: Hangs on shutdown
add_index_inplace: not stable result
+rocksdb_range2 : result difference, update after MDEV-16746 is fixed
diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result b/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result
index 9c20fea97ae..a1e501f78f4 100644
--- a/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result
+++ b/storage/rocksdb/mysql-test/rocksdb_rpl/r/mdev12179.result
@@ -2,6 +2,7 @@ include/master-slave.inc
[connection master]
connection server_2;
include/stop_slave.inc
+SET GLOBAL gtid_cleanup_batch_size = 999999999;
CHANGE MASTER TO master_use_gtid=slave_pos;
SET sql_log_bin=0;
CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos;
@@ -41,6 +42,8 @@ a
1
SELECT * FROM mysql.gtid_slave_pos ORDER BY sub_id;
domain_id sub_id server_id seq_no
+0 1 1 1
+0 2 1 2
0 3 1 3
0 4 1 4
SELECT * FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
@@ -121,6 +124,21 @@ Transactions_multi_engine 6
DELETE FROM t1 WHERE a >= 100;
DELETE FROM t2 WHERE a >= 100;
DELETE FROM t3 WHERE a >= 100;
+connection server_1;
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos;
+COUNT(*)>=10
+1
+SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
+UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select;
+COUNT(*)>=10
+1
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_rocksdb;
+COUNT(*)>=10
+1
+SET GLOBAL gtid_cleanup_batch_size = 3;
connection server_2;
include/stop_slave.inc
SET sql_log_bin=0;
diff --git a/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test b/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test
index e0d16e7f242..631d9ca533f 100644
--- a/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test
+++ b/storage/rocksdb/mysql-test/rocksdb_rpl/t/mdev12179.test
@@ -4,6 +4,12 @@
--connection server_2
--source include/stop_slave.inc
+
+# Set GTID cleanup limit high enough that cleanup will not run and we
+# can rely on consistent table output in .result.
+--let $old_gtid_cleanup_batch_size=`SELECT @@GLOBAL.gtid_cleanup_batch_size`
+SET GLOBAL gtid_cleanup_batch_size = 999999999;
+
CHANGE MASTER TO master_use_gtid=slave_pos;
SET sql_log_bin=0;
CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos;
@@ -89,6 +95,82 @@ DELETE FROM t2 WHERE a >= 100;
DELETE FROM t3 WHERE a >= 100;
+# Create a bunch more GTIDs in mysql.gtid_slave_pos* tables to test with.
+--connection server_1
+--disable_query_log
+let $i=10;
+while ($i) {
+ eval INSERT INTO t1 VALUES (300+$i);
+ eval INSERT INTO t2 VALUES (300+$i);
+ eval INSERT INTO t3 VALUES (300+$i);
+ dec $i;
+}
+--enable_query_log
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+# Check that we have many rows in mysql.gtid_slave_pos now (since
+# @@gtid_cleanup_batch_size was set to a huge value). No need to check
+# for an exact number, since that will require changing .result if
+# anything changes prior to this point, and we just need to know that
+# we have still have some data in the tables to make the following
+# test effective.
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos;
+SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
+ UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select;
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_rocksdb;
+
+# Check that old GTID rows will be deleted when batch delete size is
+# set reasonably. Old row deletion is not 100% deterministic (by design), so
+# we must wait for it to occur, but it should occur eventually.
+SET GLOBAL gtid_cleanup_batch_size = 3;
+let $i=40;
+--disable_query_log
+--let $keep_include_silent=1
+while ($i) {
+ let N=`SELECT 1+($i MOD 3)`;
+ --connection server_1
+ eval UPDATE t$N SET a=a+1 WHERE a=(SELECT MAX(a) FROM t$N);
+ --source include/save_master_gtid.inc
+ --connection server_2
+ --source include/sync_with_master_gtid.inc
+ let $j=50;
+ while ($j) {
+ let $is_done=`SELECT SUM(a)=1 FROM (
+ SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos
+ UNION ALL
+ SELECT COUNT(*) AS a FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
+ UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select
+ UNION ALL
+ SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos_rocksdb) outer_select`;
+ if ($is_done) {
+ let $j=0;
+ }
+ if (!$is_done) {
+ real_sleep 0.1;
+ dec $j;
+ }
+ }
+ dec $i;
+ if ($is_done) {
+ let $i=0;
+ }
+}
+--enable_query_log
+--let $keep_include_silent=0
+if (!$is_done) {
+ --echo Timed out waiting for mysql.gtid_slave_pos* tables to be cleaned up
+}
+
+--disable_query_log
+DELETE FROM t1 WHERE a >= 100;
+DELETE FROM t2 WHERE a >= 100;
+DELETE FROM t3 WHERE a >= 100;
+--enable_query_log
+
+
# Test status variables Rpl_transactions_multi_engine and Transactions_gtid_foreign_engine.
# Have mysql.gtid_slave_pos* for myisam and innodb but not rocksdb.
--connection server_2
@@ -223,6 +305,9 @@ SHOW STATUS LIKE "%transactions%engine";
SET sql_log_bin=0;
DROP TABLE mysql.gtid_slave_pos_innodb;
SET sql_log_bin=1;
+--disable_query_log
+eval SET GLOBAL gtid_cleanup_batch_size = $old_gtid_cleanup_batch_size;
+--enable_query_log
--connection server_1
DROP TABLE t1;
diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc
index 0d43d4da5c4..f0bc8a49761 100644
--- a/storage/rocksdb/rdb_datadic.cc
+++ b/storage/rocksdb/rdb_datadic.cc
@@ -266,8 +266,9 @@ int Rdb_key_field_iterator::next() {
bool covered_column = true;
if (m_covered_bitmap != nullptr &&
m_field->real_type() == MYSQL_TYPE_VARCHAR && !m_fpi->m_covered) {
+ uint tmp= m_curr_bitmap_pos++;
covered_column = m_curr_bitmap_pos < MAX_REF_PARTS &&
- bitmap_is_set(m_covered_bitmap, m_curr_bitmap_pos++);
+ bitmap_is_set(m_covered_bitmap, tmp);
}
if (m_fpi->m_unpack_func && covered_column) {
diff --git a/storage/sequence/mysql-test/sequence/simple.result b/storage/sequence/mysql-test/sequence/simple.result
index ea94e91b1ba..d921b80bf0f 100644
--- a/storage/sequence/mysql-test/sequence/simple.result
+++ b/storage/sequence/mysql-test/sequence/simple.result
@@ -124,9 +124,9 @@ Tables_in_test
explain select * from seq_1_to_15_step_2;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE seq_1_to_15_step_2 index NULL PRIMARY 8 NULL 8 Using index
-explain select * from seq_1_to_15_step_2 where seq > 4;
+explain select * from seq_1_to_15_step_2 where seq > 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE seq_1_to_15_step_2 range PRIMARY PRIMARY 8 NULL 6 Using where; Using index
+1 SIMPLE seq_1_to_15_step_2 range PRIMARY PRIMARY 8 NULL 3 Using where; Using index
explain select * from seq_1_to_15_step_2 where seq between 4 and 9;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE seq_1_to_15_step_2 range PRIMARY PRIMARY 8 NULL 3 Using where; Using index
diff --git a/storage/sequence/mysql-test/sequence/simple.test b/storage/sequence/mysql-test/sequence/simple.test
index fbf2b0ebc66..00d2464cf08 100644
--- a/storage/sequence/mysql-test/sequence/simple.test
+++ b/storage/sequence/mysql-test/sequence/simple.test
@@ -52,7 +52,7 @@ show open tables from test;
show tables;
# row estimates
explain select * from seq_1_to_15_step_2;
-explain select * from seq_1_to_15_step_2 where seq > 4;
+explain select * from seq_1_to_15_step_2 where seq > 10;
explain select * from seq_1_to_15_step_2 where seq between 4 and 9;
explain select * from seq_1_to_15_step_2 where seq between 20 and 30;
explain select * from seq_1_to_15_step_2 where seq between 4 and 6;
diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc
index 4092cfcb514..75558d333e0 100644
--- a/storage/sphinx/ha_sphinx.cc
+++ b/storage/sphinx/ha_sphinx.cc
@@ -2319,7 +2319,7 @@ int ha_sphinx::extra ( enum ha_extra_function op )
}
-int ha_sphinx::write_row ( byte * )
+int ha_sphinx::write_row ( const byte * )
{
SPH_ENTER_METHOD();
if ( !m_pShare || !m_pShare->m_bSphinxQL )
@@ -2749,7 +2749,9 @@ const Item * ha_sphinx::cond_push ( const Item *cond )
if ( !m_pShare->m_bSphinxQL )
{
// on non-QL tables, intercept query=value condition for SELECT
- if (!( args[0]->type()==Item::FIELD_ITEM && args[1]->type()==Item::STRING_ITEM ))
+ if (!( args[0]->type()==Item::FIELD_ITEM &&
+ args[1]->is_of_type(Item::CONST_ITEM,
+ STRING_RESULT)))
break;
Item_field * pField = (Item_field *) args[0];
@@ -2765,7 +2767,9 @@ const Item * ha_sphinx::cond_push ( const Item *cond )
} else
{
- if (!( args[0]->type()==Item::FIELD_ITEM && args[1]->type()==Item::INT_ITEM ))
+ if (!( args[0]->type()==Item::FIELD_ITEM &&
+ args[1]->is_of_type(Item::CONST_ITEM,
+ INT_RESULT)))
break;
// on QL tables, intercept id=value condition for DELETE
diff --git a/storage/sphinx/ha_sphinx.h b/storage/sphinx/ha_sphinx.h
index 8e6af908aab..decd88bad5a 100644
--- a/storage/sphinx/ha_sphinx.h
+++ b/storage/sphinx/ha_sphinx.h
@@ -85,7 +85,7 @@ public:
int open ( const char * name, int mode, uint test_if_locked );
int close ();
- int write_row ( byte * buf );
+ int write_row ( const byte * buf );
int update_row ( const byte * old_data, const byte * new_data );
int delete_row ( const byte * buf );
int extra ( enum ha_extra_function op );
diff --git a/storage/spider/ha_spider.cc b/storage/spider/ha_spider.cc
index 967d2c6e5de..d2d0ddf376f 100644
--- a/storage/spider/ha_spider.cc
+++ b/storage/spider/ha_spider.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -116,7 +117,7 @@ ha_spider::ha_spider(
use_fields = FALSE;
#endif
use_pre_call = FALSE;
- use_pre_records = FALSE;
+ use_pre_action = FALSE;
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
do_direct_update = FALSE;
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -228,7 +229,7 @@ ha_spider::ha_spider(
use_fields = FALSE;
#endif
use_pre_call = FALSE;
- use_pre_records = FALSE;
+ use_pre_action = FALSE;
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS
do_direct_update = FALSE;
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -1805,7 +1806,7 @@ int ha_spider::reset()
high_priority = FALSE;
insert_delayed = FALSE;
use_pre_call = FALSE;
- use_pre_records = FALSE;
+ use_pre_action = FALSE;
pre_bitmap_checked = FALSE;
bulk_insert = FALSE;
clone_bitmap_init = FALSE;
@@ -8760,22 +8761,24 @@ int ha_spider::info(
}
if (flag & HA_STATUS_TIME)
- stats.update_time = (ulong) share->update_time;
+ stats.update_time = (ulong) share->stat.update_time;
if (flag & (HA_STATUS_CONST | HA_STATUS_VARIABLE))
{
- stats.max_data_file_length = share->max_data_file_length;
- stats.create_time = (ulong) share->create_time;
+ stats.max_data_file_length = share->stat.max_data_file_length;
+ stats.create_time = share->stat.create_time;
stats.block_size = spider_param_block_size(thd);
}
if (flag & HA_STATUS_VARIABLE)
{
- stats.data_file_length = share->data_file_length;
- stats.index_file_length = share->index_file_length;
- stats.records = share->records;
- stats.mean_rec_length = share->mean_rec_length;
- stats.check_time = (ulong) share->check_time;
+ stats.data_file_length = share->stat.data_file_length;
+ stats.index_file_length = share->stat.index_file_length;
+ stats.records = share->stat.records;
+ stats.mean_rec_length = share->stat.mean_rec_length;
+ stats.check_time = share->stat.check_time;
if (stats.records <= 1 /* && (flag & HA_STATUS_NO_LOCK) */ )
stats.records = 2;
+ stats.checksum = share->stat.checksum;
+ stats.checksum_null = share->stat.checksum_null;
}
if (flag & HA_STATUS_AUTO)
{
@@ -9014,7 +9017,7 @@ ha_rows ha_spider::records_in_range(
key_part_map tgt_key_part_map;
KEY_PART_INFO *key_part;
Field *field = NULL;
- double rows = (double) share->records;
+ double rows = (double) share->stat.records;
double weight, rate;
DBUG_PRINT("info",("spider rows1=%f", rows));
if (start_key)
@@ -9323,11 +9326,12 @@ int ha_spider::pre_records()
result_list.casual_read[search_link_idx] =
spider_param_casual_read(thd, share->casual_read);
}
- if ((error_num = spider_db_show_records(this, search_link_idx, TRUE)))
+ if ((error_num = spider_db_simple_action(SPIDER_SIMPLE_RECORDS, this,
+ search_link_idx, TRUE)))
{
DBUG_RETURN(check_error_mode(error_num));
}
- use_pre_records = TRUE;
+ use_pre_action = TRUE;
DBUG_RETURN(0);
}
@@ -9339,14 +9343,14 @@ ha_rows ha_spider::records()
DBUG_PRINT("info",("spider this=%p", this));
if (sql_command == SQLCOM_ALTER_TABLE)
{
- use_pre_records = FALSE;
+ use_pre_action = FALSE;
DBUG_RETURN(0);
}
if (!(share->additional_table_flags & HA_HAS_RECORDS) && !this->result_list.direct_limit_offset)
{
DBUG_RETURN(handler::records());
}
- if (!use_pre_records && !this->result_list.direct_limit_offset)
+ if (!use_pre_action && !this->result_list.direct_limit_offset)
{
THD *thd = trx->thd;
if (
@@ -9357,17 +9361,84 @@ ha_rows ha_spider::records()
spider_param_casual_read(thd, share->casual_read);
}
}
- if ((error_num = spider_db_show_records(this, search_link_idx, FALSE)))
+ if ((error_num = spider_db_simple_action(SPIDER_SIMPLE_RECORDS, this,
+ search_link_idx, FALSE)))
{
- use_pre_records = FALSE;
+ use_pre_action = FALSE;
check_error_mode(error_num);
DBUG_RETURN(HA_POS_ERROR);
}
- use_pre_records = FALSE;
- share->records = table_rows;
+ use_pre_action = FALSE;
+ share->stat.records = table_rows;
DBUG_RETURN(table_rows);
}
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+int ha_spider::pre_calculate_checksum()
+{
+ int error_num;
+ backup_error_status();
+ DBUG_ENTER("ha_spider::pre_calculate_checksum");
+ DBUG_PRINT("info",("spider this=%p", this));
+ THD *thd = trx->thd;
+ if (
+ spider_param_sync_autocommit(thd) &&
+ (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
+ ) {
+ result_list.casual_read[search_link_idx] =
+ spider_param_casual_read(thd, share->casual_read);
+ }
+ action_flags = T_EXTEND;
+ if ((error_num = spider_db_simple_action(SPIDER_SIMPLE_CHECKSUM_TABLE, this,
+ search_link_idx, TRUE)))
+ {
+ DBUG_RETURN(check_error_mode(error_num));
+ }
+ use_pre_action = TRUE;
+ DBUG_RETURN(0);
+}
+
+int ha_spider::calculate_checksum()
+{
+ int error_num;
+ backup_error_status();
+ DBUG_ENTER("ha_spider::calculate_checksum");
+ DBUG_PRINT("info",("spider this=%p", this));
+ if (!use_pre_action && !this->result_list.direct_limit_offset)
+ {
+ THD *thd = trx->thd;
+ if (
+ spider_param_sync_autocommit(thd) &&
+ (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
+ ) {
+ result_list.casual_read[search_link_idx] =
+ spider_param_casual_read(thd, share->casual_read);
+ }
+ }
+ action_flags = T_EXTEND;
+ if ((error_num = spider_db_simple_action(SPIDER_SIMPLE_CHECKSUM_TABLE, this,
+ search_link_idx, FALSE)))
+ {
+ use_pre_action = FALSE;
+ DBUG_RETURN(check_error_mode(error_num));
+ }
+ use_pre_action = FALSE;
+ if (checksum_null)
+ {
+ share->stat.checksum_null = TRUE;
+ share->stat.checksum = 0;
+ stats.checksum_null = TRUE;
+ stats.checksum = 0;
+ } else {
+ share->stat.checksum_null = FALSE;
+ share->stat.checksum = (ha_checksum) checksum_val;
+ stats.checksum_null = FALSE;
+ stats.checksum = (ha_checksum) checksum_val;
+ }
+ DBUG_RETURN(0);
+}
+#endif
+
const char *ha_spider::table_type() const
{
DBUG_ENTER("ha_spider::table_type");
@@ -9397,8 +9468,8 @@ ulonglong ha_spider::table_flags() const
HA_BINLOG_ROW_CAPABLE |
HA_BINLOG_STMT_CAPABLE |
HA_PARTIAL_COLUMN_READ |
-#ifdef HA_CMP_REF_IS_EXPENSIVE
- HA_CMP_REF_IS_EXPENSIVE |
+#ifdef HA_SLOW_CMP_REF
+ HA_SLOW_CMP_REF |
#endif
#ifdef SPIDER_ENGINE_CONDITION_PUSHDOWN_IS_ALWAYS_ON
HA_CAN_TABLE_CONDITION_PUSHDOWN |
@@ -9428,7 +9499,7 @@ ulonglong ha_spider::table_flags() const
const char *ha_spider::index_type(
uint key_number
) {
- KEY *key_info = &table->s->key_info[key_number];
+ KEY *key_info = &table->key_info[key_number];
DBUG_ENTER("ha_spider::index_type");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_PRINT("info",("spider flags=%ld", key_info->flags));
@@ -9707,6 +9778,7 @@ void ha_spider::start_bulk_insert(
bulk_insert = TRUE;
bulk_size = -1;
store_last_insert_id = 0;
+ bzero(&copy_info, sizeof(copy_info));
DBUG_VOID_RETURN;
}
@@ -9719,13 +9791,13 @@ int ha_spider::end_bulk_insert()
bulk_insert = FALSE;
if (bulk_size == -1)
DBUG_RETURN(0);
- if ((error_num = spider_db_bulk_insert(this, table, TRUE)))
+ if ((error_num = spider_db_bulk_insert(this, table, &copy_info, TRUE)))
DBUG_RETURN(check_error_mode(error_num));
DBUG_RETURN(0);
}
int ha_spider::write_row(
- uchar *buf
+ const uchar *buf
) {
int error_num;
THD *thd = ha_thd();
@@ -9853,7 +9925,7 @@ int ha_spider::write_row(
else
bulk_size = 0;
}
- if ((error_num = spider_db_bulk_insert(this, table, FALSE)))
+ if ((error_num = spider_db_bulk_insert(this, table, &copy_info, FALSE)))
DBUG_RETURN(check_error_mode(error_num));
#ifdef HA_CAN_BULK_ACCESS
@@ -10478,7 +10550,8 @@ int ha_spider::direct_update_rows(
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num;
THD *thd = ha_thd();
@@ -10505,17 +10578,17 @@ int ha_spider::direct_update_rows(
if (is_bulk_access_clone)
{
bulk_access_pre_called = FALSE;
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
DBUG_RETURN(bulk_access_link_exec_tgt->spider->ha_direct_update_rows(
- ranges, range_count, sorted, new_data, update_rows));
+ ranges, range_count, sorted, new_data, update_rows, found_rows));
}
#endif
if (
(active_index != MAX_KEY && (error_num = index_handler_init())) ||
(active_index == MAX_KEY && (error_num = rnd_handler_init())) ||
(error_num = spider_db_direct_update(this, table, ranges, range_count,
- update_rows))
+ update_rows, found_rows))
)
DBUG_RETURN(check_error_mode(error_num));
@@ -10523,14 +10596,15 @@ int ha_spider::direct_update_rows(
if (bulk_access_executing && is_bulk_access_clone)
{
bulk_req_exec();
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
#endif
DBUG_RETURN(0);
}
#else
int ha_spider::direct_update_rows(
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num;
THD *thd = ha_thd();
@@ -10557,16 +10631,16 @@ int ha_spider::direct_update_rows(
if (is_bulk_access_clone)
{
bulk_access_pre_called = FALSE;
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
DBUG_RETURN(bulk_access_link_exec_tgt->spider->ha_direct_update_rows(
- update_rows));
+ update_rows, found_rows));
}
#endif
if (
(active_index != MAX_KEY && (error_num = index_handler_init())) ||
(active_index == MAX_KEY && (error_num = rnd_handler_init())) ||
- (error_num = spider_db_direct_update(this, table, update_rows))
+ (error_num = spider_db_direct_update(this, table, update_rows, found_rows))
)
DBUG_RETURN(check_error_mode(error_num));
@@ -10574,7 +10648,7 @@ int ha_spider::direct_update_rows(
if (bulk_access_executing && is_bulk_access_clone)
{
bulk_req_exec();
- DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows));
+ DBUG_RETURN(spider_db_bulk_direct_update(this, update_rows, found_rows));
}
#endif
DBUG_RETURN(0);
@@ -10588,21 +10662,23 @@ int ha_spider::pre_direct_update_rows(
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
DBUG_ENTER("ha_spider::pre_direct_update_rows");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_RETURN(bulk_access_link_current->spider->ha_direct_update_rows(ranges,
- range_count, sorted, new_data, update_rows));
+ range_count, sorted, new_data, update_rows, found_rows));
}
#else
int ha_spider::pre_direct_update_rows()
{
uint update_rows;
+ uint found_rows;
DBUG_ENTER("ha_spider::pre_direct_update_rows");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_RETURN(bulk_access_link_current->spider->ha_direct_update_rows(
- &update_rows));
+ &update_rows, &found_rows));
}
#endif
#endif
@@ -11172,8 +11248,9 @@ double ha_spider::scan_time()
DBUG_ENTER("ha_spider::scan_time");
DBUG_PRINT("info",("spider this=%p", this));
DBUG_PRINT("info",("spider scan_time = %.6f",
- share->scan_rate * share->records * share->mean_rec_length + 2));
- DBUG_RETURN(share->scan_rate * share->records * share->mean_rec_length + 2);
+ share->scan_rate * share->stat.records * share->stat.mean_rec_length + 2));
+ DBUG_RETURN(share->scan_rate * share->stat.records *
+ share->stat.mean_rec_length + 2);
}
double ha_spider::read_time(
@@ -11186,14 +11263,14 @@ double ha_spider::read_time(
if (keyread)
{
DBUG_PRINT("info",("spider read_time(keyread) = %.6f",
- share->read_rate * table->s->key_info[index].key_length *
+ share->read_rate * table->key_info[index].key_length *
rows / 2 + 2));
- DBUG_RETURN(share->read_rate * table->s->key_info[index].key_length *
+ DBUG_RETURN(share->read_rate * table->key_info[index].key_length *
rows / 2 + 2);
} else {
DBUG_PRINT("info",("spider read_time = %.6f",
- share->read_rate * share->mean_rec_length * rows + 2));
- DBUG_RETURN(share->read_rate * share->mean_rec_length * rows + 2);
+ share->read_rate * share->stat.mean_rec_length * rows + 2));
+ DBUG_RETURN(share->read_rate * share->stat.mean_rec_length * rows + 2);
}
}
diff --git a/storage/spider/ha_spider.h b/storage/spider/ha_spider.h
index 9ffe49754e8..edd7b8c881f 100644
--- a/storage/spider/ha_spider.h
+++ b/storage/spider/ha_spider.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -170,7 +171,7 @@ public:
bool high_priority;
bool insert_delayed;
bool use_pre_call;
- bool use_pre_records;
+ bool use_pre_action;
bool pre_bitmap_checked;
enum thr_lock_type lock_type;
int lock_mode;
@@ -243,6 +244,11 @@ public:
SPIDER_ITEM_HLD *direct_aggregate_item_current;
#endif
ha_rows table_rows;
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ ha_checksum checksum_val;
+ bool checksum_null;
+ uint action_flags;
+#endif
/* for fulltext search */
bool ft_init_and_first;
@@ -512,6 +518,10 @@ public:
int check_crd();
int pre_records();
ha_rows records();
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ int pre_calculate_checksum();
+ int calculate_checksum();
+#endif
const char *table_type() const;
ulonglong table_flags() const;
const char *index_type(
@@ -558,7 +568,7 @@ public:
#endif
int end_bulk_insert();
int write_row(
- uchar *buf
+ const uchar *buf
);
#ifdef HA_CAN_BULK_ACCESS
int pre_write_row(
@@ -675,20 +685,22 @@ public:
#endif
#endif
#ifdef HANDLER_HAS_DIRECT_UPDATE_ROWS_WITH_HS
- inline int direct_update_rows(ha_rows *update_rows)
+ inline int direct_update_rows(ha_rows *update_rows, ha_rows *found_rows)
{
- return direct_update_rows(NULL, 0, FALSE, NULL, update_rows);
+ return direct_update_rows(NULL, 0, FALSE, NULL, update_rows, found_rows);
}
int direct_update_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_row
);
#else
int direct_update_rows(
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_row
);
#endif
#ifdef HA_CAN_BULK_ACCESS
@@ -696,15 +708,18 @@ public:
inline int pre_direct_update_rows()
{
ha_rows update_rows;
+ ha_rows found_rows;
- return pre_direct_update_rows(NULL, 0, FALSE, NULL, &update_rows);
+ return pre_direct_update_rows(NULL, 0, FALSE, NULL, &update_rows,
+ &found_rows);
}
int pre_direct_update_rows(
KEY_MULTI_RANGE *ranges,
uint range_count,
bool sorted,
uchar *new_data,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_row
);
#else
int pre_direct_update_rows();
diff --git a/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc b/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc
index bf2d9163b9a..123410380ab 100644
--- a/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc
+++ b/storage/spider/mysql-test/spider/bugfix/include/checksum_table_with_quick_mode_3_init.inc
@@ -21,7 +21,7 @@ let $CHILD2_1_CREATE_TABLES=
let $CHILD2_1_SELECT_TABLES=
SELECT pkey FROM tbl_a ORDER BY pkey;
let $CHILD2_1_SELECT_ARGUMENT1=
- SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
--connection master_1
set @old_spider_quick_mode= @@spider_quick_mode;
set session spider_quick_mode= 3;
diff --git a/storage/spider/mysql-test/spider/bugfix/include/cp932_column_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/cp932_column_deinit.inc
new file mode 100644
index 00000000000..930cde889a4
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/cp932_column_deinit.inc
@@ -0,0 +1,13 @@
+--connection master_1
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/cp932_column_init.inc b/storage/spider/mysql-test/spider/bugfix/include/cp932_column_init.inc
new file mode 100644
index 00000000000..ba412b567f8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/cp932_column_init.inc
@@ -0,0 +1,29 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ txt_utf8 char(8) NOT NULL,
+ txt_cp932 char(8) NOT NULL COLLATE cp932_japanese_ci,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE DEFAULT CHARACTER SET utf8;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, txt_utf8, txt_cp932 FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%update %';
+--connection master_1
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
diff --git a/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_deinit.inc
new file mode 100644
index 00000000000..4ea789feae8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_deinit.inc
@@ -0,0 +1,13 @@
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--connection master_1
+set session binlog_format= @old_binlog_format;
+--connection slave1_1
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../include/deinit_spider.inc
+--source ../t/slave_test_deinit.inc
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_init.inc b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_init.inc
new file mode 100644
index 00000000000..f2f8635f9e3
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_init.inc
@@ -0,0 +1,24 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--source ../t/slave_test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, f FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%delete %';
+--connection slave1_1
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../include/init_spider.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--connection master_1
+set @old_binlog_format= @@binlog_format;
+set session binlog_format= 'ROW';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_deinit.inc
new file mode 100644
index 00000000000..4fd217a5676
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_deinit.inc
@@ -0,0 +1,4 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--source delete_with_float_column_deinit.inc
diff --git a/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_init.inc b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_init.inc
new file mode 100644
index 00000000000..9d3961491e6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mariadb_init.inc
@@ -0,0 +1,14 @@
+--source delete_with_float_column_init.inc
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1", wrapper "mariadb"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ f float DEFAULT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
diff --git a/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_deinit.inc
new file mode 100644
index 00000000000..4fd217a5676
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_deinit.inc
@@ -0,0 +1,4 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--source delete_with_float_column_deinit.inc
diff --git a/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_init.inc b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_init.inc
new file mode 100644
index 00000000000..d98f3c12397
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/delete_with_float_column_mysql_init.inc
@@ -0,0 +1,16 @@
+--source delete_with_float_column_init.inc
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1", wrapper "mysql"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a $STR_SEMICOLON
+ DROP FUNCTION to_float;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ f float DEFAULT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET $STR_SEMICOLON
+ CREATE FUNCTION to_float(a decimal(20,6)) RETURNS float RETURN cast(a as double);
diff --git a/storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_deinit.inc
new file mode 100644
index 00000000000..9d255152dd8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_deinit.inc
@@ -0,0 +1,14 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP
+--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP
+--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_init.inc b/storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_init.inc
new file mode 100644
index 00000000000..ac60580f463
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/group_by_order_by_limit_init.inc
@@ -0,0 +1,54 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+if (!$HAVE_PARTITION)
+{
+ --source group_by_order_by_limit_deinit.inc
+ --enable_result_log
+ --enable_query_log
+ --enable_warnings
+ skip Test requires partitioning;
+}
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a"'
+ PARTITION BY KEY(pkey) (
+ PARTITION pt1 COMMENT='srv "s_2_1"',
+ PARTITION pt2 COMMENT='srv "s_2_2"'
+ );
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ PRIMARY KEY (pkey),
+ KEY idx1 (skey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES
+let $CHILD2_2_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES
+let $CHILD2_2_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ PRIMARY KEY (pkey),
+ KEY idx1 (skey)
+ ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
+--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES
+let $CHILD2_2_SELECT_TABLES=
+ SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+let $CHILD2_2_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/mdev_19866_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/mdev_19866_deinit.inc
new file mode 100644
index 00000000000..9d255152dd8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/mdev_19866_deinit.inc
@@ -0,0 +1,14 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP
+--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP
+--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/mdev_19866_init.inc b/storage/spider/mysql-test/spider/bugfix/include/mdev_19866_init.inc
new file mode 100644
index 00000000000..dceae8226b0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/mdev_19866_init.inc
@@ -0,0 +1,52 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+if (!$HAVE_PARTITION)
+{
+ --source group_by_order_by_limit_deinit.inc
+ --enable_result_log
+ --enable_query_log
+ --enable_warnings
+ skip Test requires partitioning;
+}
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a"'
+ PARTITION BY KEY(pkey) (
+ PARTITION pt1 COMMENT='srv "s_2_1"',
+ PARTITION pt2 COMMENT='srv "s_2_2"'
+ );
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val char(1) NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, val FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES
+let $CHILD2_2_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES
+let $CHILD2_2_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val char(1) NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
+--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES
+let $CHILD2_2_SELECT_TABLES=
+ SELECT pkey, val FROM tbl_a ORDER BY pkey;
+let $CHILD2_2_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc
new file mode 100644
index 00000000000..76b7582abfe
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_deinit.inc
@@ -0,0 +1,11 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc
new file mode 100644
index 00000000000..da6778de504
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_insert_init.inc
@@ -0,0 +1,27 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ PRIMARY KEY (skey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+--let $MASTER_1_SET_COMMAND=set session spider_direct_dup_insert=1 $STR_SEMICOLON
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc
new file mode 100644
index 00000000000..76b7582abfe
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_deinit.inc
@@ -0,0 +1,11 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc
new file mode 100644
index 00000000000..884ef74c47e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/return_found_rows_update_init.inc
@@ -0,0 +1,26 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ KEY idx1 (skey,dt)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%update %';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/same_server_link_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/same_server_link_deinit.inc
new file mode 100644
index 00000000000..a4e8a10db19
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/same_server_link_deinit.inc
@@ -0,0 +1,11 @@
+--connection master_1
+set global spider_same_server_link= @old_global_spider_same_server_link;
+set session spider_same_server_link= @old_session_spider_same_server_link;
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/same_server_link_init.inc b/storage/spider/mysql-test/spider/bugfix/include/same_server_link_init.inc
new file mode 100644
index 00000000000..2c8150c905d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/same_server_link_init.inc
@@ -0,0 +1,15 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_b", host "127.0.0.1", port "$MASTER_1_MYPORT", user "root"';
+--connection master_1
+set @old_global_spider_same_server_link= @@global.spider_same_server_link;
+set @old_session_spider_same_server_link= @@session.spider_same_server_link;
+set global spider_same_server_link= 0;
+set session spider_same_server_link= 0;
diff --git a/storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_deinit.inc
new file mode 100644
index 00000000000..76b7582abfe
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_deinit.inc
@@ -0,0 +1,11 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_init.inc b/storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_init.inc
new file mode 100644
index 00000000000..37bf690c066
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/select_with_backquote_init.inc
@@ -0,0 +1,25 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ txt_utf8 char(8) NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE DEFAULT CHARACTER SET utf8;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, txt_utf8 FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_deinit.inc
new file mode 100644
index 00000000000..5ac67cdf783
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_deinit.inc
@@ -0,0 +1,10 @@
+--connection slave1_1
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../include/deinit_spider.inc
+--source ../t/slave_test_deinit.inc
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_init.inc b/storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_init.inc
new file mode 100644
index 00000000000..052d6ebb2eb
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/slave_transaction_retry_errors_5digit_init.inc
@@ -0,0 +1,10 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--source ../t/slave_test_init.inc
+--connection slave1_1
+--source ../include/init_spider.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc
new file mode 100644
index 00000000000..01645e85f32
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_deinit.inc
@@ -0,0 +1,12 @@
+--connection master_1
+alter table mysql.spider_table_sts add column checksum bigint unsigned default null after update_time;
+DROP DATABASE IF EXISTS auto_test_local;
+
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc b/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc
new file mode 100644
index 00000000000..1e438812af7
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/spider_table_sts_init.inc
@@ -0,0 +1,13 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", host "127.0.0.1", port "$MASTER_1_MYPORT", user "root"';
+--connection master_1
+alter table mysql.spider_table_sts drop column checksum;
+insert into mysql.spider_table_sts values ('auto_test_local', 'tbl_a', 0, 0, 0, 0, 0, '2019-01-01 00:00:00', '2019-01-01 00:00:00', '2019-01-01 00:00:00');
diff --git a/storage/spider/mysql-test/spider/bugfix/include/sql_mode_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_deinit.inc
new file mode 100644
index 00000000000..07f4d39a184
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_deinit.inc
@@ -0,0 +1,13 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--connection master_1
+set session sql_mode= @old_sql_mode;
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/sql_mode_init.inc b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_init.inc
new file mode 100644
index 00000000000..65e2f9102e7
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_init.inc
@@ -0,0 +1,40 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $SQL_MODES= real_as_float,pipes_as_concat,ansi_quotes,ignore_space,ignore_bad_table_options,only_full_group_by,no_unsigned_subtraction,no_dir_in_create,postgresql,oracle,mssql,db2,maxdb,no_key_options,no_table_options,no_field_options,mysql323,mysql40,ansi,no_auto_value_on_zero,no_backslash_escapes,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,traditional,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length
+if (`SELECT IF(STRCMP('$SERVER_NAME', 'MariaDB') = 0, 1, 0)`)
+{
+ if (`SELECT IF($SERVER_MAJOR_VERSION = 10, 1, 0)`)
+ {
+ if (`SELECT IF($SERVER_MINOR_VERSION >= 3, 1, 0)`)
+ {
+ --let $SQL_MODES= $SQL_MODES,empty_string_is_null,simultaneous_assignment
+ }
+ if (`SELECT IF($SERVER_MINOR_VERSION >= 4, 1, 0)`)
+ {
+ --let $SQL_MODES= $SQL_MODES,time_round_fractional
+ }
+ }
+}
+--connection master_1
+set @old_sql_mode= @@sql_mode;
+eval set session sql_mode= '$SQL_MODES';
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_deinit.inc
new file mode 100644
index 00000000000..0dbff811c95
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_deinit.inc
@@ -0,0 +1 @@
+--source sql_mode_deinit.inc
diff --git a/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_init.inc b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_init.inc
new file mode 100644
index 00000000000..8e03b94b160
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mariadb_init.inc
@@ -0,0 +1,3 @@
+--source sql_mode_init.inc
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1", wrapper "mariadb"';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_deinit.inc
new file mode 100644
index 00000000000..0dbff811c95
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_deinit.inc
@@ -0,0 +1 @@
+--source sql_mode_deinit.inc
diff --git a/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_init.inc b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_init.inc
new file mode 100644
index 00000000000..2cdd56bc689
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/sql_mode_mysql_init.inc
@@ -0,0 +1,3 @@
+--source sql_mode_init.inc
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1", wrapper "mysql"';
diff --git a/storage/spider/mysql-test/spider/bugfix/include/wait_timeout_deinit.inc b/storage/spider/mysql-test/spider/bugfix/include/wait_timeout_deinit.inc
new file mode 100644
index 00000000000..e66247c89c5
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/wait_timeout_deinit.inc
@@ -0,0 +1,18 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP
+--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP
+--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP
+--connection child2_1
+set global wait_timeout= @old_wait_timeout;
+--connection child2_2
+set global wait_timeout= @old_wait_timeout;
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/include/wait_timeout_init.inc b/storage/spider/mysql-test/spider/bugfix/include/wait_timeout_init.inc
new file mode 100644
index 00000000000..d56d7a20940
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/include/wait_timeout_init.inc
@@ -0,0 +1,56 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+if (!$HAVE_PARTITION)
+{
+ --source wait_timeout_deinit.inc
+ --enable_result_log
+ --enable_query_log
+ --enable_warnings
+ skip Test requires partitioning;
+}
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a"'
+ PARTITION BY KEY(pkey) (
+ PARTITION pt1 COMMENT='srv "s_2_1"',
+ PARTITION pt2 COMMENT='srv "s_2_2"'
+ );
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %';
+--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES
+let $CHILD2_2_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES
+let $CHILD2_2_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
+--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES
+let $CHILD2_2_SELECT_TABLES=
+ SELECT pkey FROM tbl_a ORDER BY pkey;
+let $CHILD2_2_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %';
+--connection child2_1
+set @old_wait_timeout= @@wait_timeout;
+set global wait_timeout= 1;
+--connection child2_2
+set @old_wait_timeout= @@wait_timeout;
+set global wait_timeout= 1;
diff --git a/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result b/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result
index eae4895411e..bd423d934f5 100644
--- a/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result
+++ b/storage/spider/mysql-test/spider/bugfix/r/checksum_table_with_quick_mode_3.result
@@ -44,10 +44,10 @@ CHECKSUM TABLE tbl_a EXTENDED;
Table Checksum
auto_test_local.tbl_a 1061386331
connection child2_1;
-SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
argument
-select `pkey` from `auto_test_remote`.`tbl_a`
-SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+checksum table `auto_test_remote`.`tbl_a` extended
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
0
diff --git a/storage/spider/mysql-test/spider/bugfix/r/cp932_column.result b/storage/spider/mysql-test/spider/bugfix/r/cp932_column.result
new file mode 100644
index 00000000000..30b333c5008
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/cp932_column.result
@@ -0,0 +1,84 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18992
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+txt_utf8 char(8) NOT NULL,
+txt_cp932 char(8) NOT NULL COLLATE cp932_japanese_ci,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE DEFAULT CHARACTER SET utf8 MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,txt_utf8,txt_cp932) VALUES (0,'',''),(1,'',''),(2,'',''),(3,'',''),(4,'',''),(5,'',''),(6,'',''),(7,'',''),(8,'',''),(9,'','');
+FLUSH TABLES;
+
+test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SET NAMES cp932;
+INSERT INTO tbl_a (pkey,txt_utf8,txt_cp932) VALUES (10,'','’†‘');
+INSERT INTO tbl_a (pkey,txt_utf8,txt_cp932) VALUES (0,'','') ON DUPLICATE KEY UPDATE txt_cp932 = '’†‘';
+UPDATE tbl_a SET txt_cp932 = '’†‘' WHERE pkey = 2;
+SET NAMES utf8;
+connection child2_1;
+SET NAMES cp932;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%update %';
+argument
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`txt_utf8`,`txt_cp932`)values(10,'',_cp932'\\x92\\x86\\x8D\\x91')
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`txt_utf8`,`txt_cp932`)values(0,'',_cp932'') on duplicate key update `txt_cp932` = _cp932'\x92\x86\x8D\x91'
+update `auto_test_remote`.`tbl_a` set `txt_cp932` = _cp932'\x92\x86\x8D\x91' where (`pkey` = 2)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%update %'
+SELECT pkey, txt_utf8, txt_cp932 FROM tbl_a ORDER BY pkey;
+pkey txt_utf8 txt_cp932
+0 ’†‘
+1
+2 ’†‘
+3
+4
+5
+6
+7
+8
+9
+10 ’†‘
+SET NAMES utf8;
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mariadb.result b/storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mariadb.result
new file mode 100644
index 00000000000..d9fb00a09fc
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mariadb.result
@@ -0,0 +1,85 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+for slave1_1
+connection slave1_1;
+connection master_1;
+set @old_binlog_format= @@binlog_format;
+set session binlog_format= 'ROW';
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection slave1_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+connection slave1_1;
+connection master_1;
+SET SESSION sql_log_bin= 0;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+f float DEFAULT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+SET SESSION sql_log_bin= 1;
+connection slave1_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+f float DEFAULT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+connection master_1;
+INSERT INTO tbl_a (pkey, f) VALUES (0,NULL);
+INSERT INTO tbl_a (pkey, f) VALUES (1,0.671437);
+DELETE FROM tbl_a WHERE pkey = 0;
+DELETE FROM tbl_a WHERE pkey = 1;
+connection slave1_1;
+connection master_1;
+SET SESSION sql_log_bin= 0;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%delete %';
+argument
+delete from `auto_test_remote`.`tbl_a` where `pkey` = 0 and `f` is null limit 1
+delete from `auto_test_remote`.`tbl_a` where `pkey` = 1 and `f` = cast(0.671437 as float) limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%delete %'
+SELECT pkey, f FROM tbl_a ORDER BY pkey;
+pkey f
+connection slave1_1;
+SELECT pkey, f FROM tbl_a ORDER BY pkey;
+pkey f
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection slave1_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session binlog_format= @old_binlog_format;
+connection slave1_1;
+for slave1_1
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mysql.result b/storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mysql.result
new file mode 100644
index 00000000000..9b11de7cff6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/delete_with_float_column_mysql.result
@@ -0,0 +1,85 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+for slave1_1
+connection slave1_1;
+connection master_1;
+set @old_binlog_format= @@binlog_format;
+set session binlog_format= 'ROW';
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection slave1_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+connection slave1_1;
+connection master_1;
+SET SESSION sql_log_bin= 0;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+f float DEFAULT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+SET SESSION sql_log_bin= 1;
+connection slave1_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+f float DEFAULT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+connection master_1;
+INSERT INTO tbl_a (pkey, f) VALUES (0,NULL);
+INSERT INTO tbl_a (pkey, f) VALUES (1,0.671437);
+DELETE FROM tbl_a WHERE pkey = 0;
+DELETE FROM tbl_a WHERE pkey = 1;
+connection slave1_1;
+connection master_1;
+SET SESSION sql_log_bin= 0;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%delete %';
+argument
+delete from `auto_test_remote`.`tbl_a` where `pkey` = 0 and `f` is null limit 1
+delete from `auto_test_remote`.`tbl_a` where `pkey` = 1 and `f` = /* create function to_float(a decimal(20,6)) returns float return a */ to_float(0.671437) limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%delete %'
+SELECT pkey, f FROM tbl_a ORDER BY pkey;
+pkey f
+connection slave1_1;
+SELECT pkey, f FROM tbl_a ORDER BY pkey;
+pkey f
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection slave1_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session binlog_format= @old_binlog_format;
+connection slave1_1;
+for slave1_1
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/group_by_order_by_limit.result b/storage/spider/mysql-test/spider/bugfix/r/group_by_order_by_limit.result
new file mode 100644
index 00000000000..8a2bcb73537
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/group_by_order_by_limit.result
@@ -0,0 +1,117 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-16520
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+skey int NOT NULL,
+PRIMARY KEY (pkey),
+KEY idx1 (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19);
+INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT skey, count(*) cnt FROM tbl_a GROUP BY skey ORDER BY cnt DESC, skey DESC LIMIT 5;
+skey cnt
+14 2
+13 2
+12 2
+11 2
+10 2
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select count(0),`skey` from `auto_test_remote`.`tbl_a` group by `skey` order by `skey`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+pkey skey
+1 1
+3 3
+5 5
+7 7
+9 9
+11 11
+13 13
+15 15
+17 17
+19 19
+21 6
+23 8
+25 10
+27 12
+29 14
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select count(0),`skey` from `auto_test_remote2`.`tbl_a` group by `skey` order by `skey`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+pkey skey
+0 0
+2 2
+4 4
+6 6
+8 8
+10 10
+12 12
+14 14
+16 16
+18 18
+20 5
+22 7
+24 9
+26 11
+28 13
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result b/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result
new file mode 100644
index 00000000000..5d483481edd
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/mdev_19866.result
@@ -0,0 +1,111 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-19866
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val char(1) NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (1,'1'),(2,'2'),(3,'3'),(4,'4');
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT * FROM tbl_a;
+pkey val
+1 1
+3 3
+2 2
+4 4
+SELECT * FROM tbl_a WHERE pkey = 1;
+pkey val
+1 1
+SELECT * FROM tbl_a;
+pkey val
+1 1
+3 3
+2 2
+4 4
+SELECT * FROM tbl_a WHERE pkey = 2;
+pkey val
+2 2
+SELECT * FROM tbl_a;
+pkey val
+1 1
+3 3
+2 2
+4 4
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `pkey`,`val` from `auto_test_remote`.`tbl_a`
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1
+select `pkey`,`val` from `auto_test_remote`.`tbl_a`
+select `pkey`,`val` from `auto_test_remote`.`tbl_a`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a`
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a`
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 2
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a`
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+2 2
+4 4
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result
new file mode 100644
index 00000000000..2ddec02ef81
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_insert.result
@@ -0,0 +1,179 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18973
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+skey int NOT NULL,
+dt date NOT NULL,
+tm time NOT NULL,
+PRIMARY KEY (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+FLUSH TABLES;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')" auto_test_local
+--------------
+set session spider_direct_dup_insert=1
+--------------
+
+Query OK, 0 rows affected
+
+--------------
+INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')
+--------------
+
+Query OK, 5 rows affected
+Records: 10 Duplicates: 5 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+argument
+insert ignore into `auto_test_remote`.`tbl_a`(`skey`,`dt`,`tm`)values(0,_latin1'2013-01-01',_latin1'13:00:00'),(2,_latin1'2013-02-01',_latin1'13:00:00'),(4,_latin1'2013-03-01',_latin1'13:00:00'),(7,_latin1'2013-04-01',_latin1'13:00:00'),(8,_latin1'2013-05-01',_latin1'13:00:00'),(10,_latin1'2013-06-01',_latin1'13:00:00'),(11,_latin1'2013-07-01',_latin1'13:00:00'),(12,_latin1'2013-08-01',_latin1'13:00:00'),(13,_latin1'2013-09-01',_latin1'13:00:00'),(14,_latin1'2013-10-01',_latin1'13:00:00')
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+1 2012-02-01 12:00:00
+2 2012-03-01 12:00:00
+3 2012-04-01 12:00:00
+4 2012-05-01 12:00:00
+5 2012-06-01 12:00:00
+6 2012-07-01 12:00:00
+7 2012-08-01 12:00:00
+8 2012-09-01 12:00:00
+9 2012-10-01 12:00:00
+10 2013-06-01 13:00:00
+11 2013-07-01 13:00:00
+12 2013-08-01 13:00:00
+13 2013-09-01 13:00:00
+14 2013-10-01 13:00:00
+TRUNCATE TABLE mysql.general_log;
+MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')" auto_test_local
+--------------
+set session spider_direct_dup_insert=1
+--------------
+
+Query OK, 0 rows affected
+
+--------------
+REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')
+--------------
+
+Query OK, 14 rows affected
+Records: 10 Duplicates: 4 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+argument
+replace into `auto_test_remote`.`tbl_a`(`skey`,`dt`,`tm`)values(1,_latin1'2012-02-01',_latin1'12:00:00'),(3,_latin1'2012-12-01',_latin1'11:00:00'),(8,_latin1'2012-11-30',_latin1'11:00:00'),(9,_latin1'2012-11-29',_latin1'11:00:00'),(10,_latin1'2012-11-28',_latin1'11:00:00'),(15,_latin1'2012-11-27',_latin1'11:00:00'),(16,_latin1'2012-11-26',_latin1'11:00:00'),(17,_latin1'2012-11-25',_latin1'11:00:00'),(18,_latin1'2012-11-24',_latin1'11:00:00'),(19,_latin1'2012-11-23',_latin1'11:00:00')
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+1 2012-02-01 12:00:00
+2 2012-03-01 12:00:00
+3 2012-12-01 11:00:00
+4 2012-05-01 12:00:00
+5 2012-06-01 12:00:00
+6 2012-07-01 12:00:00
+7 2012-08-01 12:00:00
+8 2012-11-30 11:00:00
+9 2012-11-29 11:00:00
+10 2012-11-28 11:00:00
+11 2013-07-01 13:00:00
+12 2013-08-01 13:00:00
+13 2013-09-01 13:00:00
+14 2013-10-01 13:00:00
+15 2012-11-27 11:00:00
+16 2012-11-26 11:00:00
+17 2012-11-25 11:00:00
+18 2012-11-24 11:00:00
+19 2012-11-23 11:00:00
+TRUNCATE TABLE mysql.general_log;
+MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)" auto_test_local
+--------------
+set session spider_direct_dup_insert=1
+--------------
+
+Query OK, 0 rows affected
+
+--------------
+INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)
+--------------
+
+Query OK, 13 rows affected
+Records: 10 Duplicates: 4 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`skey`,`dt`,`tm`)values(1,_latin1'2012-11-01',_latin1'11:00:00'),(3,_latin1'2012-12-01',_latin1'11:00:00'),(11,_latin1'2012-11-30',_latin1'11:00:00'),(15,_latin1'2012-11-29',_latin1'11:00:00'),(16,_latin1'2012-11-28',_latin1'11:00:00'),(20,_latin1'2012-11-27',_latin1'11:00:00'),(21,_latin1'2012-11-26',_latin1'11:00:00'),(22,_latin1'2012-11-25',_latin1'11:00:00'),(23,_latin1'2012-11-24',_latin1'11:00:00'),(24,_latin1'2012-11-23',_latin1'11:00:00') on duplicate key update `dt` = values(`dt`),`tm` = values(`tm`)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %' OR argument LIKE '%replace %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+1 2012-11-01 11:00:00
+2 2012-03-01 12:00:00
+3 2012-12-01 11:00:00
+4 2012-05-01 12:00:00
+5 2012-06-01 12:00:00
+6 2012-07-01 12:00:00
+7 2012-08-01 12:00:00
+8 2012-11-30 11:00:00
+9 2012-11-29 11:00:00
+10 2012-11-28 11:00:00
+11 2012-11-30 11:00:00
+12 2013-08-01 13:00:00
+13 2013-09-01 13:00:00
+14 2013-10-01 13:00:00
+15 2012-11-29 11:00:00
+16 2012-11-28 11:00:00
+17 2012-11-25 11:00:00
+18 2012-11-24 11:00:00
+19 2012-11-23 11:00:00
+20 2012-11-27 11:00:00
+21 2012-11-26 11:00:00
+22 2012-11-25 11:00:00
+23 2012-11-24 11:00:00
+24 2012-11-23 11:00:00
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result
new file mode 100644
index 00000000000..cd5423ed272
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/return_found_rows_update.result
@@ -0,0 +1,99 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18973
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+skey int NOT NULL,
+dt date NOT NULL,
+tm time NOT NULL,
+KEY idx1 (skey,dt)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(1, '2013-02-01', '13:00:00'),(2, '2013-03-01', '13:00:00'),(3, '2013-04-01', '13:00:00'),(4, '2013-05-01', '13:00:00'),(5, '2013-06-01', '13:00:00'),(6, '2013-07-01', '13:00:00'),(7, '2013-08-01', '13:00:00'),(8, '2013-09-01', '13:00:00'),(9, '2013-10-01', '13:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-11-01', '11:00:00'),(1, '2012-12-01', '11:00:00'),(2, '2012-11-30', '11:00:00'),(3, '2012-11-29', '11:00:00'),(4, '2012-11-28', '11:00:00'),(5, '2012-11-27', '11:00:00'),(6, '2012-11-26', '11:00:00'),(7, '2012-11-25', '11:00:00'),(8, '2012-11-24', '11:00:00'),(9, '2012-11-23', '11:00:00');
+FLUSH TABLES;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0" auto_test_local
+--------------
+UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0
+--------------
+
+Query OK, 2 rows affected
+Rows matched: 3 Changed: 2 Warnings: 0
+
+Bye
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%update %';
+argument
+update `auto_test_remote`.`tbl_a` set `tm` = _latin1'12:00:00' where (`skey` = 0)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%update %'
+SELECT skey, dt, tm FROM tbl_a ORDER BY skey;
+skey dt tm
+0 2012-01-01 12:00:00
+0 2013-01-01 12:00:00
+0 2012-11-01 12:00:00
+1 2012-12-01 11:00:00
+1 2013-02-01 13:00:00
+1 2012-02-01 12:00:00
+2 2013-03-01 13:00:00
+2 2012-11-30 11:00:00
+2 2012-03-01 12:00:00
+3 2012-11-29 11:00:00
+3 2013-04-01 13:00:00
+3 2012-04-01 12:00:00
+4 2012-11-28 11:00:00
+4 2012-05-01 12:00:00
+4 2013-05-01 13:00:00
+5 2012-11-27 11:00:00
+5 2012-06-01 12:00:00
+5 2013-06-01 13:00:00
+6 2013-07-01 13:00:00
+6 2012-11-26 11:00:00
+6 2012-07-01 12:00:00
+7 2012-11-25 11:00:00
+7 2012-08-01 12:00:00
+7 2013-08-01 13:00:00
+8 2012-09-01 12:00:00
+8 2013-09-01 13:00:00
+8 2012-11-24 11:00:00
+9 2012-10-01 12:00:00
+9 2013-10-01 13:00:00
+9 2012-11-23 11:00:00
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/same_server_link.result b/storage/spider/mysql-test/spider/bugfix/r/same_server_link.result
new file mode 100644
index 00000000000..1f4177568a7
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/same_server_link.result
@@ -0,0 +1,42 @@
+for master_1
+for child2
+for child3
+connection master_1;
+set @old_global_spider_same_server_link= @@global.spider_same_server_link;
+set @old_session_spider_same_server_link= @@session.spider_same_server_link;
+set global spider_same_server_link= 0;
+set session spider_same_server_link= 0;
+
+this test is for MDEV-6268
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+create table
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+CREATE TABLE tbl_b (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+
+select test 1
+connection master_1;
+INSERT INTO tbl_a VALUES(1);
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection master_1;
+set global spider_same_server_link= @old_global_spider_same_server_link;
+set session spider_same_server_link= @old_session_spider_same_server_link;
+for master_1
+for child2
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result b/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result
new file mode 100644
index 00000000000..52f8c98bf98
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/select_with_backquote.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-17204
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+txt_utf8 char(8) NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE DEFAULT CHARACTER SET utf8 MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,txt_utf8) VALUES (0,'01234567'),(1,'12345678'),(2,'23456789'),(3,'34567890'),(4,'45678901'),(5,'56789012'),(6,'67890123'),(7,'78901234'),(8,'89012345'),(9,'90123456');
+FLUSH TABLES;
+
+test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SET NAMES utf8;
+SELECT `pkey`, LEFT(`txt_utf8`, 4) FROM `auto_test_local`.`tbl_a` ORDER BY LEFT(`txt_utf8`, 4) LIMIT 3;
+pkey LEFT(`txt_utf8`, 4)
+0 0123
+1 1234
+2 2345
+connection child2_1;
+SET NAMES utf8;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select t0.`pkey` `pkey`,(left(t0.`txt_utf8` , 4)) `LEFT(``txt_utf8``, 4)` from `auto_test_remote`.`tbl_a` t0 order by `LEFT(``txt_utf8``, 4)` limit 3
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, txt_utf8 FROM tbl_a ORDER BY pkey;
+pkey txt_utf8
+0 01234567
+1 12345678
+2 23456789
+3 34567890
+4 45678901
+5 56789012
+6 67890123
+7 78901234
+8 89012345
+9 90123456
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result b/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result
new file mode 100644
index 00000000000..f2cab6b0a95
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/slave_transaction_retry_errors_5digit.result
@@ -0,0 +1,22 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+for slave1_1
+
+connection slave1_1;
+SHOW VARIABLES LIKE 'slave_transaction_retry_errors';
+Variable_name Value
+slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1429,2013,12701,10000,20000,30000
+connection slave1_1;
+for slave1_1
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result
index 06581a604a2..d7a0c1044a7 100644
--- a/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result
+++ b/storage/spider/mysql-test/spider/bugfix/r/slave_trx_isolation.result
@@ -50,7 +50,7 @@ SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %';
argument
set session time_zone = '+00:00'
SET NAMES utf8
-set session transaction isolation level read committed;set session autocommit = 1;start transaction
+set session transaction isolation level read committed;set session autocommit = 1;set session wait_timeout = 604800;set session sql_mode = 'strict_trans_tables,error_for_division_by_zero,no_auto_create_user,no_engine_substitution';start transaction
SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
diff --git a/storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result b/storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result
new file mode 100644
index 00000000000..f915cc951b1
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/spider_table_sts.result
@@ -0,0 +1,38 @@
+for master_1
+for child2
+for child3
+connection master_1;
+alter table mysql.spider_table_sts drop column checksum;
+insert into mysql.spider_table_sts values ('auto_test_local', 'tbl_a', 0, 0, 0, 0, 0, '2019-01-01 00:00:00', '2019-01-01 00:00:00', '2019-01-01 00:00:00');
+
+this test is for MDEV-19842
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+create table
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+
+select test 1
+connection master_1;
+SELECT pkey FROM tbl_a;
+ERROR HY000: System table spider_table_sts is different version
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+ERROR HY000: System table spider_table_sts is different version
+connection master_1;
+alter table mysql.spider_table_sts add column checksum bigint unsigned default null after update_time;
+DROP DATABASE IF EXISTS auto_test_local;
+for master_1
+for child2
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result
new file mode 100644
index 00000000000..5048fbb423c
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mariadb.result
@@ -0,0 +1,83 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_sql_mode= @@sql_mode;
+set session sql_mode= 'real_as_float,pipes_as_concat,ansi_quotes,ignore_space,ignore_bad_table_options,only_full_group_by,no_unsigned_subtraction,no_dir_in_create,postgresql,oracle,mssql,db2,maxdb,no_key_options,no_table_options,no_field_options,mysql323,mysql40,ansi,no_auto_value_on_zero,no_backslash_escapes,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,traditional,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length,empty_string_is_null,simultaneous_assignment,time_round_fractional';
+
+this test is for MDEV-16508
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+select test
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT * FROM tbl_a ORDER BY pkey;
+pkey
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%';
+argument
+set session transaction isolation level repeatable read;set session autocommit = 1;set session sql_log_off = 0;set session wait_timeout = 604800;set session sql_mode = 'real_as_float,ignore_bad_table_options,no_unsigned_subtraction,no_dir_in_create,no_auto_value_on_zero,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length,empty_string_is_null,simultaneous_assignment,time_round_fractional';set session time_zone = '+00:00';start transaction
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%'
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session sql_mode= @old_sql_mode;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result
new file mode 100644
index 00000000000..08f9a6007aa
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/sql_mode_mysql.result
@@ -0,0 +1,83 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_sql_mode= @@sql_mode;
+set session sql_mode= 'real_as_float,pipes_as_concat,ansi_quotes,ignore_space,ignore_bad_table_options,only_full_group_by,no_unsigned_subtraction,no_dir_in_create,postgresql,oracle,mssql,db2,maxdb,no_key_options,no_table_options,no_field_options,mysql323,mysql40,ansi,no_auto_value_on_zero,no_backslash_escapes,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,traditional,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length,empty_string_is_null,simultaneous_assignment,time_round_fractional';
+
+this test is for MDEV-16508
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+select test
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT * FROM tbl_a ORDER BY pkey;
+pkey
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%';
+argument
+set session transaction isolation level repeatable read;set session autocommit = 1;set session sql_log_off = 0;set session wait_timeout = 604800;set session sql_mode = 'real_as_float,ignore_bad_table_options,no_unsigned_subtraction,no_dir_in_create,no_auto_value_on_zero,strict_trans_tables,strict_all_tables,no_zero_in_date,no_zero_date,allow_invalid_dates,error_for_division_by_zero,no_auto_create_user,high_not_precedence,no_engine_substitution,pad_char_to_full_length';set session time_zone = '+00:00';start transaction
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%sql_mode%'
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session sql_mode= @old_sql_mode;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/r/wait_timeout.result b/storage/spider/mysql-test/spider/bugfix/r/wait_timeout.result
new file mode 100644
index 00000000000..ec9534f7592
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/r/wait_timeout.result
@@ -0,0 +1,130 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection child2_1;
+set @old_wait_timeout= @@wait_timeout;
+set global wait_timeout= 1;
+connection child2_2;
+set @old_wait_timeout= @@wait_timeout;
+set global wait_timeout= 1;
+
+this test is for MDEV-16530
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_1_2;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+connection child2_2_2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19);
+INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a READ;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+INSERT INTO tbl_a SELECT pkey + 30 FROM tbl_a ORDER BY pkey;
+connection child2_1_2;
+SELECT SLEEP(2);
+SLEEP(2)
+0
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %';
+argument
+insert into `auto_test_remote`.`tbl_a`(`pkey`)values(31),(33),(35),(37),(39),(41),(43),(45),(47),(49),(51),(53),(55),(57),(59)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %'
+connection child2_2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %';
+argument
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%insert %'
+connection child2_1;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+connection child2_2;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
+20
+22
+24
+26
+28
+connection master_1;
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection child2_1;
+set global wait_timeout= @old_wait_timeout;
+connection child2_2;
+set global wait_timeout= @old_wait_timeout;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/cp932_column.cnf b/storage/spider/mysql-test/spider/bugfix/t/cp932_column.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/cp932_column.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/cp932_column.test b/storage/spider/mysql-test/spider/bugfix/t/cp932_column.test
new file mode 100644
index 00000000000..8bd0d40cb60
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/cp932_column.test
@@ -0,0 +1,80 @@
+--source ../include/cp932_column_init.inc
+--echo
+--echo this test is for MDEV-18992
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ txt_utf8 char(8) NOT NULL,
+ txt_cp932 char(8) NOT NULL COLLATE cp932_japanese_ci,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE DEFAULT CHARACTER SET utf8 MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ txt_utf8 char(8) NOT NULL,
+ txt_cp932 char(8) NOT NULL COLLATE cp932_japanese_ci,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE DEFAULT CHARACTER SET utf8 $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,txt_utf8,txt_cp932) VALUES (0,'',''),(1,'',''),(2,'',''),(3,'',''),(4,'',''),(5,'',''),(6,'',''),(7,'',''),(8,'',''),(9,'','');
+FLUSH TABLES;
+
+--echo
+--echo test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SET NAMES cp932;
+INSERT INTO tbl_a (pkey,txt_utf8,txt_cp932) VALUES (10,'','’†‘');
+INSERT INTO tbl_a (pkey,txt_utf8,txt_cp932) VALUES (0,'','') ON DUPLICATE KEY UPDATE txt_cp932 = '’†‘';
+UPDATE tbl_a SET txt_cp932 = '’†‘' WHERE pkey = 2;
+SET NAMES utf8;
+
+--connection child2_1
+SET NAMES cp932;
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+SET NAMES utf8;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/cp932_column_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column.inc b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column.inc
new file mode 100644
index 00000000000..794ebedf355
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column.inc
@@ -0,0 +1,98 @@
+--echo
+--echo drop and create databases
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection slave1_1
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+save_master_pos;
+
+--connection slave1_1
+sync_with_master;
+
+--connection master_1
+SET SESSION sql_log_bin= 0;
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ f float DEFAULT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ f float DEFAULT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE2 $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+SET SESSION sql_log_bin= 1;
+
+--connection slave1_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ f float DEFAULT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ f float DEFAULT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+
+--connection master_1
+INSERT INTO tbl_a (pkey, f) VALUES (0,NULL);
+INSERT INTO tbl_a (pkey, f) VALUES (1,0.671437);
+DELETE FROM tbl_a WHERE pkey = 0;
+DELETE FROM tbl_a WHERE pkey = 1;
+save_master_pos;
+
+--connection slave1_1
+sync_with_master;
+
+--connection master_1
+SET SESSION sql_log_bin= 0;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection slave1_1
+SELECT pkey, f FROM tbl_a ORDER BY pkey;
+
+--echo
+--echo deinit
+--disable_warnings
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection slave1_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.cnf b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.cnf
new file mode 100644
index 00000000000..45019d6c537
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_4_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.test b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.test
new file mode 100644
index 00000000000..ce1a09d6287
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mariadb.test
@@ -0,0 +1,5 @@
+--source ../include/delete_with_float_column_mariadb_init.inc
+--source delete_with_float_column.inc
+--source ../include/delete_with_float_column_mariadb_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.cnf b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.cnf
new file mode 100644
index 00000000000..45019d6c537
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_4_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.test b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.test
new file mode 100644
index 00000000000..c687f947a91
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/delete_with_float_column_mysql.test
@@ -0,0 +1,5 @@
+--source ../include/delete_with_float_column_mysql_init.inc
+--source delete_with_float_column.inc
+--source ../include/delete_with_float_column_mysql_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.cnf b/storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.cnf
new file mode 100644
index 00000000000..e0ffb99c38e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.test b/storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.test
new file mode 100644
index 00000000000..f1de6d5d25f
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/group_by_order_by_limit.test
@@ -0,0 +1,97 @@
+--source ../include/group_by_order_by_limit_init.inc
+--echo
+--echo this test is for MDEV-16520
+--echo
+--echo drop and create databases
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+--connection child2_2
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+--disable_query_log
+echo CHILD2_2_CREATE_TABLES;
+eval $CHILD2_2_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ PRIMARY KEY (pkey),
+ KEY idx1 (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ PRIMARY KEY (pkey),
+ KEY idx1 (skey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19);
+INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14);
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SELECT skey, count(*) cnt FROM tbl_a GROUP BY skey ORDER BY cnt DESC, skey DESC LIMIT 5;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection child2_2
+eval $CHILD2_2_SELECT_ARGUMENT1;
+eval $CHILD2_2_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--connection child2_2
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/group_by_order_by_limit_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_19866.cnf b/storage/spider/mysql-test/spider/bugfix/t/mdev_19866.cnf
new file mode 100644
index 00000000000..e0ffb99c38e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_19866.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/mdev_19866.test b/storage/spider/mysql-test/spider/bugfix/t/mdev_19866.test
new file mode 100644
index 00000000000..05b753ae8bb
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/mdev_19866.test
@@ -0,0 +1,97 @@
+--source ../include/mdev_19866_init.inc
+--echo
+--echo this test is for MDEV-19866
+--echo
+--echo drop and create databases
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+--connection child2_2
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+--disable_query_log
+echo CHILD2_2_CREATE_TABLES;
+eval $CHILD2_2_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val char(1) NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val char(1) NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,val) VALUES (1,'1'),(2,'2'),(3,'3'),(4,'4');
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SELECT * FROM tbl_a;
+SELECT * FROM tbl_a WHERE pkey = 1;
+SELECT * FROM tbl_a;
+SELECT * FROM tbl_a WHERE pkey = 2;
+SELECT * FROM tbl_a;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection child2_2
+eval $CHILD2_2_SELECT_ARGUMENT1;
+eval $CHILD2_2_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--connection child2_2
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/mdev_19866_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test
new file mode 100644
index 00000000000..2beb9d9d7e4
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_insert.test
@@ -0,0 +1,98 @@
+--source ../include/return_found_rows_insert_init.inc
+--echo
+--echo this test is for MDEV-18973
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ PRIMARY KEY (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ PRIMARY KEY (skey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+FLUSH TABLES;
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')" auto_test_local;
+exec $MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "$MASTER_1_SET_COMMAND INSERT IGNORE INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(2, '2013-02-01', '13:00:00'),(4, '2013-03-01', '13:00:00'),(7, '2013-04-01', '13:00:00'),(8, '2013-05-01', '13:00:00'),(10, '2013-06-01', '13:00:00'),(11, '2013-07-01', '13:00:00'),(12, '2013-08-01', '13:00:00'),(13, '2013-09-01', '13:00:00'),(14, '2013-10-01', '13:00:00')" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')" auto_test_local;
+exec $MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "$MASTER_1_SET_COMMAND REPLACE INTO tbl_a (skey, dt, tm) VALUES (1, '2012-02-01', '12:00:00'),(3, '2012-12-01', '11:00:00'),(8, '2012-11-30', '11:00:00'),(9, '2012-11-29', '11:00:00'),(10, '2012-11-28', '11:00:00'),(15, '2012-11-27', '11:00:00'),(16, '2012-11-26', '11:00:00'),(17, '2012-11-25', '11:00:00'),(18, '2012-11-24', '11:00:00'),(19, '2012-11-23', '11:00:00')" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "MASTER_1_SET_COMMAND INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)" auto_test_local;
+exec $MYSQL -v -v -u root -h localhost -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "$MASTER_1_SET_COMMAND INSERT INTO tbl_a (skey, dt, tm) VALUES (1, '2012-11-01', '11:00:00'),(3, '2012-12-01', '11:00:00'),(11, '2012-11-30', '11:00:00'),(15, '2012-11-29', '11:00:00'),(16, '2012-11-28', '11:00:00'),(20, '2012-11-27', '11:00:00'),(21, '2012-11-26', '11:00:00'),(22, '2012-11-25', '11:00:00'),(23, '2012-11-24', '11:00:00'),(24, '2012-11-23', '11:00:00') ON DUPLICATE KEY UPDATE dt=VALUE(dt), tm=VALUE(tm)" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/return_found_rows_insert_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test
new file mode 100644
index 00000000000..50d9f345dfb
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/return_found_rows_update.test
@@ -0,0 +1,78 @@
+--source ../include/return_found_rows_update_init.inc
+--echo
+--echo this test is for MDEV-18973
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ KEY idx1 (skey,dt)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ skey int NOT NULL,
+ dt date NOT NULL,
+ tm time NOT NULL,
+ KEY idx1 (skey,dt)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-01-01', '12:00:00'),(1, '2012-02-01', '12:00:00'),(2, '2012-03-01', '12:00:00'),(3, '2012-04-01', '12:00:00'),(4, '2012-05-01', '12:00:00'),(5, '2012-06-01', '12:00:00'),(6, '2012-07-01', '12:00:00'),(7, '2012-08-01', '12:00:00'),(8, '2012-09-01', '12:00:00'),(9, '2012-10-01', '12:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2013-01-01', '13:00:00'),(1, '2013-02-01', '13:00:00'),(2, '2013-03-01', '13:00:00'),(3, '2013-04-01', '13:00:00'),(4, '2013-05-01', '13:00:00'),(5, '2013-06-01', '13:00:00'),(6, '2013-07-01', '13:00:00'),(7, '2013-08-01', '13:00:00'),(8, '2013-09-01', '13:00:00'),(9, '2013-10-01', '13:00:00');
+INSERT INTO tbl_a (skey, dt, tm) VALUES (0, '2012-11-01', '11:00:00'),(1, '2012-12-01', '11:00:00'),(2, '2012-11-30', '11:00:00'),(3, '2012-11-29', '11:00:00'),(4, '2012-11-28', '11:00:00'),(5, '2012-11-27', '11:00:00'),(6, '2012-11-26', '11:00:00'),(7, '2012-11-25', '11:00:00'),(8, '2012-11-24', '11:00:00'),(9, '2012-11-23', '11:00:00');
+FLUSH TABLES;
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--disable_query_log
+echo MYSQL -v -v -u root -h localhost -P MASTER_1_MYPORT -S MASTER_1_MYSOCK -e "UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0" auto_test_local;
+exec $MYSQL -v -v -u root -h localhost --default-character-set=latin1 -P $MASTER_1_MYPORT -S $MASTER_1_MYSOCK -e "UPDATE tbl_a SET tm = '12:00:00' WHERE skey = 0" auto_test_local;
+--enable_query_log
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/return_found_rows_update_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/same_server_link.cnf b/storage/spider/mysql-test/spider/bugfix/t/same_server_link.cnf
new file mode 100644
index 00000000000..b0853e32654
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/same_server_link.cnf
@@ -0,0 +1,2 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/same_server_link.test b/storage/spider/mysql-test/spider/bugfix/t/same_server_link.test
new file mode 100644
index 00000000000..1468f00cd1c
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/same_server_link.test
@@ -0,0 +1,55 @@
+--source ../include/same_server_link_init.inc
+--echo
+--echo this test is for MDEV-6268
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+--enable_warnings
+
+--echo
+--echo create table
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+echo CREATE TABLE tbl_b (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE2 MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_b (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE2 $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+
+--echo
+--echo select test 1
+
+--connection master_1
+--disable_result_log
+--error 12720
+INSERT INTO tbl_a VALUES(1);
+--enable_result_log
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--enable_warnings
+--source ../include/same_server_link_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.cnf b/storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.test b/storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.test
new file mode 100644
index 00000000000..4c4d687cf89
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/select_with_backquote.test
@@ -0,0 +1,74 @@
+--source ../include/select_with_backquote_init.inc
+--echo
+--echo this test is for MDEV-17204
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ txt_utf8 char(8) NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE DEFAULT CHARACTER SET utf8 MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ txt_utf8 char(8) NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE DEFAULT CHARACTER SET utf8 $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,txt_utf8) VALUES (0,'01234567'),(1,'12345678'),(2,'23456789'),(3,'34567890'),(4,'45678901'),(5,'56789012'),(6,'67890123'),(7,'78901234'),(8,'89012345'),(9,'90123456');
+FLUSH TABLES;
+
+--echo
+--echo test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SET NAMES utf8;
+SELECT `pkey`, LEFT(`txt_utf8`, 4) FROM `auto_test_local`.`tbl_a` ORDER BY LEFT(`txt_utf8`, 4) LIMIT 3;
+
+--connection child2_1
+SET NAMES utf8;
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/select_with_backquote_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.cnf b/storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.cnf
new file mode 100644
index 00000000000..c861d27b01d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.cnf
@@ -0,0 +1,6 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_4_1.cnf
+[mysqld.4.1]
+slave_transaction_retry_errors="10000,20000,30000"
diff --git a/storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.test b/storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.test
new file mode 100644
index 00000000000..fc91a43eeb0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/slave_transaction_retry_errors_5digit.test
@@ -0,0 +1,9 @@
+--source ../include/slave_transaction_retry_errors_5digit_init.inc
+--echo
+
+--connection slave1_1
+SHOW VARIABLES LIKE 'slave_transaction_retry_errors';
+
+--source ../include/slave_transaction_retry_errors_5digit_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf b/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf
new file mode 100644
index 00000000000..b0853e32654
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.cnf
@@ -0,0 +1,2 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test b/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test
new file mode 100644
index 00000000000..7213017505b
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/spider_table_sts.test
@@ -0,0 +1,46 @@
+--source ../include/spider_table_sts_init.inc
+--echo
+--echo this test is for MDEV-19842
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+--enable_warnings
+
+--echo
+--echo create table
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+
+--echo
+--echo select test 1
+
+--connection master_1
+--error 12609
+SELECT pkey FROM tbl_a;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+--error 12609
+DROP DATABASE IF EXISTS auto_test_local;
+
+--enable_warnings
+--source ../include/spider_table_sts_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc b/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc
new file mode 100644
index 00000000000..ae7c15c5081
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/sql_mode.inc
@@ -0,0 +1,65 @@
+--echo
+--echo this test is for MDEV-16508
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+--echo
+--echo select test
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SELECT * FROM tbl_a ORDER BY pkey;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.cnf b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.test b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.test
new file mode 100644
index 00000000000..c63514d22f0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mariadb.test
@@ -0,0 +1,5 @@
+--source ../include/sql_mode_mariadb_init.inc
+--source sql_mode.inc
+--source ../include/sql_mode_mariadb_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.cnf b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.cnf
new file mode 100644
index 00000000000..05dfd8a0bce
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.test b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.test
new file mode 100644
index 00000000000..3a0f8d20da3
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/sql_mode_mysql.test
@@ -0,0 +1,5 @@
+--source ../include/sql_mode_mysql_init.inc
+--source sql_mode.inc
+--source ../include/sql_mode_mysql_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/bugfix/t/wait_timeout.cnf b/storage/spider/mysql-test/spider/bugfix/t/wait_timeout.cnf
new file mode 100644
index 00000000000..e0ffb99c38e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/wait_timeout.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/bugfix/t/wait_timeout.test b/storage/spider/mysql-test/spider/bugfix/t/wait_timeout.test
new file mode 100644
index 00000000000..8da6e8fe314
--- /dev/null
+++ b/storage/spider/mysql-test/spider/bugfix/t/wait_timeout.test
@@ -0,0 +1,109 @@
+--source ../include/wait_timeout_init.inc
+--echo
+--echo this test is for MDEV-16530
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--connection child2_1_2
+USE auto_test_remote;
+
+--connection child2_2
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+--connection child2_2_2
+USE auto_test_remote2;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+--disable_query_log
+echo CHILD2_2_CREATE_TABLES;
+eval $CHILD2_2_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19);
+INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29);
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a READ;
+
+--connection child2_2
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+send_eval INSERT INTO tbl_a SELECT pkey + 30 FROM tbl_a ORDER BY pkey;
+
+--connection child2_1_2
+SELECT SLEEP(2);
+eval $CHILD2_1_SELECT_ARGUMENT1;
+
+--connection child2_2_2
+eval $CHILD2_2_SELECT_ARGUMENT1;
+
+--connection child2_1
+UNLOCK TABLES;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection child2_2
+eval $CHILD2_2_SELECT_TABLES;
+
+--connection master_1
+reap;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--connection child2_2
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/wait_timeout_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_deinit.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_deinit.inc
new file mode 100644
index 00000000000..52b0625ed9a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_deinit.inc
@@ -0,0 +1,16 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP
+--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP
+--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP
+--connection master_1
+set session spider_bgs_mode= @old_spider_bgs_mode;
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_deinit.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_deinit.inc
new file mode 100644
index 00000000000..799bd983393
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_deinit.inc
@@ -0,0 +1 @@
+--source checksum_table_parallel_deinit.inc
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_init.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_init.inc
new file mode 100644
index 00000000000..f17a532d53b
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_extended_init.inc
@@ -0,0 +1,2 @@
+--source checksum_table_parallel_init.inc
+--let $MASTER_1_CHECKSUM_TABLE= CHECKSUM TABLE tbl_a EXTENDED
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_init.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_init.inc
new file mode 100644
index 00000000000..7aab82515a0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_init.inc
@@ -0,0 +1,53 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+if (!$HAVE_PARTITION)
+{
+ --source checksum_table_parallel_deinit.inc
+ --enable_result_log
+ --enable_query_log
+ --enable_warnings
+ skip Test requires partitioning;
+}
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a"'
+ PARTITION BY KEY(pkey) (
+ PARTITION pt1 COMMENT='srv "s_2_1"',
+ PARTITION pt2 COMMENT='srv "s_2_2"'
+ );
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES
+let $CHILD2_2_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES
+let $CHILD2_2_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
+--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES
+let $CHILD2_2_SELECT_TABLES=
+ SELECT pkey FROM tbl_a ORDER BY pkey;
+let $CHILD2_2_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+--connection master_1
+set @old_spider_bgs_mode= @@spider_bgs_mode;
+set session spider_bgs_mode= 1;
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_deinit.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_deinit.inc
new file mode 100644
index 00000000000..799bd983393
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_deinit.inc
@@ -0,0 +1 @@
+--source checksum_table_parallel_deinit.inc
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_init.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_init.inc
new file mode 100644
index 00000000000..230b6432a01
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_no_opt_init.inc
@@ -0,0 +1,2 @@
+--source checksum_table_parallel_init.inc
+--let $MASTER_1_CHECKSUM_TABLE= CHECKSUM TABLE tbl_a
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_deinit.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_deinit.inc
new file mode 100644
index 00000000000..799bd983393
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_deinit.inc
@@ -0,0 +1 @@
+--source checksum_table_parallel_deinit.inc
diff --git a/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_init.inc b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_init.inc
new file mode 100644
index 00000000000..66f6ecbe0ef
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/checksum_table_parallel_quick_init.inc
@@ -0,0 +1,2 @@
+--source checksum_table_parallel_init.inc
+--let $MASTER_1_CHECKSUM_TABLE= CHECKSUM TABLE tbl_a QUICK
diff --git a/storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_deinit.inc b/storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_deinit.inc
new file mode 100644
index 00000000000..5ac67cdf783
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_deinit.inc
@@ -0,0 +1,10 @@
+--connection slave1_1
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../include/deinit_spider.inc
+--source ../t/slave_test_deinit.inc
+--source ../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_init.inc b/storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_init.inc
new file mode 100644
index 00000000000..052d6ebb2eb
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/include/slave_transaction_retry_errors_init.inc
@@ -0,0 +1,10 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../t/test_init.inc
+--source ../t/slave_test_init.inc
+--connection slave1_1
+--source ../include/init_spider.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/feature/my.cnf b/storage/spider/mysql-test/spider/feature/my.cnf
new file mode 100644
index 00000000000..b7f76a630cc
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my.cnf
@@ -0,0 +1,2 @@
+!include include/default_mysqld.cnf
+!include my_1_1.cnf
diff --git a/storage/spider/mysql-test/spider/feature/my_1_1.cnf b/storage/spider/mysql-test/spider/feature/my_1_1.cnf
new file mode 100644
index 00000000000..5f17295d895
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_1_1.cnf
@@ -0,0 +1,44 @@
+[mysqld.1.1]
+log-bin= master-bin
+loose_handlersocket_port= 20000
+loose_handlersocket_port_wr= 20001
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+loose_partition= 1
+
+[ENV]
+USE_GEOMETRY_TEST= 1
+USE_FULLTEXT_TEST= 1
+USE_HA_TEST= 1
+USE_GENERAL_LOG= 1
+USE_REPLICATION= 1
+MASTER_1_MYPORT= @mysqld.1.1.port
+MASTER_1_HSRPORT= 20000
+MASTER_1_HSWPORT= 20001
+MASTER_1_MYSOCK= @mysqld.1.1.socket
+MASTER_1_ENGINE_TYPE= Spider
+#MASTER_1_ENGINE_TYPE= MyISAM
+MASTER_1_ENGINE= ENGINE=Spider
+MASTER_1_CHARSET= DEFAULT CHARSET=utf8
+MASTER_1_ENGINE2= ENGINE=MyISAM
+MASTER_1_CHARSET2= DEFAULT CHARSET=utf8
+MASTER_1_CHARSET3= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
+
+STR_SEMICOLON= ;
+
+#The followings are set in include/init_xxx.inc files
+# MASTER_1_COMMENT_2_1
+# MASTER_1_COMMENT2_2_1
+# MASTER_1_COMMENT3_2_1
+# MASTER_1_COMMENT4_2_1
+# MASTER_1_COMMENT5_2_1
+# MASTER_1_COMMENT_P_2_1
diff --git a/storage/spider/mysql-test/spider/feature/my_2_1.cnf b/storage/spider/mysql-test/spider/feature/my_2_1.cnf
new file mode 100644
index 00000000000..24161645607
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_2_1.cnf
@@ -0,0 +1,56 @@
+[mysqld.2.1]
+loose_handlersocket_port= 20002
+loose_handlersocket_port_wr= 20003
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+
+[ENV]
+USE_CHILD_GROUP2= 1
+OUTPUT_CHILD_GROUP2= 0
+CHILD2_1_MYPORT= @mysqld.2.1.port
+CHILD2_1_HSRPORT= 20002
+CHILD2_1_HSWPORT= 20003
+CHILD2_1_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_ENGINE_TYPE= InnoDB
+CHILD2_1_ENGINE= ENGINE=InnoDB
+CHILD2_1_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_1_CHARSET2= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
+CHILD2_1_FT_MYPORT= @mysqld.2.1.port
+CHILD2_1_FT_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_FT_ENGINE_TYPE= MyISAM
+CHILD2_1_FT_ENGINE= ENGINE=MyISAM
+CHILD2_1_FT_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_1_GM_MYPORT= @mysqld.2.1.port
+CHILD2_1_GM_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_GM_ENGINE_TYPE= MyISAM
+CHILD2_1_GM_ENGINE= ENGINE=MyISAM
+CHILD2_1_GM_CHARSET= DEFAULT CHARSET=utf8
+
+#The followings are set in include/init_xxx.inc files
+# CHILD2_1_DROP_TABLES
+# CHILD2_1_CREATE_TABLES
+# CHILD2_1_SELECT_TABLES
+# CHILD2_1_DROP_TABLES2
+# CHILD2_1_CREATE_TABLES2
+# CHILD2_1_SELECT_TABLES2
+# CHILD2_1_DROP_TABLES3
+# CHILD2_1_CREATE_TABLES3
+# CHILD2_1_SELECT_TABLES3
+# CHILD2_1_DROP_TABLES4
+# CHILD2_1_CREATE_TABLES4
+# CHILD2_1_SELECT_TABLES4
+# CHILD2_1_DROP_TABLES5
+# CHILD2_1_CREATE_TABLES5
+# CHILD2_1_SELECT_TABLES5
+# CHILD2_1_DROP_TABLES6
+# CHILD2_1_CREATE_TABLES6
+# CHILD2_1_SELECT_TABLES6
diff --git a/storage/spider/mysql-test/spider/feature/my_2_2.cnf b/storage/spider/mysql-test/spider/feature/my_2_2.cnf
new file mode 100644
index 00000000000..2d3c2a89a7d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_2_2.cnf
@@ -0,0 +1,38 @@
+[mysqld.2.2]
+loose_handlersocket_port= 20004
+loose_handlersocket_port_wr= 20005
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+
+[ENV]
+CHILD2_2_MYPORT= @mysqld.2.2.port
+CHILD2_2_HSRPORT= 20004
+CHILD2_2_HSWPORT= 20005
+CHILD2_2_MYSOCK= @mysqld.2.2.socket
+CHILD2_2_ENGINE_TYPE= InnoDB
+CHILD2_2_ENGINE= ENGINE=InnoDB
+CHILD2_2_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_2_FT_MYPORT= @mysqld.2.2.port
+CHILD2_2_FT_MYSOCK= @mysqld.2.2.socket
+CHILD2_2_FT_ENGINE_TYPE= MyISAM
+CHILD2_2_FT_ENGINE= ENGINE=MyISAM
+CHILD2_2_FT_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_2_GM_MYPORT= @mysqld.2.2.port
+CHILD2_2_GM_MYSOCK= @mysqld.2.2.socket
+CHILD2_2_GM_ENGINE_TYPE= MyISAM
+CHILD2_2_GM_ENGINE= ENGINE=MyISAM
+CHILD2_2_GM_CHARSET= DEFAULT CHARSET=utf8
+
+#The followings are set in include/init_xxx.inc files
+# CHILD2_2_DROP_TABLES
+# CHILD2_2_CREATE_TABLES
+# CHILD2_2_SELECT_TABLES
diff --git a/storage/spider/mysql-test/spider/feature/my_2_3.cnf b/storage/spider/mysql-test/spider/feature/my_2_3.cnf
new file mode 100644
index 00000000000..024da651e0c
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_2_3.cnf
@@ -0,0 +1,8 @@
+[mysqld.2.3]
+
+[ENV]
+CHILD2_3_MYPORT= @mysqld.2.3.port
+CHILD2_3_MYSOCK= @mysqld.2.3.socket
+CHILD2_3_ENGINE_TYPE= InnoDB
+CHILD2_3_ENGINE= ENGINE=InnoDB
+CHILD2_3_CHARSET= DEFAULT CHARSET=utf8
diff --git a/storage/spider/mysql-test/spider/feature/my_3_1.cnf b/storage/spider/mysql-test/spider/feature/my_3_1.cnf
new file mode 100644
index 00000000000..fad21607789
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_3_1.cnf
@@ -0,0 +1,11 @@
+[mysqld.3.1]
+loose_partition= 1
+
+[ENV]
+USE_CHILD_GROUP3= 1
+OUTPUT_CHILD_GROUP3= 0
+CHILD3_1_MYPORT= @mysqld.3.1.port
+CHILD3_1_MYSOCK= @mysqld.3.1.socket
+CHILD3_1_ENGINE_TYPE= InnoDB
+CHILD3_1_ENGINE= ENGINE=InnoDB
+CHILD3_1_CHARSET= DEFAULT CHARSET=utf8
diff --git a/storage/spider/mysql-test/spider/feature/my_3_2.cnf b/storage/spider/mysql-test/spider/feature/my_3_2.cnf
new file mode 100644
index 00000000000..6f027b6f525
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_3_2.cnf
@@ -0,0 +1,9 @@
+[mysqld.3.2]
+loose_partition= 1
+
+[ENV]
+CHILD3_2_MYPORT= @mysqld.3.2.port
+CHILD3_2_MYSOCK= @mysqld.3.2.socket
+CHILD3_2_ENGINE_TYPE= InnoDB
+CHILD3_2_ENGINE= ENGINE=InnoDB
+CHILD3_2_CHARSET= DEFAULT CHARSET=utf8
diff --git a/storage/spider/mysql-test/spider/feature/my_3_3.cnf b/storage/spider/mysql-test/spider/feature/my_3_3.cnf
new file mode 100644
index 00000000000..fbb33694738
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_3_3.cnf
@@ -0,0 +1,9 @@
+[mysqld.3.3]
+loose_partition= 1
+
+[ENV]
+CHILD3_3_MYPORT= @mysqld.3.3.port
+CHILD3_3_MYSOCK= @mysqld.3.3.socket
+CHILD3_3_ENGINE_TYPE= InnoDB
+CHILD3_3_ENGINE= ENGINE=InnoDB
+CHILD3_3_CHARSET= DEFAULT CHARSET=utf8
diff --git a/storage/spider/mysql-test/spider/feature/my_4_1.cnf b/storage/spider/mysql-test/spider/feature/my_4_1.cnf
new file mode 100644
index 00000000000..d1812a48b68
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/my_4_1.cnf
@@ -0,0 +1,9 @@
+[mysqld.4.1]
+loose_partition= 1
+
+[ENV]
+SLAVE1_1_MYPORT= @mysqld.4.1.port
+SLAVE1_1_MYSOCK= @mysqld.4.1.socket
+SLAVE1_1_ENGINE_TYPE= MyISAM
+SLAVE1_1_ENGINE= ENGINE=MyISAM
+SLAVE1_1_CHARSET= DEFAULT CHARSET=utf8
diff --git a/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_extended.result b/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_extended.result
new file mode 100644
index 00000000000..34587052181
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_extended.result
@@ -0,0 +1,130 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_bgs_mode= @@spider_bgs_mode;
+set session spider_bgs_mode= 1;
+
+this test is for MDEV-16967
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_1_2;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+connection child2_2_2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19);
+INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+connection master_1;
+CHECKSUM TABLE tbl_a EXTENDED;
+connection child2_1_2;
+SELECT SLEEP(1);
+SLEEP(1)
+0
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+argument
+checksum table `auto_test_remote`.`tbl_a` extended
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
+connection child2_2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+argument
+checksum table `auto_test_remote2`.`tbl_a` extended
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
+connection child2_1;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+connection child2_2;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
+20
+22
+24
+26
+28
+connection master_1;
+Table Checksum
+auto_test_local.tbl_a 1061386331
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_bgs_mode= @old_spider_bgs_mode;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_no_opt.result b/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_no_opt.result
new file mode 100644
index 00000000000..4e44bd4cc73
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_no_opt.result
@@ -0,0 +1,128 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_bgs_mode= @@spider_bgs_mode;
+set session spider_bgs_mode= 1;
+
+this test is for MDEV-16967
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_1_2;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+connection child2_2_2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19);
+INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+connection master_1;
+CHECKSUM TABLE tbl_a;
+connection child2_1_2;
+SELECT SLEEP(1);
+SLEEP(1)
+0
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+argument
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
+connection child2_2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+argument
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
+connection child2_1;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+connection child2_2;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
+20
+22
+24
+26
+28
+connection master_1;
+Table Checksum
+auto_test_local.tbl_a NULL
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_bgs_mode= @old_spider_bgs_mode;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_quick.result b/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_quick.result
new file mode 100644
index 00000000000..b2c55b34130
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/r/checksum_table_parallel_quick.result
@@ -0,0 +1,128 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_bgs_mode= @@spider_bgs_mode;
+set session spider_bgs_mode= 1;
+
+this test is for MDEV-16967
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_1_2;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+connection child2_2_2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19);
+INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+connection master_1;
+CHECKSUM TABLE tbl_a QUICK;
+connection child2_1_2;
+SELECT SLEEP(1);
+SLEEP(1)
+0
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+argument
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
+connection child2_2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
+argument
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
+connection child2_1;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+1
+3
+5
+7
+9
+11
+13
+15
+17
+19
+21
+23
+25
+27
+29
+connection child2_2;
+UNLOCK TABLES;
+SELECT pkey FROM tbl_a ORDER BY pkey;
+pkey
+0
+2
+4
+6
+8
+10
+12
+14
+16
+18
+20
+22
+24
+26
+28
+connection master_1;
+Table Checksum
+auto_test_local.tbl_a NULL
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_bgs_mode= @old_spider_bgs_mode;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result b/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result
new file mode 100644
index 00000000000..0a147c0356a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/r/slave_transaction_retry_errors.result
@@ -0,0 +1,22 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+for slave1_1
+
+connection slave1_1;
+SHOW VARIABLES LIKE 'slave_transaction_retry_errors';
+Variable_name Value
+slave_transaction_retry_errors 1158,1159,1160,1161,1205,1213,1429,2013,12701
+connection slave1_1;
+for slave1_1
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/feature/suite.opt b/storage/spider/mysql-test/spider/feature/suite.opt
new file mode 100644
index 00000000000..672a3b37d4f
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/suite.opt
@@ -0,0 +1 @@
+--loose-innodb --loose-skip-performance-schema
diff --git a/storage/spider/mysql-test/spider/feature/suite.pm b/storage/spider/mysql-test/spider/feature/suite.pm
new file mode 100644
index 00000000000..f106147deb6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/suite.pm
@@ -0,0 +1,12 @@
+package My::Suite::Spider;
+
+@ISA = qw(My::Suite);
+
+return "No Spider engine" unless $ENV{HA_SPIDER_SO};
+return "Not run for embedded server" if $::opt_embedded_server;
+return "Test needs --big-test" unless $::opt_big_test;
+
+sub is_default { 1 }
+
+bless { };
+
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel.inc b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel.inc
new file mode 100644
index 00000000000..13e5053d64c
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel.inc
@@ -0,0 +1,107 @@
+--echo
+--echo this test is for MDEV-16967
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--connection child2_1_2
+USE auto_test_remote;
+
+--connection child2_2
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+--connection child2_2_2
+USE auto_test_remote2;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+--disable_query_log
+echo CHILD2_2_CREATE_TABLES;
+eval $CHILD2_2_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+INSERT INTO tbl_a (pkey) VALUES (10),(11),(12),(13),(14),(15),(16),(17),(18),(19);
+INSERT INTO tbl_a (pkey) VALUES (20),(21),(22),(23),(24),(25),(26),(27),(28),(29);
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+
+--connection child2_2
+TRUNCATE TABLE mysql.general_log;
+LOCK TABLE tbl_a WRITE;
+
+--connection master_1
+send_eval $MASTER_1_CHECKSUM_TABLE;
+
+--connection child2_1_2
+SELECT SLEEP(1);
+eval $CHILD2_1_SELECT_ARGUMENT1;
+
+--connection child2_2_2
+eval $CHILD2_2_SELECT_ARGUMENT1;
+
+--connection child2_1
+UNLOCK TABLES;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection child2_2
+UNLOCK TABLES;
+eval $CHILD2_2_SELECT_TABLES;
+
+--connection master_1
+reap;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--connection child2_2
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.cnf b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.cnf
new file mode 100644
index 00000000000..e0ffb99c38e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.test b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.test
new file mode 100644
index 00000000000..871e1e868ad
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_extended.test
@@ -0,0 +1,5 @@
+--source ../include/checksum_table_parallel_extended_init.inc
+--source checksum_table_parallel.inc
+--source ../include/checksum_table_parallel_extended_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.cnf b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.cnf
new file mode 100644
index 00000000000..e0ffb99c38e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.test b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.test
new file mode 100644
index 00000000000..0352d598df6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_no_opt.test
@@ -0,0 +1,5 @@
+--source ../include/checksum_table_parallel_no_opt_init.inc
+--source checksum_table_parallel.inc
+--source ../include/checksum_table_parallel_no_opt_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.cnf b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.cnf
new file mode 100644
index 00000000000..e0ffb99c38e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.test b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.test
new file mode 100644
index 00000000000..f08f782e7c0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/checksum_table_parallel_quick.test
@@ -0,0 +1,5 @@
+--source ../include/checksum_table_parallel_quick_init.inc
+--source checksum_table_parallel.inc
+--source ../include/checksum_table_parallel_quick_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.cnf b/storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.cnf
new file mode 100644
index 00000000000..45019d6c537
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include ../my_1_1.cnf
+!include ../my_2_1.cnf
+!include ../my_4_1.cnf
diff --git a/storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.test b/storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.test
new file mode 100644
index 00000000000..436bc3fb761
--- /dev/null
+++ b/storage/spider/mysql-test/spider/feature/t/slave_transaction_retry_errors.test
@@ -0,0 +1,9 @@
+--source ../include/slave_transaction_retry_errors_init.inc
+--echo
+
+--connection slave1_1
+SHOW VARIABLES LIKE 'slave_transaction_retry_errors';
+
+--source ../include/slave_transaction_retry_errors_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc
index d551f5a4af3..7db871c700f 100644
--- a/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc
+++ b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_deinit.inc
@@ -1,5 +1,3 @@
---let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
---let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
--let $OUTPUT_CHILD_GROUP2= $OUTPUT_CHILD_GROUP2_BACKUP
diff --git a/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc
index 9ec61a1cb77..0bb12d8f874 100644
--- a/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc
+++ b/storage/spider/mysql-test/spider/include/checksum_table_with_quick_mode_3_init.inc
@@ -21,7 +21,7 @@ let $CHILD2_1_CREATE_TABLES=
let $CHILD2_1_SELECT_TABLES=
SELECT pkey FROM tbl_a ORDER BY pkey;
let $CHILD2_1_SELECT_ARGUMENT1=
- SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
--let $OUTPUT_CHILD_GROUP2_BACKUP= $OUTPUT_CHILD_GROUP2
--let $OUTPUT_CHILD_GROUP2= 1
--let $USE_GENERAL_LOG_BACKUP= $USE_GENERAL_LOG
diff --git a/storage/spider/mysql-test/spider/include/deinit_spider.inc b/storage/spider/mysql-test/spider/include/deinit_spider.inc
index 3609551e169..51cc075edaa 100644
--- a/storage/spider/mysql-test/spider/include/deinit_spider.inc
+++ b/storage/spider/mysql-test/spider/include/deinit_spider.inc
@@ -1,8 +1,39 @@
-DROP FUNCTION spider_direct_sql;
-DROP FUNCTION spider_bg_direct_sql;
-DROP FUNCTION spider_ping_table;
-DROP FUNCTION spider_copy_tables;
+let $SERVER_NAME=
+ `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '-', 2), '-', -1)`;
+let $SERVER_MAJOR_VERSION=
+ `SELECT SUBSTRING_INDEX(version(), '.', 1)`;
+let $SERVER_MINOR_VERSION=
+ `SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(version(), '.', 2), '.', -1)`;
+let $PLUGIN_VERSION=
+ `SELECT SUBSTRING_INDEX(plugin_version, '.', 1)
+ FROM information_schema.plugins
+ WHERE plugin_name = 'SPIDER'`;
+if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`)
+{
+ let $HAS_REWRITE=
+ `SELECT IF (STRCMP('$SERVER_NAME', 'MariaDB') = 0,
+ IF ($SERVER_MAJOR_VERSION = 10,
+ IF ($SERVER_MINOR_VERSION < 4, 0, 1),
+ IF ($SERVER_MAJOR_VERSION < 10, 0, 1)),
+ 0)`;
+ let $HAS_REWRITE= 0;
+ if ($HAS_REWRITE)
+ {
+ DROP FUNCTION spider_flush_rewrite_cache;
+ UNINSTALL PLUGIN spider_rewrite;
+ DROP TABLE IF EXISTS mysql.spider_rewrite_tables;
+ DROP TABLE IF EXISTS mysql.spider_rewrite_table_tables;
+ DROP TABLE IF EXISTS mysql.spider_rewrite_table_partitions;
+ DROP TABLE IF EXISTS mysql.spider_rewrite_table_subpartitions;
+ DROP TABLE IF EXISTS mysql.spider_rewritten_tables;
+ }
+}
DROP FUNCTION spider_flush_table_mon_cache;
+DROP FUNCTION spider_copy_tables;
+DROP FUNCTION spider_ping_table;
+DROP FUNCTION spider_bg_direct_sql;
+DROP FUNCTION spider_direct_sql;
+UNINSTALL PLUGIN spider_alloc_mem;
UNINSTALL PLUGIN spider;
DROP TABLE IF EXISTS mysql.spider_xa;
DROP TABLE IF EXISTS mysql.spider_xa_member;
@@ -13,9 +44,57 @@ DROP TABLE IF EXISTS mysql.spider_link_failed_log;
DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery;
DROP TABLE IF EXISTS mysql.spider_table_sts;
DROP TABLE IF EXISTS mysql.spider_table_crd;
-DROP SERVER s_2_1;
-DROP SERVER s_2_2;
-DROP SERVER s_2_3;
-DROP SERVER s_3_1;
-DROP SERVER s_3_2;
-DROP SERVER s_3_3;
+if ($VERSION_COMPILE_OS_WIN)
+{
+ if ($CHILD2_1_MYPORT)
+ {
+ DROP SERVER s_2_1;
+ }
+ if ($CHILD2_2_MYPORT)
+ {
+ DROP SERVER s_2_2;
+ }
+ if ($CHILD2_3_MYPORT)
+ {
+ DROP SERVER s_2_3;
+ }
+ if ($CHILD3_1_MYPORT)
+ {
+ DROP SERVER s_3_1;
+ }
+ if ($CHILD3_2_MYPORT)
+ {
+ DROP SERVER s_3_2;
+ }
+ if ($CHILD2_3_MYPORT)
+ {
+ DROP SERVER s_3_3;
+ }
+}
+if (!$VERSION_COMPILE_OS_WIN)
+{
+ if ($CHILD2_1_MYSOCK)
+ {
+ DROP SERVER s_2_1;
+ }
+ if ($CHILD2_2_MYSOCK)
+ {
+ DROP SERVER s_2_2;
+ }
+ if ($CHILD2_3_MYSOCK)
+ {
+ DROP SERVER s_2_3;
+ }
+ if ($CHILD3_1_MYSOCK)
+ {
+ DROP SERVER s_3_1;
+ }
+ if ($CHILD3_2_MYSOCK)
+ {
+ DROP SERVER s_3_2;
+ }
+ if ($CHILD3_3_MYSOCK)
+ {
+ DROP SERVER s_3_3;
+ }
+}
diff --git a/storage/spider/mysql-test/spider/include/init_spider.inc b/storage/spider/mysql-test/spider/include/init_spider.inc
index 1da1ec970b5..69d1fae425e 100644
--- a/storage/spider/mysql-test/spider/include/init_spider.inc
+++ b/storage/spider/mysql-test/spider/include/init_spider.inc
@@ -3,104 +3,130 @@ let $VERSION_COMPILE_OS_WIN=
if ($VERSION_COMPILE_OS_WIN)
{
INSTALL PLUGIN spider SONAME 'ha_spider.dll';
- CREATE FUNCTION spider_direct_sql RETURNS INT SONAME 'ha_spider.dll';
- CREATE AGGREGATE FUNCTION spider_bg_direct_sql RETURNS INT SONAME 'ha_spider.dll';
- CREATE FUNCTION spider_ping_table RETURNS INT SONAME 'ha_spider.dll';
- CREATE FUNCTION spider_copy_tables RETURNS INT SONAME 'ha_spider.dll';
- CREATE FUNCTION spider_flush_table_mon_cache RETURNS INT SONAME 'ha_spider.dll';
- eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_remote',
- USER 'root',
- PASSWORD '',
- PORT $CHILD2_1_MYPORT
- );
- eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_remote2',
- USER 'root',
- PASSWORD '',
- PORT $CHILD2_2_MYPORT
- );
- eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_remote3',
- USER 'root',
- PASSWORD '',
- PORT $CHILD2_3_MYPORT
- );
- eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_local',
- USER 'root',
- PASSWORD '',
- PORT $CHILD3_1_MYPORT
- );
- eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_local',
- USER 'root',
- PASSWORD '',
- PORT $CHILD3_2_MYPORT
- );
- eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_local',
- USER 'root',
- PASSWORD '',
- PORT $CHILD2_3_MYPORT
- );
+ if ($CHILD2_1_MYPORT)
+ {
+ eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_remote',
+ USER 'root',
+ PASSWORD '',
+ PORT $CHILD2_1_MYPORT
+ );
+ }
+ if ($CHILD2_2_MYPORT)
+ {
+ eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_remote2',
+ USER 'root',
+ PASSWORD '',
+ PORT $CHILD2_2_MYPORT
+ );
+ }
+ if ($CHILD2_3_MYPORT)
+ {
+ eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_remote3',
+ USER 'root',
+ PASSWORD '',
+ PORT $CHILD2_3_MYPORT
+ );
+ }
+ if ($CHILD3_1_MYPORT)
+ {
+ eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_local',
+ USER 'root',
+ PASSWORD '',
+ PORT $CHILD3_1_MYPORT
+ );
+ }
+ if ($CHILD3_2_MYPORT)
+ {
+ eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_local',
+ USER 'root',
+ PASSWORD '',
+ PORT $CHILD3_2_MYPORT
+ );
+ }
+ if ($CHILD2_3_MYPORT)
+ {
+ eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_local',
+ USER 'root',
+ PASSWORD '',
+ PORT $CHILD2_3_MYPORT
+ );
+ }
}
if (!$VERSION_COMPILE_OS_WIN)
{
INSTALL PLUGIN spider SONAME 'ha_spider.so';
- CREATE FUNCTION spider_direct_sql RETURNS INT SONAME 'ha_spider.so';
- CREATE AGGREGATE FUNCTION spider_bg_direct_sql RETURNS INT SONAME 'ha_spider.so';
- CREATE FUNCTION spider_ping_table RETURNS INT SONAME 'ha_spider.so';
- CREATE FUNCTION spider_copy_tables RETURNS INT SONAME 'ha_spider.so';
- CREATE FUNCTION spider_flush_table_mon_cache RETURNS INT SONAME 'ha_spider.so';
- eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_remote',
- USER 'root',
- PASSWORD '',
- SOCKET '$CHILD2_1_MYSOCK'
- );
- eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_remote2',
- USER 'root',
- PASSWORD '',
- SOCKET '$CHILD2_2_MYSOCK'
- );
- eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_remote3',
- USER 'root',
- PASSWORD '',
- SOCKET '$CHILD2_3_MYSOCK'
- );
- eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_local',
- USER 'root',
- PASSWORD '',
- SOCKET '$CHILD3_1_MYSOCK'
- );
- eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_local',
- USER 'root',
- PASSWORD '',
- SOCKET '$CHILD3_2_MYSOCK'
- );
- eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS (
- HOST 'localhost',
- DATABASE 'auto_test_local',
- USER 'root',
- PASSWORD '',
- SOCKET '$CHILD3_3_MYSOCK'
- );
+ if ($CHILD2_1_MYSOCK)
+ {
+ eval CREATE SERVER s_2_1 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_remote',
+ USER 'root',
+ PASSWORD '',
+ SOCKET '$CHILD2_1_MYSOCK'
+ );
+ }
+ if ($CHILD2_2_MYSOCK)
+ {
+ eval CREATE SERVER s_2_2 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_remote2',
+ USER 'root',
+ PASSWORD '',
+ SOCKET '$CHILD2_2_MYSOCK'
+ );
+ }
+ if ($CHILD2_3_MYSOCK)
+ {
+ eval CREATE SERVER s_2_3 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_remote3',
+ USER 'root',
+ PASSWORD '',
+ SOCKET '$CHILD2_3_MYSOCK'
+ );
+ }
+ if ($CHILD3_1_MYSOCK)
+ {
+ eval CREATE SERVER s_3_1 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_local',
+ USER 'root',
+ PASSWORD '',
+ SOCKET '$CHILD3_1_MYSOCK'
+ );
+ }
+ if ($CHILD3_2_MYSOCK)
+ {
+ eval CREATE SERVER s_3_2 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_local',
+ USER 'root',
+ PASSWORD '',
+ SOCKET '$CHILD3_2_MYSOCK'
+ );
+ }
+ if ($CHILD3_3_MYSOCK)
+ {
+ eval CREATE SERVER s_3_3 FOREIGN DATA WRAPPER mysql OPTIONS (
+ HOST 'localhost',
+ DATABASE 'auto_test_local',
+ USER 'root',
+ PASSWORD '',
+ SOCKET '$CHILD3_3_MYSOCK'
+ );
+ }
}
let $SERVER_NAME=
@@ -113,313 +139,34 @@ let $PLUGIN_VERSION=
`SELECT SUBSTRING_INDEX(plugin_version, '.', 1)
FROM information_schema.plugins
WHERE plugin_name = 'SPIDER'`;
-
-if (`SELECT IF($PLUGIN_VERSION = 1, 1, 0)`)
-{
- DROP TABLE IF EXISTS mysql.spider_xa;
- CREATE TABLE mysql.spider_xa(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- status char(8) not null default '',
- PRIMARY KEY (data, format_id, gtrid_length),
- KEY idx1 (status)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_xa_member;
- CREATE TABLE mysql.spider_xa_member(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- scheme char(64) not null default '',
- host char(64) not null default '',
- port char(5) not null default '',
- socket char(64) not null default '',
- username char(64) not null default '',
- password char(64) not null default '',
- PRIMARY KEY (data, format_id, gtrid_length, host, port, socket)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_tables;
- CREATE TABLE mysql.spider_tables(
- db_name char(64) not null default '',
- table_name char(64) not null default '',
- priority bigint not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket char(64) default null,
- username char(64) default null,
- password char(64) default null,
- tgt_db_name char(64) default null,
- tgt_table_name char(64) default null,
- PRIMARY KEY (db_name, table_name),
- KEY idx1 (priority)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-}
-if (`SELECT IF($PLUGIN_VERSION = 2, 1, 0)`)
-{
- DROP TABLE IF EXISTS mysql.spider_xa;
- CREATE TABLE mysql.spider_xa(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- status char(8) not null default '',
- PRIMARY KEY (data, format_id, gtrid_length),
- KEY idx1 (status)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_xa_member;
- CREATE TABLE mysql.spider_xa_member(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- scheme char(64) not null default '',
- host char(64) not null default '',
- port char(5) not null default '',
- socket char(64) not null default '',
- username char(64) not null default '',
- password char(64) not null default '',
- ssl_ca char(64) default null,
- ssl_capath char(64) default null,
- ssl_cert char(64) default null,
- ssl_cipher char(64) default null,
- ssl_key char(64) default null,
- ssl_verify_server_cert tinyint not null default 0,
- default_file char(64) default null,
- default_group char(64) default null,
- PRIMARY KEY (data, format_id, gtrid_length, host, port, socket)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_tables;
- CREATE TABLE mysql.spider_tables(
- db_name char(64) not null default '',
- table_name char(64) not null default '',
- link_id int not null default 0,
- priority bigint not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket char(64) default null,
- username char(64) default null,
- password char(64) default null,
- ssl_ca char(64) default null,
- ssl_capath char(64) default null,
- ssl_cert char(64) default null,
- ssl_cipher char(64) default null,
- ssl_key char(64) default null,
- ssl_verify_server_cert tinyint not null default 0,
- default_file char(64) default null,
- default_group char(64) default null,
- tgt_db_name char(64) default null,
- tgt_table_name char(64) default null,
- link_status tinyint not null default 1,
- PRIMARY KEY (db_name, table_name, link_id),
- KEY idx1 (priority)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_link_mon_servers;
- CREATE TABLE mysql.spider_link_mon_servers(
- db_name char(64) not null default '',
- table_name char(64) not null default '',
- link_id char(5) not null default '',
- sid int not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket char(64) default null,
- username char(64) default null,
- password char(64) default null,
- ssl_ca char(64) default null,
- ssl_capath char(64) default null,
- ssl_cert char(64) default null,
- ssl_cipher char(64) default null,
- ssl_key char(64) default null,
- ssl_verify_server_cert tinyint not null default 0,
- default_file char(64) default null,
- default_group char(64) default null,
- PRIMARY KEY (db_name, table_name, link_id, sid)
- ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_link_failed_log;
- CREATE TABLE mysql.spider_link_failed_log(
- db_name char(64) not null default '',
- table_name char(64) not null default '',
- link_id int not null default 0,
- failed_time timestamp not null default current_timestamp
- ) ENGINE=MYISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-}
if (`SELECT IF($PLUGIN_VERSION = 3, 1, 0)`)
{
- let $ENGINE_NAME=
+ let $HAS_REWRITE=
`SELECT IF (STRCMP('$SERVER_NAME', 'MariaDB') = 0,
IF ($SERVER_MAJOR_VERSION = 10,
- IF ($SERVER_MINOR_VERSION < 4, 'MyISAM',
- 'Aria transactional=1'),
- IF ($SERVER_MAJOR_VERSION < 10, 'MyISAM',
- 'Aria transactional=1')),
- 'MyISAM')`;
- DROP TABLE IF EXISTS mysql.spider_xa;
- eval
- CREATE TABLE mysql.spider_xa(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data binary(128) not null default '',
- status char(8) not null default '',
- PRIMARY KEY (data, format_id, gtrid_length),
- KEY idx1 (status)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_xa_member;
- eval
- CREATE TABLE mysql.spider_xa_member(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data binary(128) not null default '',
- scheme char(64) not null default '',
- host char(64) not null default '',
- port char(5) not null default '',
- socket text not null default '',
- username char(64) not null default '',
- password char(64) not null default '',
- ssl_ca text default null,
- ssl_capath text default null,
- ssl_cert text default null,
- ssl_cipher char(64) default null,
- ssl_key text default null,
- ssl_verify_server_cert tinyint not null default 0,
- default_file text default null,
- default_group char(64) default null,
- KEY idx1 (data, format_id, gtrid_length, host)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_xa_failed_log;
- eval
- CREATE TABLE mysql.spider_xa_failed_log(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data binary(128) not null default '',
- scheme char(64) not null default '',
- host char(64) not null default '',
- port char(5) not null default '',
- socket text not null,
- username char(64) not null default '',
- password char(64) not null default '',
- ssl_ca text,
- ssl_capath text,
- ssl_cert text,
- ssl_cipher char(64) default null,
- ssl_key text,
- ssl_verify_server_cert tinyint not null default 0,
- default_file text,
- default_group char(64) default null,
- thread_id int default null,
- status char(8) not null default '',
- failed_time timestamp not null default current_timestamp,
- key idx1 (data, format_id, gtrid_length, host)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_tables;
- eval
- CREATE TABLE mysql.spider_tables(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- link_id int not null default 0,
- priority bigint not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket text default null,
- username char(64) default null,
- password char(64) default null,
- ssl_ca text default null,
- ssl_capath text default null,
- ssl_cert text default null,
- ssl_cipher char(64) default null,
- ssl_key text default null,
- ssl_verify_server_cert tinyint not null default 0,
- monitoring_binlog_pos_at_failing tinyint not null default 0,
- default_file text default null,
- default_group char(64) default null,
- tgt_db_name char(64) default null,
- tgt_table_name char(64) default null,
- link_status tinyint not null default 1,
- block_status tinyint not null default 0,
- static_link_id char(64) default null,
- PRIMARY KEY (db_name, table_name, link_id),
- KEY idx1 (priority),
- UNIQUE KEY uidx1 (db_name, table_name, static_link_id)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_link_mon_servers;
- eval
- CREATE TABLE mysql.spider_link_mon_servers(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- link_id char(64) not null default '',
- sid int unsigned not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket text default null,
- username char(64) default null,
- password char(64) default null,
- ssl_ca text default null,
- ssl_capath text default null,
- ssl_cert text default null,
- ssl_cipher char(64) default null,
- ssl_key text default null,
- ssl_verify_server_cert tinyint not null default 0,
- default_file text default null,
- default_group char(64) default null,
- PRIMARY KEY (db_name, table_name, link_id, sid)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_link_failed_log;
- eval
- CREATE TABLE mysql.spider_link_failed_log(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- link_id char(64) not null default '',
- failed_time timestamp not null default current_timestamp
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_table_position_for_recovery;
- eval
- CREATE TABLE mysql.spider_table_position_for_recovery(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- failed_link_id int not null default 0,
- source_link_id int not null default 0,
- file text,
- position text,
- gtid text,
- primary key (db_name, table_name, failed_link_id, source_link_id)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_table_sts;
- eval
- CREATE TABLE mysql.spider_table_sts(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- data_file_length bigint unsigned not null default 0,
- max_data_file_length bigint unsigned not null default 0,
- index_file_length bigint unsigned not null default 0,
- records bigint unsigned not null default 0,
- mean_rec_length bigint unsigned not null default 0,
- check_time datetime not null default '0000-00-00 00:00:00',
- create_time datetime not null default '0000-00-00 00:00:00',
- update_time datetime not null default '0000-00-00 00:00:00',
- primary key (db_name, table_name)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
- DROP TABLE IF EXISTS mysql.spider_table_crd;
- eval
- CREATE TABLE mysql.spider_table_crd(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- key_seq int unsigned not null default 0,
- cardinality bigint not null default 0,
- primary key (db_name, table_name, key_seq)
- ) ENGINE=$ENGINE_NAME DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+ IF ($SERVER_MINOR_VERSION < 4, 0, 1),
+ IF ($SERVER_MAJOR_VERSION < 10, 0, 1)),
+ 0)`;
+ let $HAS_REWRITE= 0;
+ if ($HAS_REWRITE)
+ {
+ let $PLUGIN_NAME= spider_flush_rewrite_cache;
+ let $PLUGIN_EXIST=
+ `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`;
+ while (!$PLUGIN_EXIST)
+ {
+ let $PLUGIN_EXIST=
+ `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`;
+ }
+ }
+}
+let $PLUGIN_NAME= spider_flush_table_mon_cache;
+let $PLUGIN_EXIST=
+ `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`;
+while (!$PLUGIN_EXIST)
+{
+ let $PLUGIN_EXIST=
+ `SELECT COUNT(*) FROM mysql.func WHERE name = '$PLUGIN_NAME'`;
}
SET spider_internal_sql_log_off= 0;
diff --git a/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result b/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result
index ee8e1f056f3..2fe86099bc2 100644
--- a/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result
+++ b/storage/spider/mysql-test/spider/r/checksum_table_with_quick_mode_3.result
@@ -45,10 +45,10 @@ CHECKSUM TABLE tbl_a EXTENDED;
Table Checksum
auto_test_local.tbl_a 1061386331
connection child2_1;
-SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %';
argument
-select `pkey` from `auto_test_remote`.`tbl_a`
-SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+checksum table `auto_test_remote`.`tbl_a` extended
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%checksum %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
0
diff --git a/storage/spider/mysql-test/spider/r/direct_join.result b/storage/spider/mysql-test/spider/r/direct_join.result
index 0a76c3246f9..a1018c35fbf 100644
--- a/storage/spider/mysql-test/spider/r/direct_join.result
+++ b/storage/spider/mysql-test/spider/r/direct_join.result
@@ -167,7 +167,7 @@ connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
select `id`,`hr_status`,`region_code`,`region` from `auto_test_remote`.`tbl_person` where `id` = '24FC3F0A5119432BAE13DD65AABAA39C' and `region` = 510411
-select `person_id`,`diseaseKind_id` from `auto_test_remote`.`tbl_ncd_cm_person` where ((`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816'))
+select count(0) `count(0)` from `auto_test_remote`.`tbl_ncd_cm_person` t0 where ((t0.`person_id` = '24FC3F0A5119432BAE13DD65AABAA39C') and (t0.`diseaseKind_id` = '52A0328740914BCE86ED10A4D2521816'))
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
SELECT * FROM tbl_person;
id hr_status region_code region
diff --git a/storage/spider/mysql-test/spider/r/partition_fulltext.result b/storage/spider/mysql-test/spider/r/partition_fulltext.result
index 3289473b905..6c001d25444 100644
--- a/storage/spider/mysql-test/spider/r/partition_fulltext.result
+++ b/storage/spider/mysql-test/spider/r/partition_fulltext.result
@@ -71,7 +71,7 @@ pkey words
connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
-select match(`words`)against('+ghi' in boolean mode),`pkey`,`words` from `auto_test_remote`.`tbl_a` where match(`words`)against('+ghi' in boolean mode) and (match(`words`)against('+ghi' in boolean mode))
+select match(`words`)against('+ghi' in boolean mode),`pkey`,`words` from `auto_test_remote`.`tbl_a` where match(`words`)against('+ghi' in boolean mode) and (match(`words`)against(_latin1'+ghi' in boolean mode))
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
@@ -80,7 +80,7 @@ pkey
connection child2_2;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
-select match(`words`)against('+ghi' in boolean mode),`pkey`,`words` from `auto_test_remote2`.`tbl_a` where match(`words`)against('+ghi' in boolean mode) and (match(`words`)against('+ghi' in boolean mode))
+select match(`words`)against('+ghi' in boolean mode),`pkey`,`words` from `auto_test_remote2`.`tbl_a` where match(`words`)against('+ghi' in boolean mode) and (match(`words`)against(_latin1'+ghi' in boolean mode))
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
@@ -91,7 +91,7 @@ pkey
connection child2_3;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
-select match(`words`)against('+ghi' in boolean mode),`pkey`,`words` from `auto_test_remote3`.`tbl_a` where match(`words`)against('+ghi' in boolean mode) and (match(`words`)against('+ghi' in boolean mode))
+select match(`words`)against('+ghi' in boolean mode),`pkey`,`words` from `auto_test_remote3`.`tbl_a` where match(`words`)against('+ghi' in boolean mode) and (match(`words`)against(_latin1'+ghi' in boolean mode))
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
diff --git a/storage/spider/mysql-test/spider/r/show_system_tables.result b/storage/spider/mysql-test/spider/r/show_system_tables.result
index 831d4578efe..67411862e00 100644
--- a/storage/spider/mysql-test/spider/r/show_system_tables.result
+++ b/storage/spider/mysql-test/spider/r/show_system_tables.result
@@ -13,15 +13,15 @@ connection master_1;
SELECT table_name, engine FROM information_schema.tables
WHERE table_schema = 'mysql' AND table_name like '%spider_%';
table_name engine
-spider_link_failed_log MyISAM
-spider_link_mon_servers MyISAM
-spider_table_crd MyISAM
-spider_table_position_for_recovery MyISAM
-spider_table_sts MyISAM
-spider_tables MyISAM
-spider_xa MyISAM
-spider_xa_failed_log MyISAM
-spider_xa_member MyISAM
+spider_link_failed_log Aria
+spider_link_mon_servers Aria
+spider_table_crd Aria
+spider_table_position_for_recovery Aria
+spider_table_sts Aria
+spider_tables Aria
+spider_xa Aria
+spider_xa_failed_log Aria
+spider_xa_member Aria
deinit
for master_1
diff --git a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result
index 7d9ba40cab3..e68b4a2c82d 100644
--- a/storage/spider/mysql-test/spider/r/slave_trx_isolation.result
+++ b/storage/spider/mysql-test/spider/r/slave_trx_isolation.result
@@ -53,7 +53,7 @@ SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %';
argument
set session time_zone = '+00:00'
SET NAMES utf8
-set session transaction isolation level read committed;set session autocommit = 1;start transaction
+set session transaction isolation level read committed;set session autocommit = 1;set session wait_timeout = 604800;set session sql_mode = 'strict_trans_tables,error_for_division_by_zero,no_auto_create_user,no_engine_substitution';start transaction
SELECT argument FROM mysql.general_log WHERE argument LIKE '%set %'
SELECT pkey FROM tbl_a ORDER BY pkey;
pkey
diff --git a/storage/spider/mysql-test/spider/r/timestamp.result b/storage/spider/mysql-test/spider/r/timestamp.result
index bd1f442d462..85ca7f6e7f4 100644
--- a/storage/spider/mysql-test/spider/r/timestamp.result
+++ b/storage/spider/mysql-test/spider/r/timestamp.result
@@ -252,11 +252,11 @@ col_a col_dt col_ts unix_timestamp(col_ts)
connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '2017-12-31 23:00:00')
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` < '2018-10-28 01:30:00')
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ('2018-10-28 01:30:00' > t0.`col_ts`)
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` between '2018-10-28 00:30:00' and '2018-10-28 01:30:00')
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ((t0.`col_ts` >= '2018-10-28 00:30:00') and (t0.`col_ts` <= '2018-10-28 01:30:00'))
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > _latin1'2017-12-31 23:00:00')
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` < _latin1'2018-10-28 01:30:00')
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (_latin1'2018-10-28 01:30:00' > t0.`col_ts`)
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` between _latin1'2018-10-28 00:30:00' and _latin1'2018-10-28 01:30:00')
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ((t0.`col_ts` >= _latin1'2018-10-28 00:30:00') and (t0.`col_ts` <= _latin1'2018-10-28 01:30:00'))
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '2018-03-25 01:00:00')
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '1970-01-01 00:00:01')
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
@@ -339,11 +339,11 @@ col_a col_dt col_ts unix_timestamp(col_ts)
connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '2017-12-31 23:00:00')
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` < '2018-10-28 01:30:00')
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ('2018-10-28 01:30:00' > t0.`col_ts`)
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` between '2018-10-28 00:30:00' and '2018-10-28 01:30:00')
-select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ((t0.`col_ts` >= '2018-10-28 00:30:00') and (t0.`col_ts` <= '2018-10-28 01:30:00'))
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > _latin1'2017-12-31 23:00:00')
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` < _latin1'2018-10-28 01:30:00')
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (_latin1'2018-10-28 01:30:00' > t0.`col_ts`)
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` between _latin1'2018-10-28 00:30:00' and _latin1'2018-10-28 01:30:00')
+select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where ((t0.`col_ts` >= _latin1'2018-10-28 00:30:00') and (t0.`col_ts` <= _latin1'2018-10-28 01:30:00'))
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '2018-03-25 01:00:00')
select t0.`col_a` `col_a`,t0.`col_dt` `col_dt`,t0.`col_ts` `col_ts`,(unix_timestamp(t0.`col_ts`)) `unix_timestamp(col_ts)` from `ts_test_remote`.`tbl_a` t0 where (t0.`col_ts` > '1970-01-01 00:00:01')
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_deinit.inc b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_deinit.inc
new file mode 100644
index 00000000000..ad30aac5d6e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_deinit.inc
@@ -0,0 +1,12 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $MASTER_1_COMMENT_2_1_2= $MASTER_1_COMMENT_2_1_2_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_init.inc b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_init.inc
new file mode 100644
index 00000000000..695d46101ae
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_key_init.inc
@@ -0,0 +1,36 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $MASTER_1_COMMENT_2_1_2_BACKUP= $MASTER_1_COMMENT_2_1_2
+let $MASTER_1_COMMENT_2_1_2=
+ COMMENT='table "tbl_b", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a $STR_SEMICOLON
+ DROP TABLE IF EXISTS tbl_b;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ akey int NOT NULL,
+ val int NOT NULL,
+ KEY idx1 (akey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET $STR_SEMICOLON
+ CREATE TABLE tbl_b (
+ bkey int NOT NULL,
+ akey int NOT NULL,
+ PRIMARY KEY (bkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT akey, val FROM tbl_a ORDER BY akey $STR_SEMICOLON
+ SELECT bkey, akey FROM tbl_b ORDER BY bkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' $STR_SEMICOLON
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%';
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_deinit.inc b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_deinit.inc
new file mode 100644
index 00000000000..ad30aac5d6e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_deinit.inc
@@ -0,0 +1,12 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $MASTER_1_COMMENT_2_1_2= $MASTER_1_COMMENT_2_1_2_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_init.inc b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_init.inc
new file mode 100644
index 00000000000..e364489c05f
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/direct_join_by_pkey_pkey_init.inc
@@ -0,0 +1,36 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $MASTER_1_COMMENT_2_1_2_BACKUP= $MASTER_1_COMMENT_2_1_2
+let $MASTER_1_COMMENT_2_1_2=
+ COMMENT='table "tbl_b", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a $STR_SEMICOLON
+ DROP TABLE IF EXISTS tbl_b;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ akey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (akey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET $STR_SEMICOLON
+ CREATE TABLE tbl_b (
+ bkey int NOT NULL,
+ akey int NOT NULL,
+ PRIMARY KEY (bkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT akey, val FROM tbl_a ORDER BY akey $STR_SEMICOLON
+ SELECT bkey, akey FROM tbl_b ORDER BY bkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' $STR_SEMICOLON
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%';
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_deinit.inc b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_deinit.inc
new file mode 100644
index 00000000000..f1899d1576a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_deinit.inc
@@ -0,0 +1,3 @@
+--connection master_1
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+--source load_data_deinit.inc
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_init.inc b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_init.inc
new file mode 100644
index 00000000000..24f0dc9820e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi0_init.inc
@@ -0,0 +1,4 @@
+--source load_data_init.inc
+--connection master_1
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_deinit.inc b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_deinit.inc
new file mode 100644
index 00000000000..f1899d1576a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_deinit.inc
@@ -0,0 +1,3 @@
+--connection master_1
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+--source load_data_deinit.inc
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_init.inc b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_init.inc
new file mode 100644
index 00000000000..50ef8d47696
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_ddi1_init.inc
@@ -0,0 +1,4 @@
+--source load_data_init.inc
+--connection master_1
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/load_data_deinit.inc b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_deinit.inc
new file mode 100644
index 00000000000..f8405973768
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_deinit.inc
@@ -0,0 +1,11 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e1121/include/load_data_init.inc b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_init.inc
new file mode 100644
index 00000000000..5f4104382dc
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/include/load_data_init.inc
@@ -0,0 +1,25 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_init.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a", srv "s_2_1"';
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, val FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
diff --git a/storage/spider/mysql-test/spider/regression/e1121/my.cnf b/storage/spider/mysql-test/spider/regression/e1121/my.cnf
new file mode 100644
index 00000000000..47558d85fc6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/my.cnf
@@ -0,0 +1,3 @@
+!include include/default_mysqld.cnf
+!include my_1_1.cnf
+!include my_2_1.cnf
diff --git a/storage/spider/mysql-test/spider/regression/e1121/my_1_1.cnf b/storage/spider/mysql-test/spider/regression/e1121/my_1_1.cnf
new file mode 100644
index 00000000000..5f17295d895
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/my_1_1.cnf
@@ -0,0 +1,44 @@
+[mysqld.1.1]
+log-bin= master-bin
+loose_handlersocket_port= 20000
+loose_handlersocket_port_wr= 20001
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+loose_partition= 1
+
+[ENV]
+USE_GEOMETRY_TEST= 1
+USE_FULLTEXT_TEST= 1
+USE_HA_TEST= 1
+USE_GENERAL_LOG= 1
+USE_REPLICATION= 1
+MASTER_1_MYPORT= @mysqld.1.1.port
+MASTER_1_HSRPORT= 20000
+MASTER_1_HSWPORT= 20001
+MASTER_1_MYSOCK= @mysqld.1.1.socket
+MASTER_1_ENGINE_TYPE= Spider
+#MASTER_1_ENGINE_TYPE= MyISAM
+MASTER_1_ENGINE= ENGINE=Spider
+MASTER_1_CHARSET= DEFAULT CHARSET=utf8
+MASTER_1_ENGINE2= ENGINE=MyISAM
+MASTER_1_CHARSET2= DEFAULT CHARSET=utf8
+MASTER_1_CHARSET3= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
+
+STR_SEMICOLON= ;
+
+#The followings are set in include/init_xxx.inc files
+# MASTER_1_COMMENT_2_1
+# MASTER_1_COMMENT2_2_1
+# MASTER_1_COMMENT3_2_1
+# MASTER_1_COMMENT4_2_1
+# MASTER_1_COMMENT5_2_1
+# MASTER_1_COMMENT_P_2_1
diff --git a/storage/spider/mysql-test/spider/regression/e1121/my_2_1.cnf b/storage/spider/mysql-test/spider/regression/e1121/my_2_1.cnf
new file mode 100644
index 00000000000..24161645607
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/my_2_1.cnf
@@ -0,0 +1,56 @@
+[mysqld.2.1]
+loose_handlersocket_port= 20002
+loose_handlersocket_port_wr= 20003
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+
+[ENV]
+USE_CHILD_GROUP2= 1
+OUTPUT_CHILD_GROUP2= 0
+CHILD2_1_MYPORT= @mysqld.2.1.port
+CHILD2_1_HSRPORT= 20002
+CHILD2_1_HSWPORT= 20003
+CHILD2_1_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_ENGINE_TYPE= InnoDB
+CHILD2_1_ENGINE= ENGINE=InnoDB
+CHILD2_1_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_1_CHARSET2= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
+CHILD2_1_FT_MYPORT= @mysqld.2.1.port
+CHILD2_1_FT_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_FT_ENGINE_TYPE= MyISAM
+CHILD2_1_FT_ENGINE= ENGINE=MyISAM
+CHILD2_1_FT_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_1_GM_MYPORT= @mysqld.2.1.port
+CHILD2_1_GM_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_GM_ENGINE_TYPE= MyISAM
+CHILD2_1_GM_ENGINE= ENGINE=MyISAM
+CHILD2_1_GM_CHARSET= DEFAULT CHARSET=utf8
+
+#The followings are set in include/init_xxx.inc files
+# CHILD2_1_DROP_TABLES
+# CHILD2_1_CREATE_TABLES
+# CHILD2_1_SELECT_TABLES
+# CHILD2_1_DROP_TABLES2
+# CHILD2_1_CREATE_TABLES2
+# CHILD2_1_SELECT_TABLES2
+# CHILD2_1_DROP_TABLES3
+# CHILD2_1_CREATE_TABLES3
+# CHILD2_1_SELECT_TABLES3
+# CHILD2_1_DROP_TABLES4
+# CHILD2_1_CREATE_TABLES4
+# CHILD2_1_SELECT_TABLES4
+# CHILD2_1_DROP_TABLES5
+# CHILD2_1_CREATE_TABLES5
+# CHILD2_1_SELECT_TABLES5
+# CHILD2_1_DROP_TABLES6
+# CHILD2_1_CREATE_TABLES6
+# CHILD2_1_SELECT_TABLES6
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result b/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result
new file mode 100644
index 00000000000..4b04b71aee2
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_key.result
@@ -0,0 +1,94 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18995
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+akey int NOT NULL,
+val int NOT NULL,
+KEY idx1 (akey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+CREATE TABLE tbl_b (
+bkey int NOT NULL,
+akey int NOT NULL,
+PRIMARY KEY (bkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1_2
+INSERT INTO tbl_a (akey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_b (bkey,akey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,4),(6,3),(7,2),(8,1),(9,0);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT a.val, a.akey FROM tbl_a a, tbl_b b WHERE a.akey = b.akey AND b.bkey = 5;
+val akey
+4 4
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%';
+argument
+select t0.`val` `val`,t0.`akey` `akey` from `auto_test_remote`.`tbl_a` t0 where (t0.`akey` = '4')
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%'
+argument
+select `bkey`,`akey` from `auto_test_remote`.`tbl_b` where `bkey` = 5
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%'
+SELECT akey, val FROM tbl_a ORDER BY akey ;
+SELECT bkey, akey FROM tbl_b ORDER BY bkey;
+akey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+bkey akey
+0 0
+1 1
+2 2
+3 3
+4 4
+5 4
+6 3
+7 2
+8 1
+9 0
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_pkey.result b/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_pkey.result
new file mode 100644
index 00000000000..9a75cc691fe
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/direct_join_by_pkey_pkey.result
@@ -0,0 +1,94 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18995
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+akey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (akey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+CREATE TABLE tbl_b (
+bkey int NOT NULL,
+akey int NOT NULL,
+PRIMARY KEY (bkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1_2
+INSERT INTO tbl_a (akey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_b (bkey,akey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,4),(6,3),(7,2),(8,1),(9,0);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT a.val, a.akey FROM tbl_a a, tbl_b b WHERE a.akey = b.akey AND b.bkey = 5;
+val akey
+4 4
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%';
+argument
+select `akey`,`val` from `auto_test_remote`.`tbl_a` where `akey` = 4
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%'
+argument
+select `bkey`,`akey` from `auto_test_remote`.`tbl_b` where `bkey` = 5
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%' ;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_b`%'
+SELECT akey, val FROM tbl_a ORDER BY akey ;
+SELECT bkey, akey FROM tbl_b ORDER BY bkey;
+akey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+bkey akey
+0 0
+1 1
+2 2
+3 3
+4 4
+5 4
+6 3
+7 2
+8 1
+9 0
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi0.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi0.result
new file mode 100644
index 00000000000..2244b176b31
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi0.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi1.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi1.result
new file mode 100644
index 00000000000..6d0d29cd4bd
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ddi1.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi0.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi0.result
new file mode 100644
index 00000000000..1bdd1470faa
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi0.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+Warnings:
+Warning 1062 Duplicate entry '0' for key 'PRIMARY'
+Warning 1062 Duplicate entry '1' for key 'PRIMARY'
+Warning 1062 Duplicate entry '2' for key 'PRIMARY'
+Warning 1062 Duplicate entry '3' for key 'PRIMARY'
+Warning 1062 Duplicate entry '4' for key 'PRIMARY'
+Warning 1062 Duplicate entry '5' for key 'PRIMARY'
+Warning 1062 Duplicate entry '6' for key 'PRIMARY'
+Warning 1062 Duplicate entry '7' for key 'PRIMARY'
+Warning 1062 Duplicate entry '8' for key 'PRIMARY'
+Warning 1062 Duplicate entry '9' for key 'PRIMARY'
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(2,2)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(4,4)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(6,6)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(8,8)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 9
+9 10
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi1.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi1.result
new file mode 100644
index 00000000000..4d64840e85d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_ignore_ddi1.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 9
+9 10
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi0.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi0.result
new file mode 100644
index 00000000000..9156c838e09
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi0.result
@@ -0,0 +1,84 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(2,2)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(4,4)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(6,6)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(8,8)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi1.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi1.result
new file mode 100644
index 00000000000..761ce71dc02
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ddi1.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi0.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi0.result
new file mode 100644
index 00000000000..81d0fdbf785
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi0.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+Warnings:
+Warning 1062 Duplicate entry '0' for key 'PRIMARY'
+Warning 1062 Duplicate entry '1' for key 'PRIMARY'
+Warning 1062 Duplicate entry '2' for key 'PRIMARY'
+Warning 1062 Duplicate entry '3' for key 'PRIMARY'
+Warning 1062 Duplicate entry '4' for key 'PRIMARY'
+Warning 1062 Duplicate entry '5' for key 'PRIMARY'
+Warning 1062 Duplicate entry '6' for key 'PRIMARY'
+Warning 1062 Duplicate entry '7' for key 'PRIMARY'
+Warning 1062 Duplicate entry '8' for key 'PRIMARY'
+Warning 1062 Duplicate entry '9' for key 'PRIMARY'
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(2,2)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(4,4)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(6,6)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(8,8)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 9
+9 10
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi1.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi1.result
new file mode 100644
index 00000000000..737cccc42cb
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_ignore_ddi1.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+1 2
+2 3
+3 4
+4 5
+5 6
+6 7
+7 8
+8 9
+9 10
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi0.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi0.result
new file mode 100644
index 00000000000..7d8fb034544
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi0.result
@@ -0,0 +1,104 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 0 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 0,`val` = 0 where `pkey` = 0 and `val` = 1 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 1,`val` = 1 where `pkey` = 1 and `val` = 2 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(2,2)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 2 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 2,`val` = 2 where `pkey` = 2 and `val` = 3 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 3 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 3,`val` = 3 where `pkey` = 3 and `val` = 4 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(4,4)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 4 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 4,`val` = 4 where `pkey` = 4 and `val` = 5 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 5 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 5,`val` = 5 where `pkey` = 5 and `val` = 6 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(6,6)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 6 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 6,`val` = 6 where `pkey` = 6 and `val` = 7 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 7 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 7,`val` = 7 where `pkey` = 7 and `val` = 8 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(8,8)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 8 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 8,`val` = 8 where `pkey` = 8 and `val` = 9 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 9 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 9,`val` = 9 where `pkey` = 9 and `val` = 10 limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi1.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi1.result
new file mode 100644
index 00000000000..f3e272c1cd1
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_local_replace_ddi1.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+replace into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi0.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi0.result
new file mode 100644
index 00000000000..3ce058a9fc8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi0.result
@@ -0,0 +1,104 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 0 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 0,`val` = 0 where `pkey` = 0 and `val` = 1 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 1,`val` = 1 where `pkey` = 1 and `val` = 2 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(2,2)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 2 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 2,`val` = 2 where `pkey` = 2 and `val` = 3 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 3 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 3,`val` = 3 where `pkey` = 3 and `val` = 4 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(4,4)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 4 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 4,`val` = 4 where `pkey` = 4 and `val` = 5 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 5 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 5,`val` = 5 where `pkey` = 5 and `val` = 6 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(6,6)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 6 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 6,`val` = 6 where `pkey` = 6 and `val` = 7 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 7 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 7,`val` = 7 where `pkey` = 7 and `val` = 8 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(8,8)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 8 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 8,`val` = 8 where `pkey` = 8 and `val` = 9 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 9 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 9,`val` = 9 where `pkey` = 9 and `val` = 10 limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi1.result b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi1.result
new file mode 100644
index 00000000000..86124b9c5c6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/r/load_data_replace_ddi1.result
@@ -0,0 +1,75 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+replace into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/suite.opt b/storage/spider/mysql-test/spider/regression/e1121/suite.opt
new file mode 100644
index 00000000000..672a3b37d4f
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/suite.opt
@@ -0,0 +1 @@
+--loose-innodb --loose-skip-performance-schema
diff --git a/storage/spider/mysql-test/spider/regression/e1121/suite.pm b/storage/spider/mysql-test/spider/regression/e1121/suite.pm
new file mode 100644
index 00000000000..f106147deb6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/suite.pm
@@ -0,0 +1,12 @@
+package My::Suite::Spider;
+
+@ISA = qw(My::Suite);
+
+return "No Spider engine" unless $ENV{HA_SPIDER_SO};
+return "Not run for embedded server" if $::opt_embedded_server;
+return "Test needs --big-test" unless $::opt_big_test;
+
+sub is_default { 1 }
+
+bless { };
+
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_key.test b/storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_key.test
new file mode 100644
index 00000000000..e915a21fd4a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_key.test
@@ -0,0 +1,82 @@
+--source ../include/direct_join_by_pkey_key_init.inc
+--echo
+--echo this test is for MDEV-18995
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ akey int NOT NULL,
+ val int NOT NULL,
+ KEY idx1 (akey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ akey int NOT NULL,
+ val int NOT NULL,
+ KEY idx1 (akey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+echo CREATE TABLE tbl_b (
+ bkey int NOT NULL,
+ akey int NOT NULL,
+ PRIMARY KEY (bkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1_2;
+eval CREATE TABLE tbl_b (
+ bkey int NOT NULL,
+ akey int NOT NULL,
+ PRIMARY KEY (bkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1_2;
+--enable_query_log
+INSERT INTO tbl_a (akey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_b (bkey,akey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,4),(6,3),(7,2),(8,1),(9,0);
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SELECT a.val, a.akey FROM tbl_a a, tbl_b b WHERE a.akey = b.akey AND b.bkey = 5;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/direct_join_by_pkey_key_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_pkey.test b/storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_pkey.test
new file mode 100644
index 00000000000..dcd6e3a4535
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/direct_join_by_pkey_pkey.test
@@ -0,0 +1,82 @@
+--source ../include/direct_join_by_pkey_pkey_init.inc
+--echo
+--echo this test is for MDEV-18995
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ akey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (akey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ akey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (akey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+echo CREATE TABLE tbl_b (
+ bkey int NOT NULL,
+ akey int NOT NULL,
+ PRIMARY KEY (bkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1_2;
+eval CREATE TABLE tbl_b (
+ bkey int NOT NULL,
+ akey int NOT NULL,
+ PRIMARY KEY (bkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1_2;
+--enable_query_log
+INSERT INTO tbl_a (akey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_b (bkey,akey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,4),(6,3),(7,2),(8,1),(9,0);
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SELECT a.val, a.akey FROM tbl_a a, tbl_b b WHERE a.akey = b.akey AND b.bkey = 5;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/direct_join_by_pkey_pkey_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data.inc b/storage/spider/mysql-test/spider/regression/e1121/t/load_data.inc
new file mode 100644
index 00000000000..8c1aa4e651f
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data.inc
@@ -0,0 +1,76 @@
+--echo
+--echo this test is for MDEV-18987
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+--disable_query_log
+--echo SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+eval SELECT pkey,val INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+--enable_query_log
+eval $COMMAND_BEFORE_LOAD_DATA;
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+--echo LOAD DATA $OPTION_LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' $OPTION_WORD INTO TABLE tbl_a;
+eval LOAD DATA $OPTION_LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' $OPTION_WORD INTO TABLE tbl_a;
+--enable_query_log
+--remove_file $MYSQLTEST_VARDIR/tmp/spider_outfile.tsv
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi0.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi0.test
new file mode 100644
index 00000000000..d43a944d5e1
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL=
+--let OPTION_WORD=
+--source load_data.inc
+--source ../include/load_data_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi1.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi1.test
new file mode 100644
index 00000000000..a73d1ef03b2
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL=
+--let OPTION_WORD=
+--source load_data.inc
+--source ../include/load_data_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi0.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi0.test
new file mode 100644
index 00000000000..6fee83e7b43
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= IGNORE
+--source load_data.inc
+--source ../include/load_data_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi1.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi1.test
new file mode 100644
index 00000000000..1c8827911b2
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_ignore_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= IGNORE
+--source load_data.inc
+--source ../include/load_data_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi0.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi0.test
new file mode 100644
index 00000000000..dadd02245ba
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD=
+--source load_data.inc
+--source ../include/load_data_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi1.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi1.test
new file mode 100644
index 00000000000..95b065050b5
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD=
+--source load_data.inc
+--source ../include/load_data_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi0.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi0.test
new file mode 100644
index 00000000000..2243f8924a8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= IGNORE
+--source load_data.inc
+--source ../include/load_data_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi1.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi1.test
new file mode 100644
index 00000000000..2ab7307e3af
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_ignore_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= IGNORE
+--source load_data.inc
+--source ../include/load_data_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi0.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi0.test
new file mode 100644
index 00000000000..1821a9ef730
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= REPLACE
+--source load_data.inc
+--source ../include/load_data_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi1.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi1.test
new file mode 100644
index 00000000000..3d53feca372
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_local_replace_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= REPLACE
+--source load_data.inc
+--source ../include/load_data_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi0.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi0.test
new file mode 100644
index 00000000000..4bc402a40f1
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= REPLACE
+--source load_data.inc
+--source ../include/load_data_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi1.test b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi1.test
new file mode 100644
index 00000000000..9dafd24a15e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e1121/t/load_data_replace_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= REPLACE
+--source load_data.inc
+--source ../include/load_data_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_deinit.inc b/storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_deinit.inc
new file mode 100644
index 00000000000..2248eef3650
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_deinit.inc
@@ -0,0 +1,14 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP
+--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP
+--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_init.inc b/storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_init.inc
new file mode 100644
index 00000000000..a6945218fab
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/group_by_order_by_limit_ok_init.inc
@@ -0,0 +1,54 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_init.inc
+if (!$HAVE_PARTITION)
+{
+ --source group_by_order_by_limit_ok_deinit.inc
+ --enable_result_log
+ --enable_query_log
+ --enable_warnings
+ skip Test requires partitioning;
+}
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a"'
+ PARTITION BY KEY(skey) (
+ PARTITION pt1 COMMENT='srv "s_2_1"',
+ PARTITION pt2 COMMENT='srv "s_2_2"'
+ );
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ KEY idx1 (pkey),
+ KEY idx2 (skey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES
+let $CHILD2_2_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES
+let $CHILD2_2_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ KEY idx1 (pkey),
+ KEY idx2 (skey)
+ ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
+--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES
+let $CHILD2_2_SELECT_TABLES=
+ SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+let $CHILD2_2_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_deinit.inc b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_deinit.inc
new file mode 100644
index 00000000000..c41917340b0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_deinit.inc
@@ -0,0 +1,3 @@
+--connection master_1
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+--source load_data_part_deinit.inc
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_init.inc b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_init.inc
new file mode 100644
index 00000000000..8e69f52cc58
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi0_init.inc
@@ -0,0 +1,4 @@
+--source load_data_part_init.inc
+--connection master_1
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_deinit.inc b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_deinit.inc
new file mode 100644
index 00000000000..c41917340b0
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_deinit.inc
@@ -0,0 +1,3 @@
+--connection master_1
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+--source load_data_part_deinit.inc
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_init.inc b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_init.inc
new file mode 100644
index 00000000000..b9194ccd51c
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_ddi1_init.inc
@@ -0,0 +1,4 @@
+--source load_data_part_init.inc
+--connection master_1
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_deinit.inc b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_deinit.inc
new file mode 100644
index 00000000000..2248eef3650
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_deinit.inc
@@ -0,0 +1,14 @@
+--let $MASTER_1_COMMENT_2_1= $MASTER_1_COMMENT_2_1_BACKUP
+--let $CHILD2_1_DROP_TABLES= $CHILD2_1_DROP_TABLES_BACKUP
+--let $CHILD2_1_CREATE_TABLES= $CHILD2_1_CREATE_TABLES_BACKUP
+--let $CHILD2_1_SELECT_TABLES= $CHILD2_1_SELECT_TABLES_BACKUP
+--let $CHILD2_2_DROP_TABLES= $CHILD2_2_DROP_TABLES_BACKUP
+--let $CHILD2_2_CREATE_TABLES= $CHILD2_2_CREATE_TABLES_BACKUP
+--let $CHILD2_2_SELECT_TABLES= $CHILD2_2_SELECT_TABLES_BACKUP
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_deinit.inc
+--enable_result_log
+--enable_query_log
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_init.inc b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_init.inc
new file mode 100644
index 00000000000..42a0ea72539
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/include/load_data_part_init.inc
@@ -0,0 +1,52 @@
+--disable_warnings
+--disable_query_log
+--disable_result_log
+--source ../../t/test_init.inc
+if (!$HAVE_PARTITION)
+{
+ --source load_data_part_deinit.inc
+ --enable_result_log
+ --enable_query_log
+ --enable_warnings
+ skip Test requires partitioning;
+}
+--enable_result_log
+--enable_query_log
+--enable_warnings
+--let $MASTER_1_COMMENT_2_1_BACKUP= $MASTER_1_COMMENT_2_1
+let $MASTER_1_COMMENT_2_1=
+ COMMENT='table "tbl_a"'
+ PARTITION BY KEY(pkey) (
+ PARTITION pt1 COMMENT='srv "s_2_1"',
+ PARTITION pt2 COMMENT='srv "s_2_2"'
+ );
+--let $CHILD2_1_DROP_TABLES_BACKUP= $CHILD2_1_DROP_TABLES
+let $CHILD2_1_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_1_CREATE_TABLES_BACKUP= $CHILD2_1_CREATE_TABLES
+let $CHILD2_1_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_1_ENGINE $CHILD2_1_CHARSET;
+--let $CHILD2_1_SELECT_TABLES_BACKUP= $CHILD2_1_SELECT_TABLES
+let $CHILD2_1_SELECT_TABLES=
+ SELECT pkey, val FROM tbl_a ORDER BY pkey;
+let $CHILD2_1_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+--let $CHILD2_2_DROP_TABLES_BACKUP= $CHILD2_2_DROP_TABLES
+let $CHILD2_2_DROP_TABLES=
+ DROP TABLE IF EXISTS tbl_a;
+--let $CHILD2_2_CREATE_TABLES_BACKUP= $CHILD2_2_CREATE_TABLES
+let $CHILD2_2_CREATE_TABLES=
+ CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+ ) $CHILD2_2_ENGINE $CHILD2_2_CHARSET;
+--let $CHILD2_2_SELECT_TABLES_BACKUP= $CHILD2_2_SELECT_TABLES
+let $CHILD2_2_SELECT_TABLES=
+ SELECT pkey, val FROM tbl_a ORDER BY pkey;
+let $CHILD2_2_SELECT_ARGUMENT1=
+ SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
diff --git a/storage/spider/mysql-test/spider/regression/e112122/my.cnf b/storage/spider/mysql-test/spider/regression/e112122/my.cnf
new file mode 100644
index 00000000000..6610e4cfd98
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/my.cnf
@@ -0,0 +1,4 @@
+!include include/default_mysqld.cnf
+!include my_1_1.cnf
+!include my_2_1.cnf
+!include my_2_2.cnf
diff --git a/storage/spider/mysql-test/spider/regression/e112122/my_1_1.cnf b/storage/spider/mysql-test/spider/regression/e112122/my_1_1.cnf
new file mode 100644
index 00000000000..5f17295d895
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/my_1_1.cnf
@@ -0,0 +1,44 @@
+[mysqld.1.1]
+log-bin= master-bin
+loose_handlersocket_port= 20000
+loose_handlersocket_port_wr= 20001
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+loose_partition= 1
+
+[ENV]
+USE_GEOMETRY_TEST= 1
+USE_FULLTEXT_TEST= 1
+USE_HA_TEST= 1
+USE_GENERAL_LOG= 1
+USE_REPLICATION= 1
+MASTER_1_MYPORT= @mysqld.1.1.port
+MASTER_1_HSRPORT= 20000
+MASTER_1_HSWPORT= 20001
+MASTER_1_MYSOCK= @mysqld.1.1.socket
+MASTER_1_ENGINE_TYPE= Spider
+#MASTER_1_ENGINE_TYPE= MyISAM
+MASTER_1_ENGINE= ENGINE=Spider
+MASTER_1_CHARSET= DEFAULT CHARSET=utf8
+MASTER_1_ENGINE2= ENGINE=MyISAM
+MASTER_1_CHARSET2= DEFAULT CHARSET=utf8
+MASTER_1_CHARSET3= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
+
+STR_SEMICOLON= ;
+
+#The followings are set in include/init_xxx.inc files
+# MASTER_1_COMMENT_2_1
+# MASTER_1_COMMENT2_2_1
+# MASTER_1_COMMENT3_2_1
+# MASTER_1_COMMENT4_2_1
+# MASTER_1_COMMENT5_2_1
+# MASTER_1_COMMENT_P_2_1
diff --git a/storage/spider/mysql-test/spider/regression/e112122/my_2_1.cnf b/storage/spider/mysql-test/spider/regression/e112122/my_2_1.cnf
new file mode 100644
index 00000000000..24161645607
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/my_2_1.cnf
@@ -0,0 +1,56 @@
+[mysqld.2.1]
+loose_handlersocket_port= 20002
+loose_handlersocket_port_wr= 20003
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+
+[ENV]
+USE_CHILD_GROUP2= 1
+OUTPUT_CHILD_GROUP2= 0
+CHILD2_1_MYPORT= @mysqld.2.1.port
+CHILD2_1_HSRPORT= 20002
+CHILD2_1_HSWPORT= 20003
+CHILD2_1_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_ENGINE_TYPE= InnoDB
+CHILD2_1_ENGINE= ENGINE=InnoDB
+CHILD2_1_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_1_CHARSET2= DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
+CHILD2_1_FT_MYPORT= @mysqld.2.1.port
+CHILD2_1_FT_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_FT_ENGINE_TYPE= MyISAM
+CHILD2_1_FT_ENGINE= ENGINE=MyISAM
+CHILD2_1_FT_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_1_GM_MYPORT= @mysqld.2.1.port
+CHILD2_1_GM_MYSOCK= @mysqld.2.1.socket
+CHILD2_1_GM_ENGINE_TYPE= MyISAM
+CHILD2_1_GM_ENGINE= ENGINE=MyISAM
+CHILD2_1_GM_CHARSET= DEFAULT CHARSET=utf8
+
+#The followings are set in include/init_xxx.inc files
+# CHILD2_1_DROP_TABLES
+# CHILD2_1_CREATE_TABLES
+# CHILD2_1_SELECT_TABLES
+# CHILD2_1_DROP_TABLES2
+# CHILD2_1_CREATE_TABLES2
+# CHILD2_1_SELECT_TABLES2
+# CHILD2_1_DROP_TABLES3
+# CHILD2_1_CREATE_TABLES3
+# CHILD2_1_SELECT_TABLES3
+# CHILD2_1_DROP_TABLES4
+# CHILD2_1_CREATE_TABLES4
+# CHILD2_1_SELECT_TABLES4
+# CHILD2_1_DROP_TABLES5
+# CHILD2_1_CREATE_TABLES5
+# CHILD2_1_SELECT_TABLES5
+# CHILD2_1_DROP_TABLES6
+# CHILD2_1_CREATE_TABLES6
+# CHILD2_1_SELECT_TABLES6
diff --git a/storage/spider/mysql-test/spider/regression/e112122/my_2_2.cnf b/storage/spider/mysql-test/spider/regression/e112122/my_2_2.cnf
new file mode 100644
index 00000000000..2d3c2a89a7d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/my_2_2.cnf
@@ -0,0 +1,38 @@
+[mysqld.2.2]
+loose_handlersocket_port= 20004
+loose_handlersocket_port_wr= 20005
+loose_handlersocket_threads= 2
+loose_handlersocket_threads_wr= 1
+loose_handlersocket_support_merge_table= 0
+loose_handlersocket_direct_update_mode= 2
+loose_handlersocket_unlimited_boundary= 65536
+loose_handlersocket_bulk_insert= 0
+loose_handlersocket_bulk_insert_timeout= 0
+loose_handlersocket_general_log= 1
+loose_handlersocket_timeout= 30
+loose_handlersocket_close_table_interval=2
+open_files_limit= 4096
+
+[ENV]
+CHILD2_2_MYPORT= @mysqld.2.2.port
+CHILD2_2_HSRPORT= 20004
+CHILD2_2_HSWPORT= 20005
+CHILD2_2_MYSOCK= @mysqld.2.2.socket
+CHILD2_2_ENGINE_TYPE= InnoDB
+CHILD2_2_ENGINE= ENGINE=InnoDB
+CHILD2_2_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_2_FT_MYPORT= @mysqld.2.2.port
+CHILD2_2_FT_MYSOCK= @mysqld.2.2.socket
+CHILD2_2_FT_ENGINE_TYPE= MyISAM
+CHILD2_2_FT_ENGINE= ENGINE=MyISAM
+CHILD2_2_FT_CHARSET= DEFAULT CHARSET=utf8
+CHILD2_2_GM_MYPORT= @mysqld.2.2.port
+CHILD2_2_GM_MYSOCK= @mysqld.2.2.socket
+CHILD2_2_GM_ENGINE_TYPE= MyISAM
+CHILD2_2_GM_ENGINE= ENGINE=MyISAM
+CHILD2_2_GM_CHARSET= DEFAULT CHARSET=utf8
+
+#The followings are set in include/init_xxx.inc files
+# CHILD2_2_DROP_TABLES
+# CHILD2_2_CREATE_TABLES
+# CHILD2_2_SELECT_TABLES
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/group_by_order_by_limit_ok.result b/storage/spider/mysql-test/spider/regression/e112122/r/group_by_order_by_limit_ok.result
new file mode 100644
index 00000000000..96746e09b8d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/group_by_order_by_limit_ok.result
@@ -0,0 +1,117 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+this test is for MDEV-18988
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+skey int NOT NULL,
+KEY idx1 (pkey),
+KEY idx2 (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19);
+INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14);
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+SELECT skey, count(*) cnt FROM tbl_a GROUP BY skey ORDER BY cnt DESC, skey DESC LIMIT 5;
+skey cnt
+14 2
+13 2
+12 2
+11 2
+10 2
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select count(0),`skey` from `auto_test_remote`.`tbl_a` group by `skey` order by count(0) desc,`skey` desc limit 5
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+pkey skey
+1 1
+3 3
+5 5
+7 7
+9 9
+11 11
+13 13
+15 15
+17 17
+19 19
+20 5
+22 7
+24 9
+26 11
+28 13
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
+argument
+select count(0),`skey` from `auto_test_remote2`.`tbl_a` group by `skey` order by count(0) desc,`skey` desc limit 5
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
+SELECT pkey, skey FROM tbl_a ORDER BY pkey;
+pkey skey
+0 0
+2 2
+4 4
+6 6
+8 8
+10 10
+12 12
+14 14
+16 16
+18 18
+21 6
+23 8
+25 10
+27 12
+29 14
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi0.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi0.result
new file mode 100644
index 00000000000..23753239054
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi0.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi1.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi1.result
new file mode 100644
index 00000000000..c30a5c037a7
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ddi1.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi0.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi0.result
new file mode 100644
index 00000000000..0071042cd58
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi0.result
@@ -0,0 +1,114 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+Warnings:
+Warning 1062 Duplicate entry '0' for key 'PRIMARY'
+Warning 1062 Duplicate entry '1' for key 'PRIMARY'
+Warning 1062 Duplicate entry '2' for key 'PRIMARY'
+Warning 1062 Duplicate entry '3' for key 'PRIMARY'
+Warning 1062 Duplicate entry '4' for key 'PRIMARY'
+Warning 1062 Duplicate entry '5' for key 'PRIMARY'
+Warning 1062 Duplicate entry '6' for key 'PRIMARY'
+Warning 1062 Duplicate entry '7' for key 'PRIMARY'
+Warning 1062 Duplicate entry '8' for key 'PRIMARY'
+Warning 1062 Duplicate entry '9' for key 'PRIMARY'
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 2
+3 4
+5 6
+7 8
+9 10
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(2,2)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(4,4)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(6,6)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+2 3
+4 5
+6 7
+8 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi1.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi1.result
new file mode 100644
index 00000000000..9f2e8dec535
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_ignore_ddi1.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 2
+3 4
+5 6
+7 8
+9 10
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+2 3
+4 5
+6 7
+8 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi0.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi0.result
new file mode 100644
index 00000000000..7ec2b5b0b9e
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi0.result
@@ -0,0 +1,103 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(2,2)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(4,4)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(6,6)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi1.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi1.result
new file mode 100644
index 00000000000..f908ce1c1d5
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ddi1.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+TRUNCATE tbl_a;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi0.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi0.result
new file mode 100644
index 00000000000..c0a8f653fee
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi0.result
@@ -0,0 +1,114 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+Warnings:
+Warning 1062 Duplicate entry '0' for key 'PRIMARY'
+Warning 1062 Duplicate entry '1' for key 'PRIMARY'
+Warning 1062 Duplicate entry '2' for key 'PRIMARY'
+Warning 1062 Duplicate entry '3' for key 'PRIMARY'
+Warning 1062 Duplicate entry '4' for key 'PRIMARY'
+Warning 1062 Duplicate entry '5' for key 'PRIMARY'
+Warning 1062 Duplicate entry '6' for key 'PRIMARY'
+Warning 1062 Duplicate entry '7' for key 'PRIMARY'
+Warning 1062 Duplicate entry '8' for key 'PRIMARY'
+Warning 1062 Duplicate entry '9' for key 'PRIMARY'
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+insert high_priority into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 2
+3 4
+5 6
+7 8
+9 10
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(2,2)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(4,4)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(6,6)
+insert high_priority into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+2 3
+4 5
+6 7
+8 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi1.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi1.result
new file mode 100644
index 00000000000..619dd789d9a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_ignore_ddi1.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' IGNORE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 2
+3 4
+5 6
+7 8
+9 10
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert high_priority ignore into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 1
+2 3
+4 5
+6 7
+8 9
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi0.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi0.result
new file mode 100644
index 00000000000..e12e380bb93
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi0.result
@@ -0,0 +1,123 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 1,`val` = 1 where `pkey` = 1 and `val` = 2 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 3 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 3,`val` = 3 where `pkey` = 3 and `val` = 4 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 5 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 5,`val` = 5 where `pkey` = 5 and `val` = 6 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 7 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 7,`val` = 7 where `pkey` = 7 and `val` = 8 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 9 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 9,`val` = 9 where `pkey` = 9 and `val` = 10 limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 0 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 0,`val` = 0 where `pkey` = 0 and `val` = 1 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(2,2)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 2 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 2,`val` = 2 where `pkey` = 2 and `val` = 3 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(4,4)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 4 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 4,`val` = 4 where `pkey` = 4 and `val` = 5 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(6,6)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 6 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 6,`val` = 6 where `pkey` = 6 and `val` = 7 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(8,8)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 8 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 8,`val` = 8 where `pkey` = 8 and `val` = 9 limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi1.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi1.result
new file mode 100644
index 00000000000..d367cbfd0ad
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_local_replace_ddi1.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+replace into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+replace into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi0.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi0.result
new file mode 100644
index 00000000000..039a8dd4fad
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi0.result
@@ -0,0 +1,123 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 0;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 1 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 1,`val` = 1 where `pkey` = 1 and `val` = 2 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(3,3)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 3 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 3,`val` = 3 where `pkey` = 3 and `val` = 4 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(5,5)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 5 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 5,`val` = 5 where `pkey` = 5 and `val` = 6 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(7,7)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 7 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 7,`val` = 7 where `pkey` = 7 and `val` = 8 limit 1
+insert into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(9,9)
+select `pkey`,`val` from `auto_test_remote`.`tbl_a` where `pkey` = 9 for update
+update ignore `auto_test_remote`.`tbl_a` set `pkey` = 9,`val` = 9 where `pkey` = 9 and `val` = 10 limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 0 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 0,`val` = 0 where `pkey` = 0 and `val` = 1 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(2,2)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 2 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 2,`val` = 2 where `pkey` = 2 and `val` = 3 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(4,4)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 4 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 4,`val` = 4 where `pkey` = 4 and `val` = 5 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(6,6)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 6 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 6,`val` = 6 where `pkey` = 6 and `val` = 7 limit 1
+insert into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(8,8)
+select `pkey`,`val` from `auto_test_remote2`.`tbl_a` where `pkey` = 8 for update
+update ignore `auto_test_remote2`.`tbl_a` set `pkey` = 8,`val` = 8 where `pkey` = 8 and `val` = 9 limit 1
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi1.result b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi1.result
new file mode 100644
index 00000000000..c8155be9910
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/r/load_data_part_replace_ddi1.result
@@ -0,0 +1,95 @@
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+connection master_1;
+set @old_spider_direct_dup_insert= @@spider_direct_dup_insert;
+set session spider_direct_dup_insert= 1;
+
+this test is for MDEV-18987
+
+drop and create databases
+connection master_1;
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+connection child2_1;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+connection child2_2;
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+
+create table and insert
+connection child2_1;
+CHILD2_1_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+CHILD2_2_CREATE_TABLES
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+CREATE TABLE tbl_a (
+pkey int NOT NULL,
+val int NOT NULL,
+PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+UPDATE tbl_a SET val = val + 1;
+
+select test 1
+connection child2_1;
+TRUNCATE TABLE mysql.general_log;
+connection child2_2;
+TRUNCATE TABLE mysql.general_log;
+connection master_1;
+LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' REPLACE INTO TABLE tbl_a;
+connection child2_1;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+replace into `auto_test_remote`.`tbl_a`(`pkey`,`val`)values(1,1),(3,3),(5,5),(7,7),(9,9)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+1 1
+3 3
+5 5
+7 7
+9 9
+connection child2_2;
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%';
+argument
+replace into `auto_test_remote2`.`tbl_a`(`pkey`,`val`)values(0,0),(2,2),(4,4),(6,6),(8,8)
+SELECT argument FROM mysql.general_log WHERE argument LIKE '%`tbl_a`%'
+SELECT pkey, val FROM tbl_a ORDER BY pkey;
+pkey val
+0 0
+2 2
+4 4
+6 6
+8 8
+
+deinit
+connection master_1;
+DROP DATABASE IF EXISTS auto_test_local;
+connection child2_1;
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+connection child2_2;
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+connection master_1;
+set session spider_direct_dup_insert= @old_spider_direct_dup_insert;
+for master_1
+for child2
+child2_1
+child2_2
+child2_3
+for child3
+
+end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/suite.opt b/storage/spider/mysql-test/spider/regression/e112122/suite.opt
new file mode 100644
index 00000000000..672a3b37d4f
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/suite.opt
@@ -0,0 +1 @@
+--loose-innodb --loose-skip-performance-schema
diff --git a/storage/spider/mysql-test/spider/regression/e112122/suite.pm b/storage/spider/mysql-test/spider/regression/e112122/suite.pm
new file mode 100644
index 00000000000..f106147deb6
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/suite.pm
@@ -0,0 +1,12 @@
+package My::Suite::Spider;
+
+@ISA = qw(My::Suite);
+
+return "No Spider engine" unless $ENV{HA_SPIDER_SO};
+return "Not run for embedded server" if $::opt_embedded_server;
+return "Test needs --big-test" unless $::opt_big_test;
+
+sub is_default { 1 }
+
+bless { };
+
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/group_by_order_by_limit_ok.test b/storage/spider/mysql-test/spider/regression/e112122/t/group_by_order_by_limit_ok.test
new file mode 100644
index 00000000000..2a70098ed1b
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/group_by_order_by_limit_ok.test
@@ -0,0 +1,97 @@
+--source ../include/group_by_order_by_limit_ok_init.inc
+--echo
+--echo this test is for MDEV-18988
+--echo
+--echo drop and create databases
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+--connection child2_2
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+--disable_query_log
+echo CHILD2_2_CREATE_TABLES;
+eval $CHILD2_2_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ KEY idx1 (pkey),
+ KEY idx2 (skey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ skey int NOT NULL,
+ KEY idx1 (pkey),
+ KEY idx2 (skey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,skey) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+INSERT INTO tbl_a (pkey,skey) VALUES (10,10),(11,11),(12,12),(13,13),(14,14),(15,15),(16,16),(17,17),(18,18),(19,19);
+INSERT INTO tbl_a (pkey,skey) VALUES (20,5),(21,6),(22,7),(23,8),(24,9),(25,10),(26,11),(27,12),(28,13),(29,14);
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+SELECT skey, count(*) cnt FROM tbl_a GROUP BY skey ORDER BY cnt DESC, skey DESC LIMIT 5;
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection child2_2
+eval $CHILD2_2_SELECT_ARGUMENT1;
+eval $CHILD2_2_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--connection child2_2
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
+--source ../include/group_by_order_by_limit_ok_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part.inc b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part.inc
new file mode 100644
index 00000000000..e66550f9a90
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part.inc
@@ -0,0 +1,100 @@
+--echo
+--echo this test is for MDEV-18987
+--echo
+--echo drop and create databases
+
+--connection master_1
+--disable_warnings
+CREATE DATABASE auto_test_local;
+USE auto_test_local;
+
+--connection child2_1
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote;
+USE auto_test_remote;
+
+--connection child2_2
+SET @old_log_output = @@global.log_output;
+SET GLOBAL log_output = 'TABLE,FILE';
+CREATE DATABASE auto_test_remote2;
+USE auto_test_remote2;
+--enable_warnings
+
+--echo
+--echo create table and insert
+
+--connection child2_1
+--disable_query_log
+echo CHILD2_1_CREATE_TABLES;
+eval $CHILD2_1_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+--disable_query_log
+echo CHILD2_2_CREATE_TABLES;
+eval $CHILD2_2_CREATE_TABLES;
+--enable_query_log
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+echo CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+) MASTER_1_ENGINE MASTER_1_CHARSET MASTER_1_COMMENT_2_1;
+eval CREATE TABLE tbl_a (
+ pkey int NOT NULL,
+ val int NOT NULL,
+ PRIMARY KEY (pkey)
+) $MASTER_1_ENGINE $MASTER_1_CHARSET $MASTER_1_COMMENT_2_1;
+--enable_query_log
+INSERT INTO tbl_a (pkey,val) VALUES (0,0),(1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+--disable_query_log
+--echo SELECT pkey,val INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+eval SELECT pkey,val INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' FROM tbl_a ORDER BY pkey;
+--enable_query_log
+eval $COMMAND_BEFORE_LOAD_DATA;
+
+--echo
+--echo select test 1
+
+--connection child2_1
+TRUNCATE TABLE mysql.general_log;
+
+--connection child2_2
+TRUNCATE TABLE mysql.general_log;
+
+--connection master_1
+--disable_query_log
+--echo LOAD DATA $OPTION_LOCAL INFILE 'MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' $OPTION_WORD INTO TABLE tbl_a;
+eval LOAD DATA $OPTION_LOCAL INFILE '$MYSQLTEST_VARDIR/tmp/spider_outfile.tsv' $OPTION_WORD INTO TABLE tbl_a;
+--enable_query_log
+--remove_file $MYSQLTEST_VARDIR/tmp/spider_outfile.tsv
+
+--connection child2_1
+eval $CHILD2_1_SELECT_ARGUMENT1;
+eval $CHILD2_1_SELECT_TABLES;
+
+--connection child2_2
+eval $CHILD2_2_SELECT_ARGUMENT1;
+eval $CHILD2_2_SELECT_TABLES;
+
+--echo
+--echo deinit
+--disable_warnings
+
+--connection master_1
+DROP DATABASE IF EXISTS auto_test_local;
+
+--connection child2_1
+DROP DATABASE IF EXISTS auto_test_remote;
+SET GLOBAL log_output = @old_log_output;
+
+--connection child2_2
+DROP DATABASE IF EXISTS auto_test_remote2;
+SET GLOBAL log_output = @old_log_output;
+
+--enable_warnings
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi0.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi0.test
new file mode 100644
index 00000000000..b78529095a4
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL=
+--let OPTION_WORD=
+--source load_data_part.inc
+--source ../include/load_data_part_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi1.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi1.test
new file mode 100644
index 00000000000..a2540077639
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL=
+--let OPTION_WORD=
+--source load_data_part.inc
+--source ../include/load_data_part_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi0.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi0.test
new file mode 100644
index 00000000000..a6fb58d69d1
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= IGNORE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi1.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi1.test
new file mode 100644
index 00000000000..b9f75894c60
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_ignore_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= IGNORE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi0.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi0.test
new file mode 100644
index 00000000000..f44f7ae936d
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD=
+--source load_data_part.inc
+--source ../include/load_data_part_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi1.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi1.test
new file mode 100644
index 00000000000..4c806096ad1
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= TRUNCATE tbl_a
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD=
+--source load_data_part.inc
+--source ../include/load_data_part_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi0.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi0.test
new file mode 100644
index 00000000000..179bab5b4aa
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= IGNORE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi1.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi1.test
new file mode 100644
index 00000000000..cd7d8215b7a
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_ignore_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= IGNORE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi0.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi0.test
new file mode 100644
index 00000000000..5df3f420e09
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= REPLACE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi1.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi1.test
new file mode 100644
index 00000000000..bf3c7c93be8
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_local_replace_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL= LOCAL
+--let OPTION_WORD= REPLACE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi0.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi0.test
new file mode 100644
index 00000000000..910b7e813da
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi0.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi0_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= REPLACE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi0_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi1.test b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi1.test
new file mode 100644
index 00000000000..fc84bf14487
--- /dev/null
+++ b/storage/spider/mysql-test/spider/regression/e112122/t/load_data_part_replace_ddi1.test
@@ -0,0 +1,8 @@
+--source ../include/load_data_part_ddi1_init.inc
+--let COMMAND_BEFORE_LOAD_DATA= UPDATE tbl_a SET val = val + 1
+--let OPTION_LOCAL=
+--let OPTION_WORD= REPLACE
+--source load_data_part.inc
+--source ../include/load_data_part_ddi1_deinit.inc
+--echo
+--echo end of test
diff --git a/storage/spider/mysql-test/spider/t/connect_child2_1.inc b/storage/spider/mysql-test/spider/t/connect_child2_1.inc
index cd9b0c9ca9b..15e26031527 100644
--- a/storage/spider/mysql-test/spider/t/connect_child2_1.inc
+++ b/storage/spider/mysql-test/spider/t/connect_child2_1.inc
@@ -1 +1,2 @@
--connect (child2_1, localhost, root, , , $CHILD2_1_MYPORT, $CHILD2_1_MYSOCK)
+--connect (child2_1_2, localhost, root, , , $CHILD2_1_MYPORT, $CHILD2_1_MYSOCK)
diff --git a/storage/spider/mysql-test/spider/t/connect_child2_2.inc b/storage/spider/mysql-test/spider/t/connect_child2_2.inc
index e145f66b630..75a50821ea7 100644
--- a/storage/spider/mysql-test/spider/t/connect_child2_2.inc
+++ b/storage/spider/mysql-test/spider/t/connect_child2_2.inc
@@ -1 +1,2 @@
--connect (child2_2, localhost, root, , , $CHILD2_2_MYPORT, $CHILD2_2_MYSOCK)
+--connect (child2_2_2, localhost, root, , , $CHILD2_2_MYPORT, $CHILD2_2_MYSOCK)
diff --git a/storage/spider/mysql-test/spider/t/test_deinit.inc b/storage/spider/mysql-test/spider/t/test_deinit.inc
index 989bde26d3c..5a82b43ce0f 100644
--- a/storage/spider/mysql-test/spider/t/test_deinit.inc
+++ b/storage/spider/mysql-test/spider/t/test_deinit.inc
@@ -10,10 +10,12 @@ if ($USE_CHILD_GROUP2)
--connection child2_1
--source ../include/deinit_child2_1.inc
--disconnect child2_1
+ --disconnect child2_1_2
--echo child2_2
--connection child2_2
--source ../include/deinit_child2_2.inc
--disconnect child2_2
+ --disconnect child2_2_2
--echo child2_3
--connection child2_3
--source ../include/deinit_child2_3.inc
diff --git a/storage/spider/scripts/install_spider.sql b/storage/spider/scripts/install_spider.sql
index f52c78e496d..403bd99fd68 100644
--- a/storage/spider/scripts/install_spider.sql
+++ b/storage/spider/scripts/install_spider.sql
@@ -1,4 +1,4 @@
-# Copyright (C) 2010-2018 Kentoku Shiba
+# Copyright (C) 2010-2019 Kentoku Shiba
#
# 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
@@ -13,482 +13,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
-# This SQL script creates system tables for SPIDER
-# or fixes incompatibilities if ones already exist.
-
--- Create system tables if not exist
-create table if not exists mysql.spider_xa(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- status char(8) not null default '',
- primary key (data, format_id, gtrid_length),
- key idx1 (status)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_xa_member(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- scheme char(64) not null default '',
- host char(64) not null default '',
- port char(5) not null default '',
- socket text not null,
- username char(64) not null default '',
- password char(64) not null default '',
- ssl_ca text,
- ssl_capath text,
- ssl_cert text,
- ssl_cipher char(64) default null,
- ssl_key text,
- ssl_verify_server_cert tinyint not null default 0,
- default_file text,
- default_group char(64) default null,
- key idx1 (data, format_id, gtrid_length, host)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_xa_failed_log(
- format_id int not null default 0,
- gtrid_length int not null default 0,
- bqual_length int not null default 0,
- data char(128) charset binary not null default '',
- scheme char(64) not null default '',
- host char(64) not null default '',
- port char(5) not null default '',
- socket text not null,
- username char(64) not null default '',
- password char(64) not null default '',
- ssl_ca text,
- ssl_capath text,
- ssl_cert text,
- ssl_cipher char(64) default null,
- ssl_key text,
- ssl_verify_server_cert tinyint not null default 0,
- default_file text,
- default_group char(64) default null,
- thread_id int default null,
- status char(8) not null default '',
- failed_time timestamp not null default current_timestamp,
- key idx1 (data, format_id, gtrid_length, host)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_tables(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- link_id int not null default 0,
- priority bigint not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket text,
- username char(64) default null,
- password char(64) default null,
- ssl_ca text,
- ssl_capath text,
- ssl_cert text,
- ssl_cipher char(64) default null,
- ssl_key text,
- ssl_verify_server_cert tinyint not null default 0,
- monitoring_binlog_pos_at_failing tinyint not null default 0,
- default_file text,
- default_group char(64) default null,
- tgt_db_name char(64) default null,
- tgt_table_name char(64) default null,
- link_status tinyint not null default 1,
- block_status tinyint not null default 0,
- static_link_id char(64) default null,
- primary key (db_name, table_name, link_id),
- key idx1 (priority),
- unique key uidx1 (db_name, table_name, static_link_id)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_link_mon_servers(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- link_id char(64) not null default '',
- sid int unsigned not null default 0,
- server char(64) default null,
- scheme char(64) default null,
- host char(64) default null,
- port char(5) default null,
- socket text,
- username char(64) default null,
- password char(64) default null,
- ssl_ca text,
- ssl_capath text,
- ssl_cert text,
- ssl_cipher char(64) default null,
- ssl_key text,
- ssl_verify_server_cert tinyint not null default 0,
- default_file text,
- default_group char(64) default null,
- primary key (db_name, table_name, link_id, sid)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_link_failed_log(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- link_id char(64) not null default '',
- failed_time timestamp not null default current_timestamp
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_table_position_for_recovery(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- failed_link_id int not null default 0,
- source_link_id int not null default 0,
- file text,
- position text,
- gtid text,
- primary key (db_name, table_name, failed_link_id, source_link_id)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_table_sts(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- data_file_length bigint unsigned not null default 0,
- max_data_file_length bigint unsigned not null default 0,
- index_file_length bigint unsigned not null default 0,
- records bigint unsigned not null default 0,
- mean_rec_length bigint unsigned not null default 0,
- check_time datetime not null default '0000-00-00 00:00:00',
- create_time datetime not null default '0000-00-00 00:00:00',
- update_time datetime not null default '0000-00-00 00:00:00',
- primary key (db_name, table_name)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-create table if not exists mysql.spider_table_crd(
- db_name char(64) not null default '',
- table_name char(199) not null default '',
- key_seq int unsigned not null default 0,
- cardinality bigint not null default 0,
- primary key (db_name, table_name, key_seq)
-) engine=MyISAM default charset=utf8 collate=utf8_bin;
-
--- If tables already exist and their definition differ from the latest ones,
--- we fix them here.
-drop procedure if exists mysql.spider_fix_one_table;
-drop procedure if exists mysql.spider_fix_system_tables;
-delimiter //
-create procedure mysql.spider_fix_one_table
- (tab_name char(255) charset utf8 collate utf8_bin,
- test_col_name char(255) charset utf8 collate utf8_bin,
- _sql text charset utf8 collate utf8_bin)
-begin
- set @col_exists := 0;
- select 1 into @col_exists from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = tab_name
- AND COLUMN_NAME = test_col_name;
- if @col_exists = 0 then
- select @stmt := _sql;
- prepare sp_stmt1 from @stmt;
- execute sp_stmt1;
- end if;
-end;//
-
-create procedure mysql.spider_fix_system_tables()
-begin
- select substring_index(substring_index(version(), '-', 2), '-', -1)
- into @server_name;
- select substring_index(version(), '.', 1)
- into @server_major_version;
- select substring_index(substring_index(version(), '.', 2), '.', -1)
- into @server_minor_version;
-
- -- Fix for 0.5
- call mysql.spider_fix_one_table('spider_tables', 'server',
- 'alter table mysql.spider_tables
- add server char(64) default null,
- add scheme char(64) default null,
- add host char(64) default null,
- add port char(5) default null,
- add socket char(64) default null,
- add username char(64) default null,
- add password char(64) default null,
- add tgt_db_name char(64) default null,
- add tgt_table_name char(64) default null');
-
- -- Fix for version 0.17
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_xa'
- AND COLUMN_NAME = 'data';
- if @col_type != 'binary(128)' then
- alter table mysql.spider_xa modify data binary(128) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_xa_member'
- AND COLUMN_NAME = 'data';
- if @col_type != 'binary(128)' then
- alter table mysql.spider_xa_member modify data binary(128) not null default '';
- end if;
-
- -- Fix for version 2.7
- call mysql.spider_fix_one_table('spider_tables', 'link_id',
- 'alter table mysql.spider_tables
- add column link_id int not null default 0 after table_name,
- drop primary key,
- add primary key (db_name, table_name, link_id)');
-
- -- Fix for version 2.8
- call mysql.spider_fix_one_table('spider_tables', 'link_status',
- 'alter table mysql.spider_tables
- add column link_status tinyint not null default 1');
-
- -- Fix for version 2.10
- call mysql.spider_fix_one_table('spider_xa_member', 'ssl_ca',
- 'alter table mysql.spider_xa_member
- add column ssl_ca char(64) default null after password,
- add column ssl_capath char(64) default null after ssl_ca,
- add column ssl_cert char(64) default null after ssl_capath,
- add column ssl_cipher char(64) default null after ssl_cert,
- add column ssl_key char(64) default null after ssl_cipher,
- add column ssl_verify_server_cert tinyint not null default 0 after ssl_key,
- add column default_file char(64) default null after ssl_verify_server_cert,
- add column default_group char(64) default null after default_file');
- call mysql.spider_fix_one_table('spider_tables', 'ssl_ca',
- 'alter table mysql.spider_tables
- add column ssl_ca char(64) default null after password,
- add column ssl_capath char(64) default null after ssl_ca,
- add column ssl_cert char(64) default null after ssl_capath,
- add column ssl_cipher char(64) default null after ssl_cert,
- add column ssl_key char(64) default null after ssl_cipher,
- add column ssl_verify_server_cert tinyint not null default 0 after ssl_key,
- add column default_file char(64) default null after ssl_verify_server_cert,
- add column default_group char(64) default null after default_file');
- call mysql.spider_fix_one_table('spider_link_mon_servers', 'ssl_ca',
- 'alter table mysql.spider_link_mon_servers
- add column ssl_ca char(64) default null after password,
- add column ssl_capath char(64) default null after ssl_ca,
- add column ssl_cert char(64) default null after ssl_capath,
- add column ssl_cipher char(64) default null after ssl_cert,
- add column ssl_key char(64) default null after ssl_cipher,
- add column ssl_verify_server_cert tinyint not null default 0 after ssl_key,
- add column default_file char(64) default null after ssl_verify_server_cert,
- add column default_group char(64) default null after default_file');
-
- -- Fix for version 2.25
- -- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- -- where TABLE_SCHEMA = 'mysql'
- -- AND TABLE_NAME = 'spider_link_mon_servers'
- -- AND COLUMN_NAME = 'link_id';
- -- if @col_type != 'char(5)' then
- -- alter table mysql.spider_link_mon_servers
- -- modify link_id char(5) not null default '';
- -- end if;
-
- -- Fix for version 2.28
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_mon_servers'
- AND COLUMN_NAME = 'sid';
- if @col_type != 'int(10) unsigned' then
- alter table mysql.spider_link_mon_servers
- modify sid int unsigned not null default 0;
- end if;
-
- -- Fix for version 3.1
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_xa_member'
- AND COLUMN_NAME = 'socket';
- if @col_type = 'char(64)' then
- alter table mysql.spider_xa_member
- drop primary key,
- add index idx1 (data, format_id, gtrid_length, host),
- modify socket text not null,
- modify ssl_ca text,
- modify ssl_capath text,
- modify ssl_cert text,
- modify ssl_key text,
- modify default_file text;
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_tables'
- AND COLUMN_NAME = 'socket';
- if @col_type = 'char(64)' then
- alter table mysql.spider_tables
- modify socket text,
- modify ssl_ca text,
- modify ssl_capath text,
- modify ssl_cert text,
- modify ssl_key text,
- modify default_file text;
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_mon_servers'
- AND COLUMN_NAME = 'socket';
- if @col_type = 'char(64)' then
- alter table mysql.spider_link_mon_servers
- modify socket text,
- modify ssl_ca text,
- modify ssl_capath text,
- modify ssl_cert text,
- modify ssl_key text,
- modify default_file text;
- end if;
-
- -- Fix for version 3.3.0
- call mysql.spider_fix_one_table('spider_tables',
- 'monitoring_binlog_pos_at_failing',
- 'alter table mysql.spider_tables
- add monitoring_binlog_pos_at_failing tinyint not null default 0 after ssl_verify_server_cert');
-
- -- Fix for version 3.3.6
- call mysql.spider_fix_one_table('spider_tables', 'block_status',
- 'alter table mysql.spider_tables
- add column block_status tinyint not null default 0 after link_status');
- call mysql.spider_fix_one_table('spider_tables', 'static_link_id',
- 'alter table mysql.spider_tables
- add column static_link_id char(64) default null after block_status,
- add unique index uidx1 (db_name, table_name, static_link_id)');
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_mon_servers'
- AND COLUMN_NAME = 'link_id';
- if @col_type != 'char(64)' then
- alter table mysql.spider_link_mon_servers
- modify link_id char(64) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_failed_log'
- AND COLUMN_NAME = 'link_id';
- if @col_type != 'char(64)' then
- alter table mysql.spider_link_failed_log
- modify link_id char(64) not null default '';
- end if;
-
- -- Fix for version 3.3.10
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_tables'
- AND COLUMN_NAME = 'table_name';
- if @col_type != 'char(199)' then
- alter table mysql.spider_tables
- modify table_name char(199) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_mon_servers'
- AND COLUMN_NAME = 'table_name';
- if @col_type != 'char(199)' then
- alter table mysql.spider_link_mon_servers
- modify table_name char(199) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_failed_log'
- AND COLUMN_NAME = 'table_name';
- if @col_type != 'char(199)' then
- alter table mysql.spider_link_failed_log
- modify table_name char(199) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_table_position_for_recovery'
- AND COLUMN_NAME = 'table_name';
- if @col_type != 'char(199)' then
- alter table mysql.spider_table_position_for_recovery
- modify table_name char(199) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_table_sts'
- AND COLUMN_NAME = 'table_name';
- if @col_type != 'char(199)' then
- alter table mysql.spider_table_sts
- modify table_name char(199) not null default '';
- end if;
- select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_table_crd'
- AND COLUMN_NAME = 'table_name';
- if @col_type != 'char(199)' then
- alter table mysql.spider_table_crd
- modify table_name char(199) not null default '';
- end if;
-
- -- Fix for MariaDB 10.4: Crash-Safe system tables
- if @server_name = 'MariaDB' and
- (
- @server_major_version > 10 or
- (
- @server_major_version = 10 and
- @server_minor_version >= 4
- )
- )
- then
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_failed_log';
- if @engine_name != 'Aria' then
- alter table mysql.spider_link_failed_log
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_link_mon_servers';
- if @engine_name != 'Aria' then
- alter table mysql.spider_link_mon_servers
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_table_crd';
- if @engine_name != 'Aria' then
- alter table mysql.spider_table_crd
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_table_position_for_recovery';
- if @engine_name != 'Aria' then
- alter table mysql.spider_table_position_for_recovery
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_table_sts';
- if @engine_name != 'Aria' then
- alter table mysql.spider_table_sts
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_tables';
- if @engine_name != 'Aria' then
- alter table mysql.spider_tables
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_xa';
- if @engine_name != 'Aria' then
- alter table mysql.spider_xa
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_xa_failed_log';
- if @engine_name != 'Aria' then
- alter table mysql.spider_xa_failed_log
- engine=Aria transactional=1;
- end if;
- select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES
- where TABLE_SCHEMA = 'mysql'
- AND TABLE_NAME = 'spider_xa_member';
- if @engine_name != 'Aria' then
- alter table mysql.spider_xa_member
- engine=Aria transactional=1;
- end if;
- end if;
-end;//
-delimiter ;
-call mysql.spider_fix_system_tables;
-drop procedure mysql.spider_fix_one_table;
-drop procedure mysql.spider_fix_system_tables;
-
--- Install a plugin and UDFs
drop procedure if exists mysql.spider_plugin_installer;
delimiter //
create procedure mysql.spider_plugin_installer()
@@ -512,71 +36,6 @@ begin
install plugin spider soname 'ha_spider.dll';
end if;
end if;
- set @have_spider_i_s_alloc_mem_plugin := 0;
- select @have_spider_i_s_alloc_mem_plugin := 1 from INFORMATION_SCHEMA.plugins where PLUGIN_NAME = 'SPIDER_ALLOC_MEM';
- set @have_spider_alloc_mem_plugin := 0;
- select @have_spider_alloc_mem_plugin := 1 from mysql.plugin where name = 'spider_alloc_mem';
- if @have_spider_i_s_alloc_mem_plugin = 0 then
- if @have_spider_alloc_mem_plugin = 1 then
- -- spider_alloc_mem plugin is present in mysql.plugin but not in
- -- information_schema.plugins. Remove spider_alloc_mem plugin entry
- -- in mysql.plugin first.
- delete from mysql.plugin where name = 'spider_alloc_mem';
- end if;
- -- Install spider_alloc_mem plugin
- if @win_plugin = 0 then
- install plugin spider_alloc_mem soname 'ha_spider.so';
- else
- install plugin spider_alloc_mem soname 'ha_spider.dll';
- end if;
- end if;
- set @have_spider_direct_sql_udf := 0;
- select @have_spider_direct_sql_udf := 1 from mysql.func where name = 'spider_direct_sql';
- if @have_spider_direct_sql_udf = 0 then
- if @win_plugin = 0 then
- create function spider_direct_sql returns int soname 'ha_spider.so';
- else
- create function spider_direct_sql returns int soname 'ha_spider.dll';
- end if;
- end if;
- set @have_spider_bg_direct_sql_udf := 0;
- select @have_spider_bg_direct_sql_udf := 1 from mysql.func where name = 'spider_bg_direct_sql';
- if @have_spider_bg_direct_sql_udf = 0 then
- if @win_plugin = 0 then
- create aggregate function spider_bg_direct_sql returns int soname 'ha_spider.so';
- else
- create aggregate function spider_bg_direct_sql returns int soname 'ha_spider.dll';
- end if;
- end if;
- set @have_spider_ping_table_udf := 0;
- select @have_spider_ping_table_udf := 1 from mysql.func where name = 'spider_ping_table';
- if @have_spider_ping_table_udf = 0 then
- if @win_plugin = 0 then
- create function spider_ping_table returns int soname 'ha_spider.so';
- else
- create function spider_ping_table returns int soname 'ha_spider.dll';
- end if;
- end if;
- set @have_spider_copy_tables_udf := 0;
- select @have_spider_copy_tables_udf := 1 from mysql.func where name = 'spider_copy_tables';
- if @have_spider_copy_tables_udf = 0 then
- if @win_plugin = 0 then
- create function spider_copy_tables returns int soname 'ha_spider.so';
- else
- create function spider_copy_tables returns int soname 'ha_spider.dll';
- end if;
- end if;
-
- set @have_spider_flush_table_mon_cache_udf := 0;
- select @have_spider_flush_table_mon_cache_udf := 1 from mysql.func where name = 'spider_flush_table_mon_cache';
- if @have_spider_flush_table_mon_cache_udf = 0 then
- if @win_plugin = 0 then
- create function spider_flush_table_mon_cache returns int soname 'ha_spider.so';
- else
- create function spider_flush_table_mon_cache returns int soname 'ha_spider.dll';
- end if;
- end if;
-
end;//
delimiter ;
call mysql.spider_plugin_installer;
diff --git a/storage/spider/spd_conn.cc b/storage/spider/spd_conn.cc
index 4a8de844ca9..03afdfd68f8 100644
--- a/storage/spider/spd_conn.cc
+++ b/storage/spider/spd_conn.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019, 2020, 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
@@ -91,6 +92,9 @@ extern PSI_thread_key spd_key_thd_bg_mon;
/* UTC time zone for timestamp columns */
extern Time_zone *UTC;
+extern sql_mode_t full_sql_mode;
+extern sql_mode_t pushdown_sql_mode;
+
HASH spider_open_connections;
uint spider_open_connections_id;
HASH spider_ipport_conns;
@@ -148,6 +152,8 @@ int spider_reset_conn_setted_parameter(
DBUG_ENTER("spider_reset_conn_setted_parameter");
conn->autocommit = spider_param_remote_autocommit();
conn->sql_log_off = spider_param_remote_sql_log_off();
+ conn->wait_timeout = spider_param_remote_wait_timeout(thd);
+ conn->sql_mode = full_sql_mode + 1;
if (thd && spider_param_remote_time_zone())
{
int tz_length = strlen(spider_param_remote_time_zone());
@@ -1428,6 +1434,32 @@ void spider_conn_queue_sql_log_off(
DBUG_VOID_RETURN;
}
+void spider_conn_queue_wait_timeout(
+ SPIDER_CONN *conn,
+ int wait_timeout
+) {
+ DBUG_ENTER("spider_conn_queue_wait_timeout");
+ DBUG_PRINT("info", ("spider conn=%p", conn));
+ if (wait_timeout > 0)
+ {
+ conn->queued_wait_timeout = TRUE;
+ conn->queued_wait_timeout_val = wait_timeout;
+ }
+ DBUG_VOID_RETURN;
+}
+
+void spider_conn_queue_sql_mode(
+ SPIDER_CONN *conn,
+ sql_mode_t sql_mode
+) {
+ DBUG_ENTER("spider_conn_queue_sql_mode");
+ DBUG_PRINT("info", ("spider conn=%p", conn));
+ DBUG_ASSERT(!(sql_mode & ~full_sql_mode));
+ conn->queued_sql_mode = TRUE;
+ conn->queued_sql_mode_val = (sql_mode & pushdown_sql_mode);
+ DBUG_VOID_RETURN;
+}
+
void spider_conn_queue_time_zone(
SPIDER_CONN *conn,
Time_zone *time_zone
@@ -1483,6 +1515,8 @@ void spider_conn_clear_queue(
conn->queued_semi_trx_isolation = FALSE;
conn->queued_autocommit = FALSE;
conn->queued_sql_log_off = FALSE;
+ conn->queued_wait_timeout = FALSE;
+ conn->queued_sql_mode = FALSE;
conn->queued_time_zone = FALSE;
conn->queued_trx_start = FALSE;
conn->queued_xa_start = FALSE;
@@ -2802,23 +2836,20 @@ void *spider_bg_conn_action(
{
switch (conn->bg_simple_action)
{
- case SPIDER_BG_SIMPLE_CONNECT:
+ case SPIDER_SIMPLE_CONNECT:
conn->db_conn->bg_connect();
break;
- case SPIDER_BG_SIMPLE_DISCONNECT:
+ case SPIDER_SIMPLE_DISCONNECT:
conn->db_conn->bg_disconnect();
break;
- case SPIDER_BG_SIMPLE_RECORDS:
- DBUG_PRINT("info",("spider bg simple records"));
+ default:
spider = (ha_spider*) conn->bg_target;
*conn->bg_error_num =
- spider->dbton_handler[conn->dbton_id]->
- show_records(conn->link_idx);
- break;
- default:
+ spider_db_simple_action(conn->bg_simple_action,
+ spider->dbton_handler[conn->dbton_id], conn->link_idx);
break;
}
- conn->bg_simple_action = SPIDER_BG_SIMPLE_NO_ACTION;
+ conn->bg_simple_action = SPIDER_SIMPLE_NO_ACTION;
if (conn->bg_caller_wait)
{
pthread_mutex_lock(&conn->bg_conn_sync_mutex);
@@ -4534,17 +4565,18 @@ SPIDER_IP_PORT_CONN* spider_create_ipport_conn(SPIDER_CONN *conn)
goto err_malloc_key;
}
- ret->key = (char *) my_malloc(ret->key_len, MY_ZEROFILL | MY_WME);
+ ret->key = (char *) my_malloc(ret->key_len + conn->tgt_host_length + 1,
+ MY_ZEROFILL | MY_WME);
if (!ret->key) {
pthread_cond_destroy(&ret->cond);
pthread_mutex_destroy(&ret->mutex);
goto err_malloc_key;
}
+ ret->remote_ip_str = ret->key + ret->key_len;
memcpy(ret->key, conn->conn_key, ret->key_len);
- strncpy(ret->remote_ip_str, conn->tgt_host, sizeof(ret->remote_ip_str));
- ret->remote_ip_str[sizeof ret->remote_ip_str - 1] = '\0';
+ memcpy(ret->remote_ip_str, conn->tgt_host, conn->tgt_host_length);
ret->remote_port = conn->tgt_port;
ret->conn_id = conn->conn_id;
ret->ip_port_count = 1; // init
diff --git a/storage/spider/spd_conn.h b/storage/spider/spd_conn.h
index a066da6a5ea..1612593a1cb 100644
--- a/storage/spider/spd_conn.h
+++ b/storage/spider/spd_conn.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -17,10 +18,13 @@
#define SPIDER_LOCK_MODE_SHARED 1
#define SPIDER_LOCK_MODE_EXCLUSIVE 2
-#define SPIDER_BG_SIMPLE_NO_ACTION 0
-#define SPIDER_BG_SIMPLE_CONNECT 1
-#define SPIDER_BG_SIMPLE_DISCONNECT 2
-#define SPIDER_BG_SIMPLE_RECORDS 3
+#define SPIDER_SIMPLE_NO_ACTION 0
+#define SPIDER_SIMPLE_CONNECT 1
+#define SPIDER_SIMPLE_DISCONNECT 2
+#define SPIDER_SIMPLE_RECORDS 3
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+#define SPIDER_SIMPLE_CHECKSUM_TABLE 4
+#endif
uchar *spider_conn_get_key(
SPIDER_CONN *conn,
@@ -132,6 +136,16 @@ void spider_conn_queue_sql_log_off(
bool sql_log_off
);
+void spider_conn_queue_wait_timeout(
+ SPIDER_CONN *conn,
+ int wait_timeout
+);
+
+void spider_conn_queue_sql_mode(
+ SPIDER_CONN *conn,
+ sql_mode_t sql_mode
+);
+
void spider_conn_queue_time_zone(
SPIDER_CONN *conn,
Time_zone *time_zone
diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc
index cc4599ce0b3..4cf9e8b4000 100644
--- a/storage/spider/spd_db_conn.cc
+++ b/storage/spider/spd_db_conn.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019, 2020, 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
@@ -381,6 +382,20 @@ int spider_db_conn_queue_action(
append_sql_log_off(&sql_str, conn->queued_sql_log_off_val))
) ||
(
+ conn->queued_wait_timeout &&
+ conn->queued_wait_timeout_val != conn->wait_timeout &&
+ conn->db_conn->set_wait_timeout_in_bulk_sql() &&
+ (error_num = spider_dbton[conn->dbton_id].db_util->
+ append_wait_timeout(&sql_str, conn->queued_wait_timeout_val))
+ ) ||
+ (
+ conn->queued_sql_mode &&
+ conn->queued_sql_mode_val != conn->sql_mode &&
+ conn->db_conn->set_sql_mode_in_bulk_sql() &&
+ (error_num = spider_dbton[conn->dbton_id].db_util->
+ append_sql_mode(&sql_str, conn->queued_sql_mode_val))
+ ) ||
+ (
conn->queued_time_zone &&
conn->queued_time_zone_val != conn->time_zone &&
conn->db_conn->set_time_zone_in_bulk_sql() &&
@@ -453,6 +468,24 @@ int spider_db_conn_queue_action(
DBUG_RETURN(error_num);
}
if (
+ conn->queued_wait_timeout &&
+ conn->queued_wait_timeout_val != conn->wait_timeout &&
+ !conn->db_conn->set_wait_timeout_in_bulk_sql() &&
+ (error_num = spider_dbton[conn->dbton_id].db_util->
+ append_wait_timeout(&sql_str, conn->queued_wait_timeout_val))
+ ) {
+ DBUG_RETURN(error_num);
+ }
+ if (
+ conn->queued_sql_mode &&
+ conn->queued_sql_mode_val != conn->sql_mode &&
+ !conn->db_conn->set_sql_mode_in_bulk_sql() &&
+ (error_num = spider_dbton[conn->dbton_id].db_util->
+ append_sql_mode(&sql_str, conn->queued_sql_mode_val))
+ ) {
+ DBUG_RETURN(error_num);
+ }
+ if (
conn->queued_time_zone &&
conn->queued_time_zone_val != conn->time_zone &&
!conn->db_conn->set_time_zone_in_bulk_sql() &&
@@ -519,6 +552,20 @@ int spider_db_conn_queue_action(
conn->trx_isolation));
}
+ if (
+ conn->queued_wait_timeout &&
+ conn->queued_wait_timeout_val != conn->wait_timeout
+ ) {
+ conn->wait_timeout = conn->queued_wait_timeout_val;
+ }
+
+ if (
+ conn->queued_sql_mode &&
+ conn->queued_sql_mode_val != conn->sql_mode
+ ) {
+ conn->sql_mode = conn->queued_sql_mode_val;
+ }
+
if (conn->queued_autocommit)
{
if (conn->queued_autocommit_val && conn->autocommit != 1)
@@ -1392,7 +1439,7 @@ int spider_db_append_name_with_quote_str(
) {
DBUG_ENTER("spider_db_append_name_with_quote_str");
DBUG_RETURN(spider_db_append_name_with_quote_str_internal(
- str, name, strlen(name), dbton_id));
+ str, name, strlen(name), system_charset_info, dbton_id));
}
int spider_db_append_name_with_quote_str(
@@ -1402,13 +1449,25 @@ int spider_db_append_name_with_quote_str(
) {
DBUG_ENTER("spider_db_append_name_with_quote_str");
DBUG_RETURN(spider_db_append_name_with_quote_str_internal(
- str, name.str, name.length, dbton_id));
+ str, name.str, name.length, system_charset_info, dbton_id));
+}
+
+int spider_db_append_name_with_quote_str_internal(
+ spider_string *str,
+ const char *name,
+ int length,
+ uint dbton_id
+) {
+ DBUG_ENTER("spider_db_append_name_with_quote_str_internal");
+ DBUG_RETURN(spider_db_append_name_with_quote_str_internal(
+ str, name, length, system_charset_info, dbton_id));
}
int spider_db_append_name_with_quote_str_internal(
spider_string *str,
const char *name,
int length,
+ CHARSET_INFO *cs,
uint dbton_id
) {
int error_num;
@@ -1419,9 +1478,9 @@ int spider_db_append_name_with_quote_str_internal(
{
head_code = *name;
#ifdef SPIDER_HAS_MY_CHARLEN
- if ((length = my_charlen(system_charset_info, name, name_end)) < 1)
+ if ((length = my_charlen(cs, name, name_end)) < 1)
#else
- if (!(length = my_mbcharlen(system_charset_info, (uchar) head_code)))
+ if (!(length = my_mbcharlen(cs, (uchar) head_code)))
#endif
{
my_message(ER_SPIDER_WRONG_CHARACTER_IN_NAME_NUM,
@@ -1438,7 +1497,7 @@ int spider_db_append_name_with_quote_str_internal(
DBUG_RETURN(error_num);
}
} else {
- if (str->append(name, length, system_charset_info))
+ if (str->append(name, length, cs))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
}
@@ -1801,6 +1860,7 @@ int spider_db_append_key_where_internal(
key_part++,
key_count++
) {
+ DBUG_PRINT("info", ("spider tgt_key_part_map=%lu", tgt_key_part_map));
store_length = key_part->store_length;
field = key_part->field;
key_name_length = dbton_share->get_column_name_length(field->field_index);
@@ -1826,7 +1886,6 @@ int spider_db_append_key_where_internal(
#endif
}
} else {
- DBUG_PRINT("info", ("spider tgt_key_part_map=%lu", tgt_key_part_map));
if (tgt_key_part_map > 1)
key_eq = TRUE;
else
@@ -1836,7 +1895,8 @@ int spider_db_append_key_where_internal(
(key_eq && use_key == start_key) ||
(!key_eq && start_key_part_map)
) {
- bool tgt_final = (use_key == start_key && tgt_key_part_map == 1);
+ bool tgt_final = (use_key == start_key &&
+ (tgt_key_part_map == 1 || !end_key_part_map));
ptr = start_key->key + length;
if (
(error_num = dbton_hdl->append_is_null_part(sql_type, key_part,
@@ -1882,10 +1942,23 @@ int spider_db_append_key_where_internal(
if (use_key == start_key)
{
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
if (spider_dbton[dbton_id].db_util->
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_EQUAL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -1933,7 +2006,8 @@ int spider_db_append_key_where_internal(
if (use_key == start_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !end_key_part_map)
{
if (str->reserve(SPIDER_SQL_EQUAL_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -1943,6 +2017,18 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_EQUAL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -1992,7 +2078,8 @@ int spider_db_append_key_where_internal(
if (use_key == start_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !end_key_part_map)
{
if (str->reserve(SPIDER_SQL_GT_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2002,6 +2089,18 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_GT_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_GT_STR, SPIDER_SQL_GT_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -2052,7 +2151,8 @@ int spider_db_append_key_where_internal(
if (use_key == start_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !end_key_part_map)
{
if (str->reserve(SPIDER_SQL_LT_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2062,6 +2162,18 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_LT_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_LT_STR, SPIDER_SQL_LT_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -2118,7 +2230,8 @@ int spider_db_append_key_where_internal(
if (use_key == start_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !end_key_part_map)
{
if (str->reserve(SPIDER_SQL_LTEQUAL_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2129,6 +2242,19 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_LTEQUAL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_LTEQUAL_STR,
+ SPIDER_SQL_LTEQUAL_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -2267,7 +2393,8 @@ int spider_db_append_key_where_internal(
if (use_key == start_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !end_key_part_map)
{
if (str->reserve(SPIDER_SQL_GTEQUAL_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2278,6 +2405,19 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_GTEQUAL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_GTEQUAL_STR,
+ SPIDER_SQL_GTEQUAL_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -2308,12 +2448,14 @@ int spider_db_append_key_where_internal(
str_part2->q_append(SPIDER_SQL_AND_STR,
SPIDER_SQL_AND_LEN);
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
if (use_key == start_key)
{
if (str_part->reserve(SPIDER_SQL_COMMA_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str_part->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
}
+#endif
}
}
@@ -2369,18 +2511,23 @@ int spider_db_append_key_where_internal(
if (use_key == end_key)
{
-/*
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
{
if (str->reserve(SPIDER_SQL_EQUAL_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
-*/
- if (spider_dbton[dbton_id].db_util->
- append_column_value(spider, str_part, field, ptr,
- share->access_charset))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#endif
}
}
} else {
@@ -2421,7 +2568,8 @@ int spider_db_append_key_where_internal(
if (use_key == end_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !start_key_part_map)
{
if (str->reserve(SPIDER_SQL_LT_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2431,6 +2579,18 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_LT_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_LT_STR, SPIDER_SQL_LT_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
break;
@@ -2467,7 +2627,8 @@ int spider_db_append_key_where_internal(
if (use_key == end_key)
{
- if (tgt_key_part_map == 1)
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
+ if (tgt_key_part_map == 1 || !start_key_part_map)
{
if (str->reserve(SPIDER_SQL_LTEQUAL_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
@@ -2478,6 +2639,19 @@ int spider_db_append_key_where_internal(
append_column_value(spider, str_part, field, ptr,
share->access_charset))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_LTEQUAL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_LTEQUAL_STR,
+ SPIDER_SQL_LTEQUAL_LEN);
+ if (spider_dbton[dbton_id].db_util->
+ append_column_value(spider, str_part, field, ptr,
+ share->access_charset))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+#endif
}
}
break;
@@ -2495,12 +2669,14 @@ int spider_db_append_key_where_internal(
str_part2->q_append(SPIDER_SQL_AND_STR,
SPIDER_SQL_AND_LEN);
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
if (use_key == end_key)
{
if (str_part->reserve(SPIDER_SQL_COMMA_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str_part->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
}
+#endif
}
}
if (use_both && (!start_key_part_map || !end_key_part_map))
@@ -2558,6 +2734,22 @@ int spider_db_append_key_where(
DBUG_RETURN(0);
}
+int spider_db_append_charset_name_before_string(
+ spider_string *str,
+ CHARSET_INFO *cs
+) {
+ const char *csname = cs->csname;
+ uint csname_length = strlen(csname);
+ DBUG_ENTER("spider_db_append_charset_name_before_string");
+ if (str->reserve(SPIDER_SQL_UNDERSCORE_LEN + csname_length))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_UNDERSCORE_STR, SPIDER_SQL_UNDERSCORE_LEN);
+ str->q_append(csname, csname_length);
+ DBUG_RETURN(0);
+}
+
#ifdef HANDLER_HAS_DIRECT_AGGREGATE
int spider_db_refetch_for_item_sum_funcs(
ha_spider *spider
@@ -5644,7 +5836,39 @@ int spider_db_show_table_status(
DBUG_RETURN(error_num);
}
-int spider_db_show_records(
+int spider_db_simple_action(
+ uint simple_action,
+ spider_db_handler *db_handler,
+ int link_idx
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_simple_action");
+ switch (simple_action)
+ {
+ case SPIDER_SIMPLE_RECORDS:
+ DBUG_PRINT("info",("spider simple records"));
+ error_num = db_handler->show_records(
+ link_idx
+ );
+ break;
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ case SPIDER_SIMPLE_CHECKSUM_TABLE:
+ DBUG_PRINT("info",("spider simple checksum_table"));
+ error_num = db_handler->checksum_table(
+ link_idx
+ );
+ break;
+#endif
+ default:
+ DBUG_ASSERT(0);
+ error_num = HA_ERR_CRASHED;
+ break;
+ }
+ DBUG_RETURN(error_num);
+}
+
+int spider_db_simple_action(
+ uint simple_action,
ha_spider *spider,
int link_idx,
bool pre_call
@@ -5652,7 +5876,7 @@ int spider_db_show_records(
int error_num;
THD *thd = spider->trx->thd;
SPIDER_CONN *conn;
- DBUG_ENTER("spider_db_show_records");
+ DBUG_ENTER("spider_db_simple_action");
if (pre_call)
{
if (spider_param_bgs_mode(thd, spider->share->bgs_mode))
@@ -5665,18 +5889,20 @@ int spider_db_show_records(
conn = spider->conns[link_idx];
if (!(error_num = spider_create_conn_thread(conn)))
{
- spider_bg_conn_simple_action(conn, SPIDER_BG_SIMPLE_RECORDS, FALSE,
+ spider_bg_conn_simple_action(conn, simple_action, FALSE,
spider, link_idx, (int *) &spider->result_list.bgs_error);
}
} else {
conn = spider->conns[link_idx];
- error_num = spider->dbton_handler[conn->dbton_id]->show_records(
+ error_num = spider_db_simple_action(
+ simple_action,
+ spider->dbton_handler[conn->dbton_id],
link_idx
);
}
} else {
conn = spider->conns[link_idx];
- if (spider->use_pre_records)
+ if (spider->use_pre_action)
{
if (spider_param_bgs_mode(thd, spider->share->bgs_mode))
{
@@ -5690,7 +5916,9 @@ int spider_db_show_records(
error_num = 0;
}
} else {
- error_num = spider->dbton_handler[conn->dbton_id]->show_records(
+ error_num = spider_db_simple_action(
+ simple_action,
+ spider->dbton_handler[conn->dbton_id],
link_idx
);
}
@@ -5718,7 +5946,7 @@ void spider_db_set_cardinarity(
{
key_part = &key_info->key_part[roop_count2];
field = key_part->field;
- rec_per_key = (ha_rows) share->records /
+ rec_per_key = (ha_rows) share->stat.records /
share->cardinality[field->field_index];
if (rec_per_key > ~(ulong) 0)
key_info->rec_per_key[roop_count2] = ~(ulong) 0;
@@ -5863,6 +6091,7 @@ int spider_db_bulk_insert_init(
int spider_db_bulk_insert(
ha_spider *spider,
TABLE *table,
+ ha_copy_info *copy_info,
bool bulk_end
) {
int error_num, first_insert_link_idx = -1;
@@ -5909,6 +6138,7 @@ int spider_db_bulk_insert(
if (!spider->is_bulk_access_clone)
{
#endif
+ bool insert_info = FALSE;
for (
roop_count2 = spider_conn_link_idx_next(share->link_statuses,
spider->conn_link_idx, -1, share->link_count,
@@ -6057,6 +6287,11 @@ int spider_db_bulk_insert(
}
conn->mta_conn_mutex_lock_already = mta_conn_mutex_lock_already_backup;
conn->mta_conn_mutex_unlock_later = mta_conn_mutex_unlock_later_backup;
+ if (!insert_info && copy_info)
+ {
+ insert_info =
+ conn->db_conn->inserted_info(dbton_handler, copy_info);
+ }
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
if (conn->conn_kind != SPIDER_CONN_KIND_MYSQL)
{
@@ -6810,7 +7045,8 @@ int spider_db_direct_update(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num, roop_count;
SPIDER_SHARE *share = spider->share;
@@ -7083,6 +7319,8 @@ int spider_db_direct_update(
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = spider->conns[roop_count]->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -7104,6 +7342,8 @@ int spider_db_direct_update(
{
*update_rows = conn->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = conn->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
result->free_result();
@@ -7141,7 +7381,8 @@ int spider_db_direct_update(
int spider_db_direct_update(
ha_spider *spider,
TABLE *table,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num, roop_count;
SPIDER_SHARE *share = spider->share;
@@ -7334,6 +7575,8 @@ int spider_db_direct_update(
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = spider->conns[roop_count]->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
#ifdef HA_CAN_BULK_ACCESS
@@ -7353,7 +7596,8 @@ int spider_db_direct_update(
#ifdef HA_CAN_BULK_ACCESS
int spider_db_bulk_direct_update(
ha_spider *spider,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
) {
int error_num = 0, roop_count, tmp_error_num;
SPIDER_SHARE *share = spider->share;
@@ -7398,6 +7642,8 @@ int spider_db_bulk_direct_update(
{
*update_rows = spider->conns[roop_count]->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = spider->conns[roop_count]->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
#if defined(HS_HAS_SQLCOM) && defined(HAVE_HANDLERSOCKET)
@@ -7419,6 +7665,8 @@ int spider_db_bulk_direct_update(
{
*update_rows = conn->db_conn->affected_rows();
DBUG_PRINT("info", ("spider update_rows = %llu", *update_rows));
+ *found_rows = conn->db_conn->matched_rows();
+ DBUG_PRINT("info", ("spider found_rows = %llu", *found_rows));
counted = TRUE;
}
result->free_result();
@@ -8884,34 +9132,58 @@ int spider_db_open_item_ident(
Field *field = item_ident->cached_table->table->field[
item_ident->cached_field_index];
DBUG_PRINT("info",("spider use cached_field_index"));
- if (!use_fields)
+ DBUG_PRINT("info",("spider const_table=%s",
+ field->table->const_table ? "TRUE" : "FALSE"));
+ if (field->table->const_table)
{
- if (!(field = spider->field_exchange(field)))
- DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
if (str)
{
- if ((error_num = share->dbton_share[dbton_id]->
- append_column_name_with_alias(str, field->field_index,
- alias, alias_length)))
- DBUG_RETURN(error_num);
+ String str_value;
+ String *tmp_str;
+ tmp_str = field->val_str(&str_value);
+ if (!tmp_str)
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 +
+ tmp_str->length() * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ str->append_escape_string(tmp_str->ptr(), tmp_str->length());
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
}
} else {
- if (str)
+ if (!use_fields)
{
- SPIDER_FIELD_CHAIN *field_chain = fields->get_next_field_chain();
- SPIDER_FIELD_HOLDER *field_holder = field_chain->field_holder;
- spider = field_holder->spider;
- share = spider->share;
- field = spider->field_exchange(field);
- DBUG_ASSERT(field);
- if ((error_num = share->dbton_share[dbton_id]->
- append_column_name_with_alias(str, field->field_index,
- field_holder->alias->ptr(), field_holder->alias->length())))
- DBUG_RETURN(error_num);
+ if (!(field = spider->field_exchange(field)))
+ DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
+ if (str)
+ {
+ if ((error_num = share->dbton_share[dbton_id]->
+ append_column_name_with_alias(str, field->field_index,
+ alias, alias_length)))
+ DBUG_RETURN(error_num);
+ }
} else {
- if ((error_num = fields->add_field(field)))
+ if (str)
{
- DBUG_RETURN(error_num);
+ SPIDER_FIELD_CHAIN *field_chain = fields->get_next_field_chain();
+ SPIDER_FIELD_HOLDER *field_holder = field_chain->field_holder;
+ spider = field_holder->spider;
+ share = spider->share;
+ field = spider->field_exchange(field);
+ DBUG_ASSERT(field);
+ if ((error_num = share->dbton_share[dbton_id]->
+ append_column_name_with_alias(str, field->field_index,
+ field_holder->alias->ptr(), field_holder->alias->length())))
+ DBUG_RETURN(error_num);
+ } else {
+ if ((error_num = fields->add_field(field)))
+ {
+ DBUG_RETURN(error_num);
+ }
}
}
}
@@ -8938,10 +9210,11 @@ int spider_db_open_item_ident(
str->q_append(alias, alias_length);
#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name(str, item_ident->field_name.str, field_name_length)))
+ append_escaped_name(str, item_ident->field_name.str,
+ field_name_length)))
#else
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name(str, item_ident->field_name, field_name_length)))
+ append_escaped_name(str, item_ident->field_name, field_name_length)))
#endif
{
DBUG_RETURN(error_num);
@@ -8952,11 +9225,11 @@ int spider_db_open_item_ident(
str->q_append(alias, alias_length);
#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name_with_charset(str, item_ident->field_name.str,
+ append_escaped_name_with_charset(str, item_ident->field_name.str,
field_name_length, system_charset_info)))
#else
if ((error_num = spider_dbton[dbton_id].db_util->
- append_name_with_charset(str, item_ident->field_name,
+ append_escaped_name_with_charset(str, item_ident->field_name,
field_name_length, system_charset_info)))
#endif
{
@@ -8981,46 +9254,72 @@ int spider_db_open_item_field(
Field *field = item_field->field;
SPIDER_SHARE *share = spider->share;
DBUG_ENTER("spider_db_open_item_field");
- if (field && !field->table->const_table)
+ if (field)
{
DBUG_PRINT("info",("spider field=%p", field));
DBUG_PRINT("info",("spider db=%s", field->table->s->db.str));
- DBUG_PRINT("info",("spider table_name=%s", field->table->s->table_name.str));
- DBUG_PRINT("info",("spider tmp_table=%u", field->table->s->tmp_table));
- if (field->table->s->tmp_table != INTERNAL_TMP_TABLE)
+ DBUG_PRINT("info",("spider table_name=%s",
+ field->table->s->table_name.str));
+ DBUG_PRINT("info",("spider const_table=%s",
+ field->table->const_table ? "TRUE" : "FALSE"));
+ if (field->table->const_table)
{
- if (!use_fields)
+ if (str)
{
- if (!(field = spider->field_exchange(field)))
- DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
- if (str)
+ String str_value;
+ String *tmp_str;
+ tmp_str = field->val_str(&str_value);
+ if (!tmp_str)
{
- if ((error_num = share->dbton_share[dbton_id]->
- append_column_name_with_alias(str, field->field_index,
- alias, alias_length)))
- DBUG_RETURN(error_num);
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
- DBUG_RETURN(0);
- } else {
- if (str)
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 +
+ tmp_str->length() * 2))
{
- SPIDER_FIELD_CHAIN *field_chain = fields->get_next_field_chain();
- SPIDER_FIELD_HOLDER *field_holder = field_chain->field_holder;
- spider = field_holder->spider;
- share = spider->share;
- field = spider->field_exchange(field);
- DBUG_ASSERT(field);
- if ((error_num = share->dbton_share[dbton_id]->
- append_column_name_with_alias(str, field->field_index,
- field_holder->alias->ptr(), field_holder->alias->length())))
- DBUG_RETURN(error_num);
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ str->append_escape_string(tmp_str->ptr(), tmp_str->length());
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ }
+ DBUG_RETURN(0);
+ } else {
+ DBUG_PRINT("info",("spider tmp_table=%u", field->table->s->tmp_table));
+ if (field->table->s->tmp_table != INTERNAL_TMP_TABLE)
+ {
+ if (!use_fields)
+ {
+ if (!(field = spider->field_exchange(field)))
+ DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
+ if (str)
+ {
+ if ((error_num = share->dbton_share[dbton_id]->
+ append_column_name_with_alias(str, field->field_index,
+ alias, alias_length)))
+ DBUG_RETURN(error_num);
+ }
+ DBUG_RETURN(0);
} else {
- if ((error_num = fields->add_field(field)))
+ if (str)
{
- DBUG_RETURN(error_num);
+ SPIDER_FIELD_CHAIN *field_chain = fields->get_next_field_chain();
+ SPIDER_FIELD_HOLDER *field_holder = field_chain->field_holder;
+ spider = field_holder->spider;
+ share = spider->share;
+ field = spider->field_exchange(field);
+ DBUG_ASSERT(field);
+ if ((error_num = share->dbton_share[dbton_id]->
+ append_column_name_with_alias(str, field->field_index,
+ field_holder->alias->ptr(), field_holder->alias->length())))
+ DBUG_RETURN(error_num);
+ } else {
+ if ((error_num = fields->add_field(field)))
+ {
+ DBUG_RETURN(error_num);
+ }
}
+ DBUG_RETURN(0);
}
- DBUG_RETURN(0);
}
}
}
@@ -9217,6 +9516,14 @@ int spider_db_open_item_string(
goto end;
}
}
+ if (str->charset() != tmp_str2->charset())
+ {
+ if ((error_num = spider_db_append_charset_name_before_string(str,
+ tmp_str2->charset())))
+ {
+ goto end;
+ }
+ }
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 +
tmp_str2->length() * 2))
{
@@ -9226,7 +9533,8 @@ int spider_db_open_item_string(
if (!thd)
tmp_str.mem_calc();
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
- str->append_escape_string(tmp_str2->ptr(), tmp_str2->length());
+ str->append_escape_string(tmp_str2->ptr(), tmp_str2->length(),
+ tmp_str2->charset());
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
{
error_num = HA_ERR_OUT_OF_MEM;
diff --git a/storage/spider/spd_db_conn.h b/storage/spider/spd_db_conn.h
index e3f95f7b28d..6fdb4b694ae 100644
--- a/storage/spider/spd_db_conn.h
+++ b/storage/spider/spd_db_conn.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -429,6 +430,14 @@ int spider_db_append_name_with_quote_str_internal(
uint dbton_id
);
+int spider_db_append_name_with_quote_str_internal(
+ spider_string *str,
+ const char *name,
+ int length,
+ CHARSET_INFO *cs,
+ uint dbton_id
+);
+
int spider_db_append_select(
ha_spider *spider
);
@@ -472,6 +481,11 @@ int spider_db_append_key_where(
ha_spider *spider
);
+int spider_db_append_charset_name_before_string(
+ spider_string *str,
+ CHARSET_INFO *cs
+);
+
#ifdef HANDLER_HAS_DIRECT_AGGREGATE
int spider_db_refetch_for_item_sum_funcs(
ha_spider *spider
@@ -692,7 +706,14 @@ int spider_db_show_table_status(
uint flag
);
-int spider_db_show_records(
+int spider_db_simple_action(
+ uint simple_action,
+ spider_db_handler *db_handler,
+ int link_idx
+);
+
+int spider_db_simple_action(
+ uint simple_action,
ha_spider *spider,
int link_idx,
bool pre_call
@@ -725,6 +746,7 @@ int spider_db_bulk_insert_init(
int spider_db_bulk_insert(
ha_spider *spider,
TABLE *table,
+ ha_copy_info *copy_info,
bool bulk_end
);
@@ -768,13 +790,15 @@ int spider_db_direct_update(
TABLE *table,
KEY_MULTI_RANGE *ranges,
uint range_count,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
);
#else
int spider_db_direct_update(
ha_spider *spider,
TABLE *table,
- ha_rows *update_rows
+ ha_rows *update_rows,
+ ha_rows *found_rows
);
#endif
#endif
diff --git a/storage/spider/spd_db_handlersocket.cc b/storage/spider/spd_db_handlersocket.cc
index 1e42838f40a..b8e4c0e705a 100644
--- a/storage/spider/spd_db_handlersocket.cc
+++ b/storage/spider/spd_db_handlersocket.cc
@@ -740,15 +740,7 @@ SPIDER_DB_ROW *spider_db_handlersocket_result::fetch_row_from_tmp_table(
int spider_db_handlersocket_result::fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
) {
DBUG_ENTER("spider_db_handlersocket_result::fetch_table_status");
DBUG_PRINT("info",("spider this=%p", this));
@@ -1663,6 +1655,22 @@ uint spider_db_handlersocket::affected_rows()
DBUG_RETURN((uint) my_strtoll10(hs_row->begin(), (char**) NULL, &error_num));
}
+uint spider_db_handlersocket::matched_rows()
+{
+ DBUG_ENTER("spider_db_handlersocket::matched_rows");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(0);
+}
+
+bool spider_db_handlersocket::inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+) {
+ DBUG_ENTER("spider_db_handlersocket::inserted_info");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
ulonglong spider_db_handlersocket::last_insert_id()
{
DBUG_ENTER("spider_db_handlersocket::last_insert_id");
@@ -1839,6 +1847,40 @@ int spider_db_handlersocket::set_sql_log_off(
DBUG_RETURN(0);
}
+bool spider_db_handlersocket::set_wait_timeout_in_bulk_sql()
+{
+ DBUG_ENTER("spider_db_handlersocket::set_wait_timeout_in_bulk_sql");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
+int spider_db_handlersocket::set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+) {
+ DBUG_ENTER("spider_db_handlersocket::set_wait_timeout");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
+bool spider_db_handlersocket::set_sql_mode_in_bulk_sql()
+{
+ DBUG_ENTER("spider_db_handlersocket::set_sql_mode_in_bulk_sql");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
+int spider_db_handlersocket::set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+) {
+ DBUG_ENTER("spider_db_handlersocket::set_sql_mode");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
bool spider_db_handlersocket::set_time_zone_in_bulk_sql()
{
DBUG_ENTER("spider_db_handlersocket::set_time_zone_in_bulk_sql");
@@ -2478,6 +2520,57 @@ int spider_db_handlersocket_util::append_name_with_charset(
DBUG_RETURN(0);
}
+int spider_db_handlersocket_util::append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_handlersocket_util::append_name");
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ if ((error_num = spider_db_append_name_with_quote_str_internal(
+ str, name, name_length, dbton_id)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
+int spider_db_handlersocket_util::append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_handlersocket_util::append_name_with_charset");
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ if ((error_num = spider_db_append_name_with_quote_str_internal(
+ str, name, name_length, name_charset, dbton_id)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
bool spider_db_handlersocket_util::is_name_quote(
const char head_code
) {
@@ -2675,6 +2768,26 @@ int spider_db_handlersocket_util::append_sql_log_off(
DBUG_RETURN(0);
}
+int spider_db_handlersocket_util::append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+) {
+ DBUG_ENTER("spider_db_handlersocket_util::append_wait_timeout");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
+int spider_db_handlersocket_util::append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+) {
+ DBUG_ENTER("spider_db_handlersocket_util::append_sql_mode");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
int spider_db_handlersocket_util::append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -5145,7 +5258,7 @@ int spider_handlersocket_handler::append_open_handler(
share->tgt_dbs[spider->conn_link_idx[link_idx]],
share->tgt_table_names[spider->conn_link_idx[link_idx]],
spider->active_index < MAX_KEY ?
- table->s->key_info[spider->active_index].name :
+ table->key_info[spider->active_index].name :
"0",
str->c_ptr_safe(),
&request_key
@@ -5786,15 +5899,7 @@ int spider_handlersocket_handler::show_table_status(
DBUG_ENTER("spider_handlersocket_show_table_status");
res.fetch_table_status(
sts_mode,
- share->records,
- share->mean_rec_length,
- share->data_file_length,
- share->max_data_file_length,
- share->index_file_length,
- auto_increment_value,
- share->create_time,
- share->update_time,
- share->check_time
+ share->stat
);
if (auto_increment_value > share->lgtm_tblhnd_share->auto_increment_value)
{
diff --git a/storage/spider/spd_db_handlersocket.h b/storage/spider/spd_db_handlersocket.h
index d1b59386cbe..19a4a391ed6 100644
--- a/storage/spider/spd_db_handlersocket.h
+++ b/storage/spider/spd_db_handlersocket.h
@@ -34,6 +34,17 @@ public:
uint name_length,
CHARSET_INFO *name_charset
);
+ int append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+ );
+ int append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+ );
bool is_name_quote(
const char head_code
);
@@ -59,6 +70,14 @@ public:
spider_string *str,
bool sql_log_off
);
+ int append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+ );
+ int append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+ );
int append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -211,15 +230,7 @@ public:
);
int fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
);
int fetch_table_records(
int mode,
@@ -324,6 +335,11 @@ public:
);
int next_result();
uint affected_rows();
+ uint matched_rows();
+ bool inserted_info(
+ spider_db_handler *handler,
+ spider_copy_info *copy_info
+ );
ulonglong last_insert_id();
int set_character_set(
const char *csname
@@ -380,6 +396,16 @@ public:
bool sql_log_off,
int *need_mon
);
+ bool set_wait_timeout_in_bulk_sql();
+ int set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+ );
+ bool set_sql_mode_in_bulk_sql();
+ int set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+ );
bool set_time_zone_in_bulk_sql();
int set_time_zone(
Time_zone *time_zone,
diff --git a/storage/spider/spd_db_include.cc b/storage/spider/spd_db_include.cc
index 2910aa97690..7f600142187 100644
--- a/storage/spider/spd_db_include.cc
+++ b/storage/spider/spd_db_include.cc
@@ -41,6 +41,16 @@ spider_db_result::spider_db_result(
DBUG_VOID_RETURN;
}
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+int spider_db_result::fetch_table_checksum(
+ ha_spider *spider
+) {
+ DBUG_ENTER("spider_db_result::fetch_table_checksum");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(0);
+}
+#endif
+
spider_db_conn::spider_db_conn(
SPIDER_CONN *in_conn
) : conn(in_conn), dbton_id(in_conn->dbton_id)
@@ -49,3 +59,20 @@ spider_db_conn::spider_db_conn(
DBUG_PRINT("info",("spider this=%p", this));
DBUG_VOID_RETURN;
}
+
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+bool spider_db_share::checksum_support()
+{
+ DBUG_ENTER("spider_db_share::checksum_support");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
+int spider_db_handler::checksum_table(
+ int link_idx
+) {
+ DBUG_ENTER("spider_db_handler::checksum_table");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(0);
+}
+#endif
diff --git a/storage/spider/spd_db_include.h b/storage/spider/spd_db_include.h
index d51770c1a77..046fe66435c 100644
--- a/storage/spider/spd_db_include.h
+++ b/storage/spider/spd_db_include.h
@@ -157,6 +157,8 @@ typedef st_spider_result SPIDER_RESULT;
#define SPIDER_SQL_MBR_DISJOINT_LEN (sizeof(SPIDER_SQL_MBR_DISJOINT_STR) - 1)
#define SPIDER_SQL_NOT_BETWEEN_STR "not between"
#define SPIDER_SQL_NOT_BETWEEN_LEN (sizeof(SPIDER_SQL_NOT_BETWEEN_STR) - 1)
+#define SPIDER_SQL_TO_FLOAT_STR "/* create function to_float(a decimal(20,6)) returns float return a */ to_float("
+#define SPIDER_SQL_TO_FLOAT_LEN (sizeof(SPIDER_SQL_TO_FLOAT_STR) - 1)
#define SPIDER_SQL_IN_STR "in("
#define SPIDER_SQL_IN_LEN (sizeof(SPIDER_SQL_IN_STR) - 1)
#define SPIDER_SQL_NOT_IN_STR "not in("
@@ -181,6 +183,8 @@ typedef st_spider_result SPIDER_RESULT;
#define SPIDER_SQL_AS_TIME_LEN (sizeof(SPIDER_SQL_AS_TIME_STR) - 1)
#define SPIDER_SQL_AS_BINARY_STR " as binary"
#define SPIDER_SQL_AS_BINARY_LEN (sizeof(SPIDER_SQL_AS_BINARY_STR) - 1)
+#define SPIDER_SQL_AS_FLOAT_STR " as float"
+#define SPIDER_SQL_AS_FLOAT_LEN (sizeof(SPIDER_SQL_AS_FLOAT_STR) - 1)
#define SPIDER_SQL_IS_TRUE_STR " is true"
#define SPIDER_SQL_IS_TRUE_LEN (sizeof(SPIDER_SQL_IS_TRUE_STR) - 1)
#define SPIDER_SQL_IS_NOT_TRUE_STR " is not true"
@@ -251,6 +255,7 @@ typedef struct st_spider_transaction SPIDER_TRX;
typedef struct st_spider_share SPIDER_SHARE;
class ha_spider;
class spider_db_copy_table;
+class spider_db_handler;
class spider_string
{
@@ -533,6 +538,11 @@ public:
const char *st,
uint len
);
+ void append_escape_string(
+ const char *st,
+ uint len,
+ CHARSET_INFO *cs
+ );
bool append_for_single_quote(
const char *st,
uint len
@@ -812,6 +822,17 @@ public:
uint name_length,
CHARSET_INFO *name_charset
) = 0;
+ virtual int append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+ ) = 0;
+ virtual int append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+ ) = 0;
virtual bool is_name_quote(
const char head_code
) = 0;
@@ -837,6 +858,14 @@ public:
spider_string *str,
bool sql_log_off
) = 0;
+ virtual int append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+ ) = 0;
+ virtual int append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+ ) = 0;
virtual int append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -979,20 +1008,17 @@ public:
) = 0;
virtual int fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
) = 0;
virtual int fetch_table_records(
int mode,
ha_rows &records
) = 0;
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ virtual int fetch_table_checksum(
+ ha_spider *spider
+ );
+#endif
virtual int fetch_table_cardinality(
int mode,
TABLE *table,
@@ -1080,6 +1106,11 @@ public:
) = 0;
virtual int next_result() = 0;
virtual uint affected_rows() = 0;
+ virtual uint matched_rows() = 0;
+ virtual bool inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+ ) = 0;
virtual ulonglong last_insert_id() = 0;
virtual int set_character_set(
const char *csname
@@ -1136,6 +1167,16 @@ public:
bool sql_log_off,
int *need_mon
) = 0;
+ virtual bool set_wait_timeout_in_bulk_sql() = 0;
+ virtual int set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+ ) = 0;
+ virtual bool set_sql_mode_in_bulk_sql() = 0;
+ virtual int set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+ ) = 0;
virtual bool set_time_zone_in_bulk_sql() = 0;
virtual int set_time_zone(
Time_zone *time_zone,
@@ -1262,6 +1303,9 @@ public:
spider_string *str
) = 0;
#endif
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ virtual bool checksum_support();
+#endif
};
class spider_db_handler
@@ -1630,6 +1674,11 @@ public:
virtual int show_records(
int link_idx
) = 0;
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ virtual int checksum_table(
+ int link_idx
+ );
+#endif
virtual int show_last_insert_id(
int link_idx,
ulonglong &last_insert_id
diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc
index 0329509c748..015ca373577 100644
--- a/storage/spider/spd_db_mysql.cc
+++ b/storage/spider/spd_db_mysql.cc
@@ -56,6 +56,8 @@ extern HASH spider_open_connections;
extern HASH spider_ipport_conns;
extern SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE];
extern const char spider_dig_upper[];
+extern const char **spd_mysqld_unix_port;
+extern uint *spd_mysqld_port;
spider_db_mysql_util spider_db_mysql_utility;
spider_db_mariadb_util spider_db_mariadb_utility;
@@ -88,6 +90,12 @@ static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR;
#define SPIDER_SQL_SQL_LOG_ON_STR "set session sql_log_off = 1"
#define SPIDER_SQL_SQL_LOG_ON_LEN sizeof(SPIDER_SQL_SQL_LOG_ON_STR) - 1
+#define SPIDER_SQL_WAIT_TIMEOUT_STR "set session wait_timeout = "
+#define SPIDER_SQL_WAIT_TIMEOUT_LEN sizeof(SPIDER_SQL_WAIT_TIMEOUT_STR) - 1
+
+#define SPIDER_SQL_SQL_MODE_STR "set session sql_mode = '"
+#define SPIDER_SQL_SQL_MODE_LEN sizeof(SPIDER_SQL_SQL_MODE_STR) - 1
+
#define SPIDER_SQL_TIME_ZONE_STR "set session time_zone = '"
#define SPIDER_SQL_TIME_ZONE_LEN sizeof(SPIDER_SQL_TIME_ZONE_STR) - 1
@@ -123,7 +131,7 @@ static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR;
#define SPIDER_SQL_SHOW_TABLE_STATUS_STR "show table status from "
#define SPIDER_SQL_SHOW_TABLE_STATUS_LEN sizeof(SPIDER_SQL_SHOW_TABLE_STATUS_STR) - 1
-#define SPIDER_SQL_SELECT_TABLES_STATUS_STR "select `table_rows`,`avg_row_length`,`data_length`,`max_data_length`,`index_length`,`auto_increment`,`create_time`,`update_time`,`check_time` from `information_schema`.`tables` where `table_schema` = "
+#define SPIDER_SQL_SELECT_TABLES_STATUS_STR "select `table_rows`,`avg_row_length`,`data_length`,`max_data_length`,`index_length`,`auto_increment`,`create_time`,`update_time`,`check_time`,`checksum` from `information_schema`.`tables` where `table_schema` = "
#define SPIDER_SQL_SELECT_TABLES_STATUS_LEN sizeof(SPIDER_SQL_SELECT_TABLES_STATUS_STR) - 1
#define SPIDER_SQL_SHOW_WARNINGS_STR "show warnings"
#define SPIDER_SQL_SHOW_WARNINGS_LEN sizeof(SPIDER_SQL_SHOW_WARNINGS_STR) - 1
@@ -151,6 +159,15 @@ static const char *name_quote_str = SPIDER_SQL_NAME_QUOTE_STR;
#define SPIDER_SQL_USING_HASH_LEN sizeof(SPIDER_SQL_USING_HASH_STR) - 1
#endif
+#define SPIDER_SQL_SHOW_RECORDS_RECORDS_POS 0
+#define SPIDER_SQL_EXPLAIN_SELECT_RECORDS_POS 8
+
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+#define SPIDER_SQL_CHECKSUM_CHECKSUM_POS 1
+#define SPIDER_SQL_CHECKSUM_TABLE_STR "checksum table "
+#define SPIDER_SQL_CHECKSUM_TABLE_LEN (sizeof(SPIDER_SQL_CHECKSUM_TABLE_STR) - 1)
+#endif
+
#define SPIDER_SQL_LIKE_STR " like "
#define SPIDER_SQL_LIKE_LEN (sizeof(SPIDER_SQL_LIKE_STR) - 1)
#define SPIDER_SQL_LIMIT1_STR " limit 1"
@@ -167,6 +184,11 @@ static uchar SPIDER_SQL_LINESTRING_HEAD_STR[] =
{0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00};
#define SPIDER_SQL_LINESTRING_HEAD_LEN sizeof(SPIDER_SQL_LINESTRING_HEAD_STR)
+#define SPIDER_SQL_DIRECT_INSERT_KIND_INSERT 0
+#define SPIDER_SQL_DIRECT_INSERT_KIND_REPLACE 1
+#define SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE 2
+#define SPIDER_SQL_DIRECT_INSERT_KIND_DUP_UPDATE 3
+
static const char *spider_db_table_lock_str[] =
{
" read local,",
@@ -784,15 +806,7 @@ SPIDER_DB_ROW *spider_db_mbase_result::fetch_row_from_tmp_table(
int spider_db_mbase_result::fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
) {
int error_num;
MYSQL_ROW mysql_row;
@@ -831,47 +845,47 @@ int spider_db_mbase_result::fetch_table_status(
}
if (mysql_row[4])
- records =
+ stat.records =
(ha_rows) my_strtoll10(mysql_row[4], (char**) NULL, &error_num);
else
- records = (ha_rows) 0;
+ stat.records = (ha_rows) 0;
DBUG_PRINT("info",
- ("spider records=%lld", records));
+ ("spider records=%lld", stat.records));
if (mysql_row[5])
- mean_rec_length =
+ stat.mean_rec_length =
(ulong) my_strtoll10(mysql_row[5], (char**) NULL, &error_num);
else
- mean_rec_length = 0;
+ stat.mean_rec_length = 0;
DBUG_PRINT("info",
- ("spider mean_rec_length=%lu", mean_rec_length));
+ ("spider mean_rec_length=%lu", stat.mean_rec_length));
if (mysql_row[6])
- data_file_length =
+ stat.data_file_length =
(ulonglong) my_strtoll10(mysql_row[6], (char**) NULL, &error_num);
else
- data_file_length = 0;
+ stat.data_file_length = 0;
DBUG_PRINT("info",
- ("spider data_file_length=%lld", data_file_length));
+ ("spider data_file_length=%lld", stat.data_file_length));
if (mysql_row[7])
- max_data_file_length =
+ stat.max_data_file_length =
(ulonglong) my_strtoll10(mysql_row[7], (char**) NULL, &error_num);
else
- max_data_file_length = 0;
+ stat.max_data_file_length = 0;
DBUG_PRINT("info",
- ("spider max_data_file_length=%lld", max_data_file_length));
+ ("spider max_data_file_length=%lld", stat.max_data_file_length));
if (mysql_row[8])
- index_file_length =
+ stat.index_file_length =
(ulonglong) my_strtoll10(mysql_row[8], (char**) NULL, &error_num);
else
- index_file_length = 0;
+ stat.index_file_length = 0;
DBUG_PRINT("info",
- ("spider index_file_length=%lld", index_file_length));
+ ("spider index_file_length=%lld", stat.index_file_length));
if (mysql_row[10])
- auto_increment_value =
+ stat.auto_increment_value =
(ulonglong) my_strtoll10(mysql_row[10], (char**) NULL, &error_num);
else
- auto_increment_value = 1;
+ stat.auto_increment_value = 1;
DBUG_PRINT("info",
- ("spider auto_increment_value=%lld", auto_increment_value));
+ ("spider auto_increment_value=%lld", stat.auto_increment_value));
if (mysql_row[11])
{
#ifdef SPIDER_HAS_TIME_STATUS
@@ -880,19 +894,19 @@ int spider_db_mbase_result::fetch_table_status(
SPIDER_str_to_datetime(mysql_row[11], strlen(mysql_row[11]),
&mysql_time, 0, &time_status);
#ifdef MARIADB_BASE_VERSION
- create_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.create_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- create_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.create_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
} else
- create_time = (time_t) 0;
+ stat.create_time = (time_t) 0;
#ifndef DBUG_OFF
{
struct tm *ts, tmp_ts;
char buf[80];
- ts = localtime_r(&create_time, &tmp_ts);
+ ts = localtime_r(&stat.create_time, &tmp_ts);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts);
DBUG_PRINT("info",("spider create_time=%s", buf));
}
@@ -905,19 +919,19 @@ int spider_db_mbase_result::fetch_table_status(
SPIDER_str_to_datetime(mysql_row[12], strlen(mysql_row[12]),
&mysql_time, 0, &time_status);
#ifdef MARIADB_BASE_VERSION
- update_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.update_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- update_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.update_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
} else
- update_time = (time_t) 0;
+ stat.update_time = (time_t) 0;
#ifndef DBUG_OFF
{
struct tm *ts, tmp_ts;
char buf[80];
- ts = localtime_r(&update_time, &tmp_ts);
+ ts = localtime_r(&stat.update_time, &tmp_ts);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts);
DBUG_PRINT("info",("spider update_time=%s", buf));
}
@@ -930,66 +944,77 @@ int spider_db_mbase_result::fetch_table_status(
SPIDER_str_to_datetime(mysql_row[13], strlen(mysql_row[13]),
&mysql_time, 0, &time_status);
#ifdef MARIADB_BASE_VERSION
- check_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.check_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- check_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.check_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
} else
- check_time = (time_t) 0;
+ stat.check_time = (time_t) 0;
#ifndef DBUG_OFF
{
struct tm *ts, tmp_ts;
char buf[80];
- ts = localtime_r(&check_time, &tmp_ts);
+ ts = localtime_r(&stat.check_time, &tmp_ts);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts);
DBUG_PRINT("info",("spider check_time=%s", buf));
}
#endif
+ if (mysql_row[15])
+ {
+ stat.checksum_null = FALSE;
+ stat.checksum =
+ (ha_checksum) my_strtoll10(mysql_row[15], (char**) NULL, &error_num);
+ DBUG_PRINT("info", ("spider checksum=%lu", (ulong) stat.checksum));
+ } else {
+ stat.checksum_null = TRUE;
+ stat.checksum = (ha_checksum) 0;
+ DBUG_PRINT("info", ("spider checksum is null"));
+ }
} else {
if (mysql_row[0])
- records =
+ stat.records =
(ha_rows) my_strtoll10(mysql_row[0], (char**) NULL, &error_num);
else
- records = (ha_rows) 0;
+ stat.records = (ha_rows) 0;
DBUG_PRINT("info",
- ("spider records=%lld", records));
+ ("spider records=%lld", stat.records));
if (mysql_row[1])
- mean_rec_length =
+ stat.mean_rec_length =
(ulong) my_strtoll10(mysql_row[1], (char**) NULL, &error_num);
else
- mean_rec_length = 0;
+ stat.mean_rec_length = 0;
DBUG_PRINT("info",
- ("spider mean_rec_length=%lu", mean_rec_length));
+ ("spider mean_rec_length=%lu", stat.mean_rec_length));
if (mysql_row[2])
- data_file_length =
+ stat.data_file_length =
(ulonglong) my_strtoll10(mysql_row[2], (char**) NULL, &error_num);
else
- data_file_length = 0;
+ stat.data_file_length = 0;
DBUG_PRINT("info",
- ("spider data_file_length=%lld", data_file_length));
+ ("spider data_file_length=%lld", stat.data_file_length));
if (mysql_row[3])
- max_data_file_length =
+ stat.max_data_file_length =
(ulonglong) my_strtoll10(mysql_row[3], (char**) NULL, &error_num);
else
- max_data_file_length = 0;
+ stat.max_data_file_length = 0;
DBUG_PRINT("info",
- ("spider max_data_file_length=%lld", max_data_file_length));
+ ("spider max_data_file_length=%lld", stat.max_data_file_length));
if (mysql_row[4])
- index_file_length =
+ stat.index_file_length =
(ulonglong) my_strtoll10(mysql_row[4], (char**) NULL, &error_num);
else
- index_file_length = 0;
+ stat.index_file_length = 0;
DBUG_PRINT("info",
- ("spider index_file_length=%lld", index_file_length));
+ ("spider index_file_length=%lld", stat.index_file_length));
if (mysql_row[5])
- auto_increment_value =
+ stat.auto_increment_value =
(ulonglong) my_strtoll10(mysql_row[5], (char**) NULL, &error_num);
else
- auto_increment_value = 1;
+ stat.auto_increment_value = 1;
DBUG_PRINT("info",
- ("spider auto_increment_value=%lld", auto_increment_value));
+ ("spider auto_increment_value=%lld", stat.auto_increment_value));
if (mysql_row[6])
{
#ifdef SPIDER_HAS_TIME_STATUS
@@ -998,19 +1023,19 @@ int spider_db_mbase_result::fetch_table_status(
SPIDER_str_to_datetime(mysql_row[6], strlen(mysql_row[6]),
&mysql_time, 0, &time_status);
#ifdef MARIADB_BASE_VERSION
- create_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.create_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- create_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.create_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
} else
- create_time = (time_t) 0;
+ stat.create_time = (time_t) 0;
#ifndef DBUG_OFF
{
struct tm *ts, tmp_ts;
char buf[80];
- ts = localtime_r(&create_time, &tmp_ts);
+ ts = localtime_r(&stat.create_time, &tmp_ts);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts);
DBUG_PRINT("info",("spider create_time=%s", buf));
}
@@ -1023,19 +1048,19 @@ int spider_db_mbase_result::fetch_table_status(
SPIDER_str_to_datetime(mysql_row[7], strlen(mysql_row[7]),
&mysql_time, 0, &time_status);
#ifdef MARIADB_BASE_VERSION
- update_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.update_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- update_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.update_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
} else
- update_time = (time_t) 0;
+ stat.update_time = (time_t) 0;
#ifndef DBUG_OFF
{
struct tm *ts, tmp_ts;
char buf[80];
- ts = localtime_r(&update_time, &tmp_ts);
+ ts = localtime_r(&stat.update_time, &tmp_ts);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts);
DBUG_PRINT("info",("spider update_time=%s", buf));
}
@@ -1048,34 +1073,46 @@ int spider_db_mbase_result::fetch_table_status(
SPIDER_str_to_datetime(mysql_row[8], strlen(mysql_row[8]),
&mysql_time, 0, &time_status);
#ifdef MARIADB_BASE_VERSION
- check_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.check_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- check_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat.check_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
} else
- check_time = (time_t) 0;
+ stat.check_time = (time_t) 0;
#ifndef DBUG_OFF
{
struct tm *ts, tmp_ts;
char buf[80];
- ts = localtime_r(&check_time, &tmp_ts);
+ ts = localtime_r(&stat.check_time, &tmp_ts);
strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ts);
DBUG_PRINT("info",("spider check_time=%s", buf));
}
#endif
+ if (mysql_row[9])
+ {
+ stat.checksum_null = FALSE;
+ stat.checksum =
+ (ha_checksum) my_strtoll10(mysql_row[9], (char**) NULL, &error_num);
+ DBUG_PRINT("info", ("spider checksum=%lu", (ulong) stat.checksum));
+ } else {
+ stat.checksum_null = TRUE;
+ stat.checksum = (ha_checksum) 0;
+ DBUG_PRINT("info", ("spider checksum is null"));
+ }
}
DBUG_RETURN(0);
}
-int spider_db_mbase_result::fetch_table_records(
- int mode,
- ha_rows &records
+int spider_db_mbase_result::fetch_simple_action(
+ uint simple_action,
+ uint position,
+ void *param
) {
int error_num;
MYSQL_ROW mysql_row;
- DBUG_ENTER("spider_db_mbase_result::fetch_table_records");
+ DBUG_ENTER("spider_db_mbase_result::fetch_simple_action");
DBUG_PRINT("info",("spider this=%p", this));
if (!(mysql_row = mysql_fetch_row(db_result)))
{
@@ -1088,32 +1125,78 @@ int spider_db_mbase_result::fetch_table_records(
}
DBUG_RETURN(ER_QUERY_ON_FOREIGN_DATA_SOURCE);
}
- if (mode == 1)
+ if (num_fields() <= position)
{
- if (mysql_row[0])
- {
- records =
- (ha_rows) my_strtoll10(mysql_row[0], (char**) NULL, &error_num);
- } else
- records = (ha_rows) 0;
- DBUG_PRINT("info",
- ("spider records=%lld", records));
- } else {
- if (num_fields() != 10)
+ DBUG_RETURN(ER_QUERY_ON_FOREIGN_DATA_SOURCE);
+ }
+ switch (simple_action)
+ {
+ case SPIDER_SIMPLE_RECORDS:
{
- DBUG_RETURN(ER_QUERY_ON_FOREIGN_DATA_SOURCE);
+ ha_rows *records = (ha_rows *) param;
+ if (mysql_row[position])
+ {
+ *records =
+ (ha_rows) my_strtoll10(mysql_row[position], (char**) NULL,
+ &error_num);
+ } else {
+ *records = (ha_rows) 0;
+ }
+ DBUG_PRINT("info", ("spider records=%lld", *records));
+ break;
}
-
- if (mysql_row[8])
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ case SPIDER_SIMPLE_CHECKSUM_TABLE:
{
- records =
- (ha_rows) my_strtoll10(mysql_row[8], (char**) NULL, &error_num);
- } else
- records = 0;
+ ha_spider *spider = (ha_spider *) param;
+ if (mysql_row[position])
+ {
+ spider->checksum_val =
+ (ha_checksum) my_strtoll10(mysql_row[position], (char**) NULL,
+ &error_num);
+ DBUG_PRINT("info", ("spider checksum=%llu", (ulonglong)spider->checksum_val));
+ spider->checksum_null = FALSE;
+ } else {
+ spider->checksum_null = TRUE;
+ DBUG_PRINT("info", ("spider checksum is null"));
+ }
+ break;
+ }
+#endif
+ default:
+ DBUG_ASSERT(0);
+ break;
}
DBUG_RETURN(0);
}
+int spider_db_mbase_result::fetch_table_records(
+ int mode,
+ ha_rows &records
+) {
+ DBUG_ENTER("spider_db_mbase_result::fetch_table_records");
+ DBUG_PRINT("info",("spider this=%p", this));
+ if (mode == 1)
+ {
+ DBUG_RETURN(fetch_simple_action(SPIDER_SIMPLE_RECORDS,
+ SPIDER_SQL_SHOW_RECORDS_RECORDS_POS, &records));
+ } else {
+ DBUG_RETURN(fetch_simple_action(SPIDER_SIMPLE_RECORDS,
+ SPIDER_SQL_EXPLAIN_SELECT_RECORDS_POS, &records));
+ }
+}
+
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+int spider_db_mbase_result::fetch_table_checksum(
+ ha_spider *spider
+) {
+ DBUG_ENTER("spider_db_mbase_result::fetch_table_checksum");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(fetch_simple_action(SPIDER_SIMPLE_CHECKSUM_TABLE,
+ SPIDER_SQL_CHECKSUM_CHECKSUM_POS, spider));
+}
+#endif
+
int spider_db_mbase_result::fetch_table_cardinality(
int mode,
TABLE *table,
@@ -1897,6 +1980,30 @@ int spider_db_mbase::connect(
conn->tgt_default_group);
}
+ if (!spider_param_same_server_link(thd))
+ {
+ if (!strcmp(tgt_host, my_localhost))
+ {
+ if (!strcmp(tgt_socket, *spd_mysqld_unix_port))
+ {
+ my_printf_error(ER_SPIDER_SAME_SERVER_LINK_NUM,
+ ER_SPIDER_SAME_SERVER_LINK_STR1, MYF(0),
+ tgt_host, tgt_socket);
+ DBUG_RETURN(ER_SPIDER_SAME_SERVER_LINK_NUM);
+ }
+ } else if (!strcmp(tgt_host, "127.0.0.1") ||
+ !strcmp(tgt_host, glob_hostname))
+ {
+ if (tgt_port == (long) *spd_mysqld_port)
+ {
+ my_printf_error(ER_SPIDER_SAME_SERVER_LINK_NUM,
+ ER_SPIDER_SAME_SERVER_LINK_STR2, MYF(0),
+ tgt_host, tgt_port);
+ DBUG_RETURN(ER_SPIDER_SAME_SERVER_LINK_NUM);
+ }
+ }
+ }
+
if (connect_mutex)
pthread_mutex_lock(&spider_open_conn_mutex);
/* tgt_db not use */
@@ -1948,6 +2055,9 @@ int spider_db_mbase::connect(
connect_retry_count--;
my_sleep((ulong) connect_retry_interval);
} else {
+#ifdef SPIDER_NET_HAS_THD
+ db_conn->net.thd = NULL;
+#endif
if (connect_mutex)
pthread_mutex_unlock(&spider_open_conn_mutex);
break;
@@ -2339,6 +2449,81 @@ uint spider_db_mbase::affected_rows()
DBUG_RETURN((uint) last_used_con->affected_rows);
}
+uint spider_db_mbase::matched_rows()
+{
+ MYSQL *last_used_con;
+ DBUG_ENTER("spider_db_mysql::matched_rows");
+ DBUG_PRINT("info", ("spider this=%p", this));
+#if MYSQL_VERSION_ID < 50500
+ last_used_con = db_conn->last_used_con;
+#else
+ last_used_con = db_conn;
+#endif
+ /* Rows matched: 65 Changed: 65 Warnings: 0 */
+ const char *info = last_used_con->info;
+ if (!info)
+ DBUG_RETURN(0);
+ DBUG_PRINT("info", ("spider info=%s", info));
+ const char *begin = strstr(info, "Rows matched: ");
+ if (!begin)
+ DBUG_RETURN(0);
+ DBUG_RETURN(atoi(begin + strlen("Rows matched: ")));
+}
+
+bool spider_db_mbase::inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+) {
+ MYSQL *last_used_con;
+ uchar direct_insert_kind =
+ ((spider_mbase_handler *) handler)->direct_insert_kind;
+ DBUG_ENTER("spider_db_mysql::inserted_info");
+ DBUG_PRINT("info", ("spider this=%p", this));
+ if (direct_insert_kind == SPIDER_SQL_DIRECT_INSERT_KIND_INSERT)
+ {
+ DBUG_RETURN(TRUE);
+ }
+#if MYSQL_VERSION_ID < 50500
+ last_used_con = db_conn->last_used_con;
+#else
+ last_used_con = db_conn;
+#endif
+ /* Records: 10 Duplicates: 4 Warnings: 0 */
+ const char *info = last_used_con->info;
+ if (!info)
+ DBUG_RETURN(FALSE);
+ DBUG_PRINT("info", ("spider info=%s", info));
+ const char *begin = strstr(info, "Records: ");
+ if (!begin)
+ DBUG_RETURN(FALSE);
+ begin += strlen("Records: ");
+ uint records = atoi(begin);
+ begin = strstr(begin, "Duplicates: ");
+ if (!begin)
+ DBUG_RETURN(FALSE);
+ uint duplicates = atoi(begin + strlen("Duplicates: "));
+ copy_info->records+= records;
+ switch (direct_insert_kind)
+ {
+ case SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE:
+ copy_info->copied+= duplicates;
+ break;
+ case SPIDER_SQL_DIRECT_INSERT_KIND_REPLACE:
+ copy_info->copied+= records;
+ copy_info->deleted+= duplicates;
+ break;
+ case SPIDER_SQL_DIRECT_INSERT_KIND_DUP_UPDATE:
+ copy_info->touched+= (last_used_con->affected_rows - (duplicates * 2));
+ copy_info->copied+= (last_used_con->affected_rows - duplicates);
+ copy_info->updated+= duplicates;
+ break;
+ default:
+ DBUG_ASSERT(0);
+ DBUG_RETURN(FALSE);
+ }
+ DBUG_RETURN(TRUE);
+}
+
ulonglong spider_db_mbase::last_insert_id()
{
MYSQL *last_used_con;
@@ -2738,6 +2923,92 @@ int spider_db_mbase::set_sql_log_off(
DBUG_RETURN(0);
}
+bool spider_db_mbase::set_wait_timeout_in_bulk_sql()
+{
+ DBUG_ENTER("spider_db_mbase::set_wait_timeout_in_bulk_sql");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(TRUE);
+}
+
+int spider_db_mbase::set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+) {
+ char sql_buf[MAX_FIELD_WIDTH];
+ char timeout_str[SPIDER_SQL_INT_LEN];
+ int timeout_str_length;
+ spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin);
+ DBUG_ENTER("spider_db_mbase::set_wait_timeout");
+ DBUG_PRINT("info",("spider this=%p", this));
+ sql_str.init_calc_mem(264);
+ sql_str.length(0);
+ timeout_str_length =
+ my_sprintf(timeout_str, (timeout_str, "%d", wait_timeout));
+ if (sql_str.reserve(SPIDER_SQL_WAIT_TIMEOUT_LEN + timeout_str_length))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ sql_str.q_append(SPIDER_SQL_WAIT_TIMEOUT_STR, SPIDER_SQL_WAIT_TIMEOUT_LEN);
+ sql_str.q_append(timeout_str, timeout_str_length);
+ if (spider_db_query(
+ conn,
+ sql_str.ptr(),
+ sql_str.length(),
+ -1,
+ need_mon)
+ )
+ DBUG_RETURN(spider_db_errorno(conn));
+ SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos);
+ pthread_mutex_unlock(&conn->mta_conn_mutex);
+ DBUG_RETURN(0);
+}
+
+bool spider_db_mbase::set_sql_mode_in_bulk_sql()
+{
+ DBUG_ENTER("spider_db_mbase::set_sql_mode_in_bulk_sql");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(TRUE);
+}
+
+int spider_db_mbase::set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+) {
+ int error_num;
+ char sql_buf[MAX_FIELD_WIDTH];
+ spider_string sql_str(sql_buf, sizeof(sql_buf), &my_charset_bin);
+ DBUG_ENTER("spider_db_mbase::set_sql_mode");
+ DBUG_PRINT("info",("spider this=%p", this));
+ sql_str.init_calc_mem(265);
+ sql_str.length(0);
+ if (sql_str.reserve(SPIDER_SQL_SQL_MODE_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ sql_str.q_append(SPIDER_SQL_SQL_MODE_STR, SPIDER_SQL_SQL_MODE_LEN);
+ if ((error_num = spider_db_mbase_utility->append_sql_mode_internal(&sql_str, sql_mode)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (sql_str.length() > SPIDER_SQL_SQL_MODE_LEN)
+ {
+ sql_str.length(sql_str.length() - SPIDER_SQL_COMMA_LEN);
+ } else {
+ if (sql_str.reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ }
+ sql_str.q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ if (spider_db_query(
+ conn,
+ sql_str.ptr(),
+ sql_str.length(),
+ -1,
+ need_mon)
+ )
+ DBUG_RETURN(spider_db_errorno(conn));
+ SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos);
+ pthread_mutex_unlock(&conn->mta_conn_mutex);
+ DBUG_RETURN(0);
+}
+
bool spider_db_mbase::set_time_zone_in_bulk_sql()
{
DBUG_ENTER("spider_db_mbase::set_time_zone_in_bulk_sql");
@@ -3290,10 +3561,10 @@ void spider_db_mbase::set_dup_key_idx(
key_name_length = spider->share->tgt_pk_names_lengths[all_link_idx];
} else {
#ifdef SPIDER_use_LEX_CSTRING_for_KEY_Field_name
- key_name = table->s->key_info[roop_count].name.str;
- key_name_length = table->s->key_info[roop_count].name.length;
+ key_name = table->key_info[roop_count].name.str;
+ key_name_length = table->key_info[roop_count].name.length;
#else
- key_name = table->s->key_info[roop_count].name;
+ key_name = table->key_info[roop_count].name;
key_name_length = strlen(key_name);
#endif
}
@@ -3396,6 +3667,57 @@ int spider_db_mbase_util::append_name_with_charset(
DBUG_RETURN(0);
}
+int spider_db_mbase_util::append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_mbase_util::append_name");
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ if ((error_num = spider_db_append_name_with_quote_str_internal(
+ str, name, name_length, dbton_id)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
+int spider_db_mbase_util::append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_mbase_util::append_name_with_charset");
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ if ((error_num = spider_db_append_name_with_quote_str_internal(
+ str, name, name_length, name_charset, dbton_id)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
bool spider_db_mbase_util::is_name_quote(
const char head_code
) {
@@ -3414,20 +3736,22 @@ int spider_db_mbase_util::append_escaped_name_quote(
DBUG_RETURN(0);
}
-int spider_db_mbase_util::append_column_value(
+int spider_db_mariadb_util::append_column_value(
ha_spider *spider,
spider_string *str,
Field *field,
const uchar *new_ptr,
CHARSET_INFO *access_charset
) {
+ bool float_value = FALSE;
+ int error_num;
char buf[MAX_FIELD_WIDTH];
- spider_string tmp_str(buf, MAX_FIELD_WIDTH, &my_charset_bin);
+ spider_string tmp_str(buf, MAX_FIELD_WIDTH, field->charset());
String *ptr;
uint length;
THD *thd = field->table->in_use;
Time_zone *saved_time_zone = thd->variables.time_zone;
- DBUG_ENTER("spider_db_mbase_util::append_column_value");
+ DBUG_ENTER("spider_db_mariadb_util::append_column_value");
tmp_str.init_calc_mem(113);
thd->variables.time_zone = UTC;
@@ -3440,7 +3764,7 @@ int spider_db_mbase_util::append_column_value(
) {
length = uint2korr(new_ptr);
tmp_str.set_quick((char *) new_ptr + HA_KEY_BLOB_LENGTH, length,
- &my_charset_bin);
+ field->charset());
ptr = tmp_str.get_str();
} else if (field->type() == MYSQL_TYPE_GEOMETRY)
{
@@ -3526,6 +3850,10 @@ int spider_db_mbase_util::append_column_value(
} else {
ptr = field->val_str(tmp_str.get_str());
tmp_str.mem_calc();
+ if (field->type() == MYSQL_TYPE_FLOAT)
+ {
+ float_value = TRUE;
+ }
}
thd->variables.time_zone = saved_time_zone;
@@ -3556,6 +3884,14 @@ int spider_db_mbase_util::append_column_value(
if (field->result_type() == STRING_RESULT)
{
DBUG_PRINT("info", ("spider STRING_RESULT"));
+ if (str->charset() != field->charset())
+ {
+ if ((error_num = spider_db_append_charset_name_before_string(str,
+ field->charset())))
+ {
+ DBUG_RETURN(error_num);
+ }
+ }
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
@@ -3566,7 +3902,7 @@ int spider_db_mbase_util::append_column_value(
) {
DBUG_PRINT("info", ("spider append_escaped"));
char buf2[MAX_FIELD_WIDTH];
- spider_string tmp_str2(buf2, MAX_FIELD_WIDTH, access_charset);
+ spider_string tmp_str2(buf2, MAX_FIELD_WIDTH, field->charset());
tmp_str2.init_calc_mem(114);
tmp_str2.length(0);
if (
@@ -3582,13 +3918,258 @@ int spider_db_mbase_util::append_column_value(
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
} else if (field->str_needs_quotes())
{
+ if (str->charset() != field->charset())
+ {
+ if ((error_num = spider_db_append_charset_name_before_string(str,
+ field->charset())))
+ {
+ DBUG_RETURN(error_num);
+ }
+ }
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + ptr->length() * 2 + 2))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ append_escaped_util(str, ptr);
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ } else if (float_value)
+ {
+ if (str->reserve(SPIDER_SQL_CAST_LEN + ptr->length() +
+ SPIDER_SQL_AS_FLOAT_LEN, SPIDER_SQL_CLOSE_PAREN_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_CAST_STR, SPIDER_SQL_CAST_LEN);
+ str->q_append(ptr->ptr(), ptr->length());
+ str->q_append(SPIDER_SQL_AS_FLOAT_STR, SPIDER_SQL_AS_FLOAT_LEN);
+ str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN);
+ } else if (str->append(*ptr))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ DBUG_RETURN(0);
+}
+
+int spider_db_mysql_util::append_column_value(
+ ha_spider *spider,
+ spider_string *str,
+ Field *field,
+ const uchar *new_ptr,
+ CHARSET_INFO *access_charset
+) {
+ bool float_value = FALSE;
+ int error_num;
+ char buf[MAX_FIELD_WIDTH];
+ spider_string tmp_str(buf, MAX_FIELD_WIDTH, field->charset());
+ String *ptr;
+ uint length;
+ THD *thd = field->table->in_use;
+ Time_zone *saved_time_zone = thd->variables.time_zone;
+ DBUG_ENTER("spider_db_mysql_util::append_column_value");
+ tmp_str.init_calc_mem(266);
+
+ thd->variables.time_zone = UTC;
+
+ if (new_ptr)
+ {
+ if (
+ field->type() == MYSQL_TYPE_BLOB ||
+ field->real_type() == MYSQL_TYPE_VARCHAR
+ ) {
+ length = uint2korr(new_ptr);
+ tmp_str.set_quick((char *) new_ptr + HA_KEY_BLOB_LENGTH, length,
+ field->charset());
+ ptr = tmp_str.get_str();
+ } else if (field->type() == MYSQL_TYPE_GEOMETRY)
+ {
+/*
+ uint mlength = SIZEOF_STORED_DOUBLE, lcnt;
+ uchar *dest = (uchar *) buf;
+ const uchar *source;
+ for (lcnt = 0; lcnt < 4; lcnt++)
+ {
+ mlength = SIZEOF_STORED_DOUBLE;
+ source = new_ptr + mlength + SIZEOF_STORED_DOUBLE * lcnt;
+ while (mlength--)
+ *dest++ = *--source;
+ }
+ tmp_str.length(SIZEOF_STORED_DOUBLE * lcnt);
+*/
+#ifndef DBUG_OFF
+ double xmin, xmax, ymin, ymax;
+/*
+ float8store(buf,xmin);
+ float8store(buf+8,xmax);
+ float8store(buf+16,ymin);
+ float8store(buf+24,ymax);
+ memcpy(&xmin,new_ptr,sizeof(xmin));
+ memcpy(&xmax,new_ptr + 8,sizeof(xmax));
+ memcpy(&ymin,new_ptr + 16,sizeof(ymin));
+ memcpy(&ymax,new_ptr + 24,sizeof(ymax));
+ float8get(xmin, buf);
+ float8get(xmax, buf + 8);
+ float8get(ymin, buf + 16);
+ float8get(ymax, buf + 24);
+ DBUG_PRINT("info", ("spider geo is %f %f %f %f",
+ xmin, xmax, ymin, ymax));
+ DBUG_PRINT("info", ("spider geo is %.14g %.14g %.14g %.14g",
+ xmin, xmax, ymin, ymax));
+*/
+ float8get(xmin, new_ptr);
+ float8get(xmax, new_ptr + 8);
+ float8get(ymin, new_ptr + 16);
+ float8get(ymax, new_ptr + 24);
+ DBUG_PRINT("info", ("spider geo is %f %f %f %f",
+ xmin, xmax, ymin, ymax));
+/*
+ float8get(xmin, new_ptr + SIZEOF_STORED_DOUBLE * 4);
+ float8get(xmax, new_ptr + SIZEOF_STORED_DOUBLE * 5);
+ float8get(ymin, new_ptr + SIZEOF_STORED_DOUBLE * 6);
+ float8get(ymax, new_ptr + SIZEOF_STORED_DOUBLE * 7);
+ DBUG_PRINT("info", ("spider geo is %f %f %f %f",
+ xmin, xmax, ymin, ymax));
+ float8get(xmin, new_ptr + SIZEOF_STORED_DOUBLE * 8);
+ float8get(xmax, new_ptr + SIZEOF_STORED_DOUBLE * 9);
+ float8get(ymin, new_ptr + SIZEOF_STORED_DOUBLE * 10);
+ float8get(ymax, new_ptr + SIZEOF_STORED_DOUBLE * 11);
+ DBUG_PRINT("info", ("spider geo is %f %f %f %f",
+ xmin, xmax, ymin, ymax));
+ float8get(xmin, new_ptr + SIZEOF_STORED_DOUBLE * 12);
+ float8get(xmax, new_ptr + SIZEOF_STORED_DOUBLE * 13);
+ float8get(ymin, new_ptr + SIZEOF_STORED_DOUBLE * 14);
+ float8get(ymax, new_ptr + SIZEOF_STORED_DOUBLE * 15);
+ DBUG_PRINT("info", ("spider geo is %f %f %f %f",
+ xmin, xmax, ymin, ymax));
+*/
+#endif
+/*
+ tmp_str.set_quick((char *) new_ptr, SIZEOF_STORED_DOUBLE * 4,
+ &my_charset_bin);
+*/
+ tmp_str.length(0);
+ tmp_str.q_append((char *) SPIDER_SQL_LINESTRING_HEAD_STR,
+ SPIDER_SQL_LINESTRING_HEAD_LEN);
+ tmp_str.q_append((char *) new_ptr, SIZEOF_STORED_DOUBLE);
+ tmp_str.q_append((char *) new_ptr + SIZEOF_STORED_DOUBLE * 2,
+ SIZEOF_STORED_DOUBLE);
+ tmp_str.q_append((char *) new_ptr + SIZEOF_STORED_DOUBLE,
+ SIZEOF_STORED_DOUBLE);
+ tmp_str.q_append((char *) new_ptr + SIZEOF_STORED_DOUBLE * 3,
+ SIZEOF_STORED_DOUBLE);
+ ptr = tmp_str.get_str();
+ } else {
+ ptr = field->val_str(tmp_str.get_str(), new_ptr);
+ tmp_str.mem_calc();
+ }
+ } else {
+ ptr = field->val_str(tmp_str.get_str());
+ tmp_str.mem_calc();
+ if (field->type() == MYSQL_TYPE_FLOAT)
+ {
+ float_value = TRUE;
+ }
+ }
+
+ thd->variables.time_zone = saved_time_zone;
+
+ DBUG_PRINT("info", ("spider field->type() is %d", field->type()));
+ DBUG_PRINT("info", ("spider ptr->length() is %d", ptr->length()));
+/*
+ if (
+ field->type() == MYSQL_TYPE_BIT ||
+ (field->type() >= MYSQL_TYPE_TINY_BLOB &&
+ field->type() <= MYSQL_TYPE_BLOB)
+ ) {
+ uchar *hex_ptr = (uchar *) ptr->ptr(), *end_ptr;
+ char *str_ptr;
+ DBUG_PRINT("info", ("spider HEX"));
+ if (str->reserve(SPIDER_SQL_HEX_LEN + ptr->length() * 2))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_HEX_STR, SPIDER_SQL_HEX_LEN);
+ str_ptr = (char *) str->ptr() + str->length();
+ for (end_ptr = hex_ptr + ptr->length(); hex_ptr < end_ptr; hex_ptr++)
+ {
+ *str_ptr++ = spider_dig_upper[(*hex_ptr) >> 4];
+ *str_ptr++ = spider_dig_upper[(*hex_ptr) & 0x0F];
+ }
+ str->length(str->length() + ptr->length() * 2);
+ } else
+*/
+ if (field->result_type() == STRING_RESULT)
+ {
+ DBUG_PRINT("info", ("spider STRING_RESULT"));
+ if (str->charset() != field->charset())
+ {
+ if ((error_num = spider_db_append_charset_name_before_string(str,
+ field->charset())))
+ {
+ DBUG_RETURN(error_num);
+ }
+ }
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ if (
+ field->type() == MYSQL_TYPE_VARCHAR ||
+ (field->type() >= MYSQL_TYPE_ENUM &&
+ field->type() <= MYSQL_TYPE_GEOMETRY)
+ ) {
+ DBUG_PRINT("info", ("spider append_escaped"));
+ char buf2[MAX_FIELD_WIDTH];
+ spider_string tmp_str2(buf2, MAX_FIELD_WIDTH, field->charset());
+ tmp_str2.init_calc_mem(267);
+ tmp_str2.length(0);
+ if (
+ tmp_str2.append(ptr->ptr(), ptr->length(), field->charset()) ||
+ str->reserve(tmp_str2.length() * 2) ||
+ append_escaped_util(str, tmp_str2.get_str())
+ )
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ } else if (str->append(*ptr))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ } else if (field->str_needs_quotes())
+ {
+ if (str->charset() != field->charset())
+ {
+ if ((error_num = spider_db_append_charset_name_before_string(str,
+ field->charset())))
+ {
+ DBUG_RETURN(error_num);
+ }
+ }
if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN * 2 + ptr->length() * 2 + 2))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
append_escaped_util(str, ptr);
str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ } else if (float_value)
+ {
+ if (str->reserve(SPIDER_SQL_TO_FLOAT_LEN + ptr->length() +
+ SPIDER_SQL_CLOSE_PAREN_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_TO_FLOAT_STR, SPIDER_SQL_TO_FLOAT_LEN);
+ str->q_append(ptr->ptr(), ptr->length());
+ str->q_append(SPIDER_SQL_CLOSE_PAREN_STR, SPIDER_SQL_CLOSE_PAREN_LEN);
} else if (str->append(*ptr))
+ {
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ DBUG_RETURN(0);
+}
+
+int spider_db_mbase_util::append_column_value(
+ ha_spider *spider,
+ spider_string *str,
+ Field *field,
+ const uchar *new_ptr,
+ CHARSET_INFO *access_charset
+) {
+ DBUG_ENTER("spider_db_mbase_util::append_column_value");
+ DBUG_ASSERT(0);
DBUG_RETURN(0);
}
@@ -3707,6 +4288,885 @@ int spider_db_mbase_util::append_sql_log_off(
DBUG_RETURN(0);
}
+int spider_db_mbase_util::append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+) {
+ char timeout_str[SPIDER_SQL_INT_LEN];
+ int timeout_str_length;
+ DBUG_ENTER("spider_db_mbase_util::append_wait_timeout");
+ DBUG_PRINT("info",("spider this=%p", this));
+ timeout_str_length =
+ my_sprintf(timeout_str, (timeout_str, "%d", wait_timeout));
+ if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_WAIT_TIMEOUT_LEN +
+ timeout_str_length))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ if (str->length())
+ {
+ str->q_append(SPIDER_SQL_SEMICOLON_STR, SPIDER_SQL_SEMICOLON_LEN);
+ }
+ str->q_append(SPIDER_SQL_WAIT_TIMEOUT_STR, SPIDER_SQL_WAIT_TIMEOUT_LEN);
+ str->q_append(timeout_str, timeout_str_length);
+ DBUG_RETURN(0);
+}
+
+#define SPIDER_REAL_AS_FLOAT_STR "real_as_float"
+#define SPIDER_REAL_AS_FLOAT_LEN (sizeof(SPIDER_REAL_AS_FLOAT_STR) - 1)
+#define SPIDER_PIPES_AS_CONCAT_STR "pipes_as_concat"
+#define SPIDER_PIPES_AS_CONCAT_LEN (sizeof(SPIDER_PIPES_AS_CONCAT_STR) - 1)
+#define SPIDER_ANSI_QUOTES_STR "ansi_quotes"
+#define SPIDER_ANSI_QUOTES_LEN (sizeof(SPIDER_ANSI_QUOTES_STR) - 1)
+#define SPIDER_IGNORE_SPACE_STR "ignore_space"
+#define SPIDER_IGNORE_SPACE_LEN (sizeof(SPIDER_IGNORE_SPACE_STR) - 1)
+#define SPIDER_IGNORE_BAD_TABLE_OPTIONS_STR "ignore_bad_table_options"
+#define SPIDER_IGNORE_BAD_TABLE_OPTIONS_LEN (sizeof(SPIDER_IGNORE_BAD_TABLE_OPTIONS_STR) - 1)
+#define SPIDER_ONLY_FULL_GROUP_BY_STR "only_full_group_by"
+#define SPIDER_ONLY_FULL_GROUP_BY_LEN (sizeof(SPIDER_ONLY_FULL_GROUP_BY_STR) - 1)
+#define SPIDER_NO_UNSIGNED_SUBTRACTION_STR "no_unsigned_subtraction"
+#define SPIDER_NO_UNSIGNED_SUBTRACTION_LEN (sizeof(SPIDER_NO_UNSIGNED_SUBTRACTION_STR) - 1)
+#define SPIDER_NO_DIR_IN_CREATE_STR "no_dir_in_create"
+#define SPIDER_NO_DIR_IN_CREATE_LEN (sizeof(SPIDER_NO_DIR_IN_CREATE_STR) - 1)
+#define SPIDER_POSTGRESQL_STR "postgresql"
+#define SPIDER_POSTGRESQL_LEN (sizeof(SPIDER_POSTGRESQL_STR) - 1)
+#define SPIDER_ORACLE_STR "oracle"
+#define SPIDER_ORACLE_LEN (sizeof(SPIDER_ORACLE_STR) - 1)
+#define SPIDER_MSSQL_STR "mssql"
+#define SPIDER_MSSQL_LEN (sizeof(SPIDER_MSSQL_STR) - 1)
+#define SPIDER_DB2_STR "db2"
+#define SPIDER_DB2_LEN (sizeof(SPIDER_DB2_STR) - 1)
+#define SPIDER_MAXDB_STR "maxdb"
+#define SPIDER_MAXDB_LEN (sizeof(SPIDER_MAXDB_STR) - 1)
+#define SPIDER_NO_KEY_OPTIONS_STR "no_key_options"
+#define SPIDER_NO_KEY_OPTIONS_LEN (sizeof(SPIDER_NO_KEY_OPTIONS_STR) - 1)
+#define SPIDER_NO_TABLE_OPTIONS_STR "no_table_options"
+#define SPIDER_NO_TABLE_OPTIONS_LEN (sizeof(SPIDER_NO_TABLE_OPTIONS_STR) - 1)
+#define SPIDER_NO_FIELD_OPTIONS_STR "no_field_options"
+#define SPIDER_NO_FIELD_OPTIONS_LEN (sizeof(SPIDER_NO_FIELD_OPTIONS_STR) - 1)
+#define SPIDER_MYSQL323_STR "mysql323"
+#define SPIDER_MYSQL323_LEN (sizeof(SPIDER_MYSQL323_STR) - 1)
+#define SPIDER_MYSQL40_STR "mysql40"
+#define SPIDER_MYSQL40_LEN (sizeof(SPIDER_MYSQL40_STR) - 1)
+#define SPIDER_ANSI_STR "ansi"
+#define SPIDER_ANSI_LEN (sizeof(SPIDER_ANSI_STR) - 1)
+#define SPIDER_NO_AUTO_VALUE_ON_ZERO_STR "no_auto_value_on_zero"
+#define SPIDER_NO_AUTO_VALUE_ON_ZERO_LEN (sizeof(SPIDER_NO_AUTO_VALUE_ON_ZERO_STR) - 1)
+#define SPIDER_NO_BACKSLASH_ESCAPES_STR "no_backslash_escapes"
+#define SPIDER_NO_BACKSLASH_ESCAPES_LEN (sizeof(SPIDER_NO_BACKSLASH_ESCAPES_STR) - 1)
+#define SPIDER_STRICT_TRANS_TABLES_STR "strict_trans_tables"
+#define SPIDER_STRICT_TRANS_TABLES_LEN (sizeof(SPIDER_STRICT_TRANS_TABLES_STR) - 1)
+#define SPIDER_STRICT_ALL_TABLES_STR "strict_all_tables"
+#define SPIDER_STRICT_ALL_TABLES_LEN (sizeof(SPIDER_STRICT_ALL_TABLES_STR) - 1)
+#define SPIDER_NO_ZERO_IN_DATE_STR "no_zero_in_date"
+#define SPIDER_NO_ZERO_IN_DATE_LEN (sizeof(SPIDER_NO_ZERO_IN_DATE_STR) - 1)
+#define SPIDER_NO_ZERO_DATE_STR "no_zero_date"
+#define SPIDER_NO_ZERO_DATE_LEN (sizeof(SPIDER_NO_ZERO_DATE_STR) - 1)
+#define SPIDER_INVALID_DATES_STR "allow_invalid_dates"
+#define SPIDER_INVALID_DATES_LEN (sizeof(SPIDER_INVALID_DATES_STR) - 1)
+#define SPIDER_ERROR_FOR_DIVISION_BY_ZERO_STR "error_for_division_by_zero"
+#define SPIDER_ERROR_FOR_DIVISION_BY_ZERO_LEN (sizeof(SPIDER_ERROR_FOR_DIVISION_BY_ZERO_STR) - 1)
+#define SPIDER_TRADITIONAL_STR "traditional"
+#define SPIDER_TRADITIONAL_LEN (sizeof(SPIDER_TRADITIONAL_STR) - 1)
+#define SPIDER_NO_AUTO_CREATE_USER_STR "no_auto_create_user"
+#define SPIDER_NO_AUTO_CREATE_USER_LEN (sizeof(SPIDER_NO_AUTO_CREATE_USER_STR) - 1)
+#define SPIDER_HIGH_NOT_PRECEDENCE_STR "high_not_precedence"
+#define SPIDER_HIGH_NOT_PRECEDENCE_LEN (sizeof(SPIDER_HIGH_NOT_PRECEDENCE_STR) - 1)
+#define SPIDER_NO_ENGINE_SUBSTITUTION_STR "no_engine_substitution"
+#define SPIDER_NO_ENGINE_SUBSTITUTION_LEN (sizeof(SPIDER_NO_ENGINE_SUBSTITUTION_STR) - 1)
+#define SPIDER_PAD_CHAR_TO_FULL_LENGTH_STR "pad_char_to_full_length"
+#define SPIDER_PAD_CHAR_TO_FULL_LENGTH_LEN (sizeof(SPIDER_PAD_CHAR_TO_FULL_LENGTH_STR) - 1)
+#define SPIDER_EMPTY_STRING_IS_NULL_STR "empty_string_is_null"
+#define SPIDER_EMPTY_STRING_IS_NULL_LEN (sizeof(SPIDER_EMPTY_STRING_IS_NULL_STR) - 1)
+#define SPIDER_SIMULTANEOUS_ASSIGNMENT_STR "simultaneous_assignment"
+#define SPIDER_SIMULTANEOUS_ASSIGNMENT_LEN (sizeof(SPIDER_SIMULTANEOUS_ASSIGNMENT_STR) - 1)
+#define SPIDER_TIME_ROUND_FRACTIONAL_STR "time_round_fractional"
+#define SPIDER_TIME_ROUND_FRACTIONAL_LEN (sizeof(SPIDER_TIME_ROUND_FRACTIONAL_STR) - 1)
+
+sql_mode_t full_sql_mode =
+#ifdef MODE_REAL_AS_FLOAT
+ MODE_REAL_AS_FLOAT |
+#endif
+#ifdef MODE_PIPES_AS_CONCAT
+ MODE_PIPES_AS_CONCAT |
+#endif
+#ifdef MODE_ANSI_QUOTES
+ MODE_ANSI_QUOTES |
+#endif
+#ifdef MODE_IGNORE_SPACE
+ MODE_IGNORE_SPACE |
+#endif
+#ifdef MODE_IGNORE_BAD_TABLE_OPTIONS
+ MODE_IGNORE_BAD_TABLE_OPTIONS |
+#endif
+#ifdef MODE_ONLY_FULL_GROUP_BY
+ MODE_ONLY_FULL_GROUP_BY |
+#endif
+#ifdef MODE_NO_UNSIGNED_SUBTRACTION
+ MODE_NO_UNSIGNED_SUBTRACTION |
+#endif
+#ifdef MODE_NO_DIR_IN_CREATE
+ MODE_NO_DIR_IN_CREATE |
+#endif
+#ifdef MODE_POSTGRESQL
+ MODE_POSTGRESQL |
+#endif
+#ifdef MODE_ORACLE
+ MODE_ORACLE |
+#endif
+#ifdef MODE_MSSQL
+ MODE_MSSQL |
+#endif
+#ifdef MODE_DB2
+ MODE_DB2 |
+#endif
+#ifdef MODE_MAXDB
+ MODE_MAXDB |
+#endif
+#ifdef MODE_NO_KEY_OPTIONS
+ MODE_NO_KEY_OPTIONS |
+#endif
+#ifdef MODE_NO_TABLE_OPTIONS
+ MODE_NO_TABLE_OPTIONS |
+#endif
+#ifdef MODE_NO_FIELD_OPTIONS
+ MODE_NO_FIELD_OPTIONS |
+#endif
+#ifdef MODE_MYSQL323
+ MODE_MYSQL323 |
+#endif
+#ifdef MODE_MYSQL40
+ MODE_MYSQL40 |
+#endif
+#ifdef MODE_ANSI
+ MODE_ANSI |
+#endif
+#ifdef MODE_NO_AUTO_VALUE_ON_ZERO
+ MODE_NO_AUTO_VALUE_ON_ZERO |
+#endif
+#ifdef MODE_NO_BACKSLASH_ESCAPES
+ MODE_NO_BACKSLASH_ESCAPES |
+#endif
+#ifdef MODE_STRICT_TRANS_TABLES
+ MODE_STRICT_TRANS_TABLES |
+#endif
+#ifdef MODE_STRICT_ALL_TABLES
+ MODE_STRICT_ALL_TABLES |
+#endif
+#ifdef MODE_NO_ZERO_IN_DATE
+ MODE_NO_ZERO_IN_DATE |
+#endif
+#ifdef MODE_NO_ZERO_DATE
+ MODE_NO_ZERO_DATE |
+#endif
+#ifdef MODE_INVALID_DATES
+ MODE_INVALID_DATES |
+#endif
+#ifdef MODE_ERROR_FOR_DIVISION_BY_ZERO
+ MODE_ERROR_FOR_DIVISION_BY_ZERO |
+#endif
+#ifdef MODE_TRADITIONAL
+ MODE_TRADITIONAL |
+#endif
+#ifdef MODE_NO_AUTO_CREATE_USER
+ MODE_NO_AUTO_CREATE_USER |
+#endif
+#ifdef MODE_HIGH_NOT_PRECEDENCE
+ MODE_HIGH_NOT_PRECEDENCE |
+#endif
+#ifdef MODE_NO_ENGINE_SUBSTITUTION
+ MODE_NO_ENGINE_SUBSTITUTION |
+#endif
+#ifdef MODE_PAD_CHAR_TO_FULL_LENGTH
+ MODE_PAD_CHAR_TO_FULL_LENGTH |
+#endif
+#ifdef MODE_EMPTY_STRING_IS_NULL
+ MODE_EMPTY_STRING_IS_NULL |
+#endif
+#ifdef MODE_SIMULTANEOUS_ASSIGNMENT
+ MODE_SIMULTANEOUS_ASSIGNMENT |
+#endif
+#ifdef MODE_TIME_ROUND_FRACTIONAL
+ MODE_TIME_ROUND_FRACTIONAL |
+#endif
+ 0;
+
+#ifdef MODE_REAL_AS_FLOAT
+/* pushdown */
+#define SPIDER_SQL_MODE_REAL_AS_FLOAT
+#endif
+#ifdef MODE_PIPES_AS_CONCAT
+/* no pushdown */
+#endif
+#ifdef MODE_ANSI_QUOTES
+/* no pushdown */
+#endif
+#ifdef MODE_IGNORE_SPACE
+/* no pushdown */
+#endif
+#ifdef MODE_IGNORE_BAD_TABLE_OPTIONS
+/* pushdown */
+#define SPIDER_SQL_MODE_IGNORE_BAD_TABLE_OPTIONS
+#endif
+#ifdef MODE_ONLY_FULL_GROUP_BY
+/* no pushdown */
+#endif
+#ifdef MODE_NO_UNSIGNED_SUBTRACTION
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_UNSIGNED_SUBTRACTION
+#endif
+#ifdef MODE_NO_DIR_IN_CREATE
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_DIR_IN_CREATE
+#endif
+#ifdef MODE_POSTGRESQL
+/* no pushdown */
+#endif
+#ifdef MODE_ORACLE
+/* no pushdown */
+#endif
+#ifdef MODE_MSSQL
+/* no pushdown */
+#endif
+#ifdef MODE_DB2
+/* no pushdown */
+#endif
+#ifdef MODE_MAXDB
+/* no pushdown */
+#endif
+#ifdef MODE_NO_KEY_OPTIONS
+/* no pushdown */
+#endif
+#ifdef MODE_NO_TABLE_OPTIONS
+/* no pushdown */
+#endif
+#ifdef MODE_NO_FIELD_OPTIONS
+/* no pushdown */
+#endif
+#ifdef MODE_MYSQL323
+/* no pushdown */
+#endif
+#ifdef MODE_MYSQL40
+/* no pushdown */
+#endif
+#ifdef MODE_ANSI
+/* no pushdown */
+#endif
+#ifdef MODE_NO_AUTO_VALUE_ON_ZERO
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_AUTO_VALUE_ON_ZERO
+#endif
+#ifdef MODE_NO_BACKSLASH_ESCAPES
+/* no pushdown */
+#endif
+#ifdef MODE_STRICT_TRANS_TABLES
+/* pushdown */
+#define SPIDER_SQL_MODE_STRICT_TRANS_TABLES
+#endif
+#ifdef MODE_STRICT_ALL_TABLES
+/* pushdown */
+#define SPIDER_SQL_MODE_STRICT_ALL_TABLES
+#endif
+#ifdef MODE_NO_ZERO_IN_DATE
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_ZERO_IN_DATE
+#endif
+#ifdef MODE_NO_ZERO_DATE
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_ZERO_DATE
+#endif
+#ifdef MODE_INVALID_DATES
+/* pushdown */
+#define SPIDER_SQL_MODE_INVALID_DATES
+#endif
+#ifdef MODE_ERROR_FOR_DIVISION_BY_ZERO
+/* pushdown */
+#define SPIDER_SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO
+#endif
+#ifdef MODE_TRADITIONAL
+/* no pushdown */
+#endif
+#ifdef MODE_NO_AUTO_CREATE_USER
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_AUTO_CREATE_USER
+#endif
+#ifdef MODE_HIGH_NOT_PRECEDENCE
+/* pushdown */
+#define SPIDER_SQL_MODE_HIGH_NOT_PRECEDENCE
+#endif
+#ifdef MODE_NO_ENGINE_SUBSTITUTION
+/* pushdown */
+#define SPIDER_SQL_MODE_NO_ENGINE_SUBSTITUTION
+#endif
+#ifdef MODE_PAD_CHAR_TO_FULL_LENGTH
+/* pushdown */
+#define SPIDER_SQL_MODE_PAD_CHAR_TO_FULL_LENGTH
+#endif
+#ifdef MODE_EMPTY_STRING_IS_NULL
+/* pushdown */
+#define SPIDER_SQL_MODE_EMPTY_STRING_IS_NULL
+#endif
+#ifdef MODE_SIMULTANEOUS_ASSIGNMENT
+/* pushdown */
+#define SPIDER_SQL_MODE_SIMULTANEOUS_ASSIGNMENT
+#endif
+#ifdef MODE_TIME_ROUND_FRACTIONAL
+/* pushdown */
+#define SPIDER_SQL_MODE_TIME_ROUND_FRACTIONAL
+#endif
+
+sql_mode_t pushdown_sql_mode =
+#ifdef SPIDER_SQL_MODE_REAL_AS_FLOAT
+ MODE_REAL_AS_FLOAT |
+#endif
+#ifdef SPIDER_SQL_MODE_PIPES_AS_CONCAT
+ MODE_PIPES_AS_CONCAT |
+#endif
+#ifdef SPIDER_SQL_MODE_ANSI_QUOTES
+ MODE_ANSI_QUOTES |
+#endif
+#ifdef SPIDER_SQL_MODE_IGNORE_SPACE
+ MODE_IGNORE_SPACE |
+#endif
+#ifdef SPIDER_SQL_MODE_IGNORE_BAD_TABLE_OPTIONS
+ MODE_IGNORE_BAD_TABLE_OPTIONS |
+#endif
+#ifdef SPIDER_SQL_MODE_ONLY_FULL_GROUP_BY
+ MODE_ONLY_FULL_GROUP_BY |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_UNSIGNED_SUBTRACTION
+ MODE_NO_UNSIGNED_SUBTRACTION |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_DIR_IN_CREATE
+ MODE_NO_DIR_IN_CREATE |
+#endif
+#ifdef SPIDER_SQL_MODE_POSTGRESQL
+ MODE_POSTGRESQL |
+#endif
+#ifdef SPIDER_SQL_MODE_ORACLE
+ MODE_ORACLE |
+#endif
+#ifdef SPIDER_SQL_MODE_MSSQL
+ MODE_MSSQL |
+#endif
+#ifdef SPIDER_SQL_MODE_DB2
+ MODE_DB2 |
+#endif
+#ifdef SPIDER_SQL_MODE_MAXDB
+ MODE_MAXDB |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_KEY_OPTIONS
+ MODE_NO_KEY_OPTIONS |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_TABLE_OPTIONS
+ MODE_NO_TABLE_OPTIONS |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_FIELD_OPTIONS
+ MODE_NO_FIELD_OPTIONS |
+#endif
+#ifdef SPIDER_SQL_MODE_MYSQL323
+ MODE_MYSQL323 |
+#endif
+#ifdef SPIDER_SQL_MODE_MYSQL40
+ MODE_MYSQL40 |
+#endif
+#ifdef SPIDER_SQL_MODE_ANSI
+ MODE_ANSI |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_AUTO_VALUE_ON_ZERO
+ MODE_NO_AUTO_VALUE_ON_ZERO |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_BACKSLASH_ESCAPES
+ MODE_NO_BACKSLASH_ESCAPES |
+#endif
+#ifdef SPIDER_SQL_MODE_STRICT_TRANS_TABLES
+ MODE_STRICT_TRANS_TABLES |
+#endif
+#ifdef SPIDER_SQL_MODE_STRICT_ALL_TABLES
+ MODE_STRICT_ALL_TABLES |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_ZERO_IN_DATE
+ MODE_NO_ZERO_IN_DATE |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_ZERO_DATE
+ MODE_NO_ZERO_DATE |
+#endif
+#ifdef SPIDER_SQL_MODE_INVALID_DATES
+ MODE_INVALID_DATES |
+#endif
+#ifdef SPIDER_SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO
+ MODE_ERROR_FOR_DIVISION_BY_ZERO |
+#endif
+#ifdef SPIDER_SQL_MODE_TRADITIONAL
+ MODE_TRADITIONAL |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_AUTO_CREATE_USER
+ MODE_NO_AUTO_CREATE_USER |
+#endif
+#ifdef SPIDER_SQL_MODE_HIGH_NOT_PRECEDENCE
+ MODE_HIGH_NOT_PRECEDENCE |
+#endif
+#ifdef SPIDER_SQL_MODE_NO_ENGINE_SUBSTITUTION
+ MODE_NO_ENGINE_SUBSTITUTION |
+#endif
+#ifdef SPIDER_SQL_MODE_PAD_CHAR_TO_FULL_LENGTH
+ MODE_PAD_CHAR_TO_FULL_LENGTH |
+#endif
+#ifdef SPIDER_SQL_MODE_EMPTY_STRING_IS_NULL
+ MODE_EMPTY_STRING_IS_NULL |
+#endif
+#ifdef SPIDER_SQL_MODE_SIMULTANEOUS_ASSIGNMENT
+ MODE_SIMULTANEOUS_ASSIGNMENT |
+#endif
+#ifdef SPIDER_SQL_MODE_TIME_ROUND_FRACTIONAL
+ MODE_TIME_ROUND_FRACTIONAL |
+#endif
+ 0;
+
+int spider_db_mbase_util::append_sql_mode_internal(
+ spider_string *str,
+ sql_mode_t sql_mode
+) {
+ DBUG_ENTER("spider_db_mbase_util::append_sql_mode_internal");
+ DBUG_PRINT("info",("spider this=%p", this));
+#ifdef SPIDER_SQL_MODE_REAL_AS_FLOAT
+ if (sql_mode & MODE_REAL_AS_FLOAT)
+ {
+ if (str->reserve(SPIDER_REAL_AS_FLOAT_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_REAL_AS_FLOAT_STR, SPIDER_REAL_AS_FLOAT_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_PIPES_AS_CONCAT
+ if (sql_mode & MODE_PIPES_AS_CONCAT)
+ {
+ if (str->reserve(SPIDER_PIPES_AS_CONCAT_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_PIPES_AS_CONCAT_STR, SPIDER_PIPES_AS_CONCAT_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_ANSI_QUOTES
+ if (sql_mode & MODE_ANSI_QUOTES)
+ {
+ if (str->reserve(SPIDER_ANSI_QUOTES_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_ANSI_QUOTES_STR, SPIDER_ANSI_QUOTES_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_IGNORE_SPACE
+ if (sql_mode & MODE_IGNORE_SPACE)
+ {
+ if (str->reserve(SPIDER_IGNORE_SPACE_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_IGNORE_SPACE_STR, SPIDER_IGNORE_SPACE_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_IGNORE_BAD_TABLE_OPTIONS
+ if (sql_mode & MODE_IGNORE_BAD_TABLE_OPTIONS)
+ {
+ if (str->reserve(SPIDER_IGNORE_BAD_TABLE_OPTIONS_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_IGNORE_BAD_TABLE_OPTIONS_STR, SPIDER_IGNORE_BAD_TABLE_OPTIONS_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_ONLY_FULL_GROUP_BY
+ if (sql_mode & MODE_ONLY_FULL_GROUP_BY)
+ {
+ if (str->reserve(SPIDER_ONLY_FULL_GROUP_BY_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_ONLY_FULL_GROUP_BY_STR, SPIDER_ONLY_FULL_GROUP_BY_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_UNSIGNED_SUBTRACTION
+ if (sql_mode & MODE_NO_UNSIGNED_SUBTRACTION)
+ {
+ if (str->reserve(SPIDER_NO_UNSIGNED_SUBTRACTION_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_UNSIGNED_SUBTRACTION_STR, SPIDER_NO_UNSIGNED_SUBTRACTION_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_DIR_IN_CREATE
+ if (sql_mode & MODE_NO_DIR_IN_CREATE)
+ {
+ if (str->reserve(SPIDER_NO_DIR_IN_CREATE_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_DIR_IN_CREATE_STR, SPIDER_NO_DIR_IN_CREATE_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_POSTGRESQL
+ if (sql_mode & MODE_POSTGRESQL)
+ {
+ if (str->reserve(SPIDER_POSTGRESQL_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_POSTGRESQL_STR, SPIDER_POSTGRESQL_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_ORACLE
+ if (sql_mode & MODE_ORACLE)
+ {
+ if (str->reserve(SPIDER_ORACLE_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_ORACLE_STR, SPIDER_ORACLE_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_MSSQL
+ if (sql_mode & MODE_MSSQL)
+ {
+ if (str->reserve(SPIDER_MSSQL_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_MSSQL_STR, SPIDER_MSSQL_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_DB2
+ if (sql_mode & MODE_DB2)
+ {
+ if (str->reserve(SPIDER_DB2_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_DB2_STR, SPIDER_DB2_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_MAXDB
+ if (sql_mode & MODE_MAXDB)
+ {
+ if (str->reserve(SPIDER_MAXDB_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_MAXDB_STR, SPIDER_MAXDB_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_KEY_OPTIONS
+ if (sql_mode & MODE_NO_KEY_OPTIONS)
+ {
+ if (str->reserve(SPIDER_NO_KEY_OPTIONS_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_KEY_OPTIONS_STR, SPIDER_NO_KEY_OPTIONS_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_TABLE_OPTIONS
+ if (sql_mode & MODE_NO_TABLE_OPTIONS)
+ {
+ if (str->reserve(SPIDER_NO_TABLE_OPTIONS_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_TABLE_OPTIONS_STR, SPIDER_NO_TABLE_OPTIONS_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_FIELD_OPTIONS
+ if (sql_mode & MODE_NO_FIELD_OPTIONS)
+ {
+ if (str->reserve(SPIDER_NO_FIELD_OPTIONS_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_FIELD_OPTIONS_STR, SPIDER_NO_FIELD_OPTIONS_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_MYSQL323
+ if (sql_mode & MODE_MYSQL323)
+ {
+ if (str->reserve(SPIDER_MYSQL323_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_MYSQL323_STR, SPIDER_MYSQL323_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_MYSQL40
+ if (sql_mode & MODE_MYSQL40)
+ {
+ if (str->reserve(SPIDER_MYSQL40_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_MYSQL40_STR, SPIDER_MYSQL40_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_ANSI
+ if (sql_mode & MODE_ANSI)
+ {
+ if (str->reserve(SPIDER_ANSI_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_ANSI_STR, SPIDER_ANSI_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_AUTO_VALUE_ON_ZERO
+ if (sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
+ {
+ if (str->reserve(SPIDER_NO_AUTO_VALUE_ON_ZERO_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_AUTO_VALUE_ON_ZERO_STR, SPIDER_NO_AUTO_VALUE_ON_ZERO_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_BACKSLASH_ESCAPES
+ if (sql_mode & MODE_NO_BACKSLASH_ESCAPES)
+ {
+ if (str->reserve(SPIDER_NO_BACKSLASH_ESCAPES_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_BACKSLASH_ESCAPES_STR, SPIDER_NO_BACKSLASH_ESCAPES_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_STRICT_TRANS_TABLES
+ if (sql_mode & MODE_STRICT_TRANS_TABLES)
+ {
+ if (str->reserve(SPIDER_STRICT_TRANS_TABLES_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_STRICT_TRANS_TABLES_STR, SPIDER_STRICT_TRANS_TABLES_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_STRICT_ALL_TABLES
+ if (sql_mode & MODE_STRICT_ALL_TABLES)
+ {
+ if (str->reserve(SPIDER_STRICT_ALL_TABLES_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_STRICT_ALL_TABLES_STR, SPIDER_STRICT_ALL_TABLES_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_ZERO_IN_DATE
+ if (sql_mode & MODE_NO_ZERO_IN_DATE)
+ {
+ if (str->reserve(SPIDER_NO_ZERO_IN_DATE_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_ZERO_IN_DATE_STR, SPIDER_NO_ZERO_IN_DATE_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_ZERO_DATE
+ if (sql_mode & MODE_NO_ZERO_DATE)
+ {
+ if (str->reserve(SPIDER_NO_ZERO_DATE_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_ZERO_DATE_STR, SPIDER_NO_ZERO_DATE_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_INVALID_DATES
+ if (sql_mode & MODE_INVALID_DATES)
+ {
+ if (str->reserve(SPIDER_INVALID_DATES_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_INVALID_DATES_STR, SPIDER_INVALID_DATES_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_ERROR_FOR_DIVISION_BY_ZERO
+ if (sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
+ {
+ if (str->reserve(SPIDER_ERROR_FOR_DIVISION_BY_ZERO_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_ERROR_FOR_DIVISION_BY_ZERO_STR, SPIDER_ERROR_FOR_DIVISION_BY_ZERO_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_TRADITIONAL
+ if (sql_mode & MODE_TRADITIONAL)
+ {
+ if (str->reserve(SPIDER_TRADITIONAL_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_TRADITIONAL_STR, SPIDER_TRADITIONAL_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_AUTO_CREATE_USER
+ if (sql_mode & MODE_NO_AUTO_CREATE_USER)
+ {
+ if (str->reserve(SPIDER_NO_AUTO_CREATE_USER_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_AUTO_CREATE_USER_STR, SPIDER_NO_AUTO_CREATE_USER_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_HIGH_NOT_PRECEDENCE
+ if (sql_mode & MODE_HIGH_NOT_PRECEDENCE)
+ {
+ if (str->reserve(SPIDER_HIGH_NOT_PRECEDENCE_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_HIGH_NOT_PRECEDENCE_STR, SPIDER_HIGH_NOT_PRECEDENCE_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_NO_ENGINE_SUBSTITUTION
+ if (sql_mode & MODE_NO_ENGINE_SUBSTITUTION)
+ {
+ if (str->reserve(SPIDER_NO_ENGINE_SUBSTITUTION_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_NO_ENGINE_SUBSTITUTION_STR, SPIDER_NO_ENGINE_SUBSTITUTION_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_PAD_CHAR_TO_FULL_LENGTH
+ if (sql_mode & MODE_PAD_CHAR_TO_FULL_LENGTH)
+ {
+ if (str->reserve(SPIDER_PAD_CHAR_TO_FULL_LENGTH_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_PAD_CHAR_TO_FULL_LENGTH_STR, SPIDER_PAD_CHAR_TO_FULL_LENGTH_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+ DBUG_RETURN(0);
+}
+
+int spider_db_mariadb_util::append_sql_mode_internal(
+ spider_string *str,
+ sql_mode_t sql_mode
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_mbase_util::append_sql_mode_internal");
+ DBUG_PRINT("info",("spider this=%p", this));
+ if ((error_num = spider_db_mbase_util::append_sql_mode_internal(
+ str, sql_mode)))
+ {
+ DBUG_RETURN(error_num);
+ }
+#ifdef SPIDER_SQL_MODE_EMPTY_STRING_IS_NULL
+ if (sql_mode & MODE_EMPTY_STRING_IS_NULL)
+ {
+ if (str->reserve(SPIDER_EMPTY_STRING_IS_NULL_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_EMPTY_STRING_IS_NULL_STR, SPIDER_EMPTY_STRING_IS_NULL_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_SIMULTANEOUS_ASSIGNMENT
+ if (sql_mode & MODE_SIMULTANEOUS_ASSIGNMENT)
+ {
+ if (str->reserve(SPIDER_SIMULTANEOUS_ASSIGNMENT_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SIMULTANEOUS_ASSIGNMENT_STR, SPIDER_SIMULTANEOUS_ASSIGNMENT_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+#ifdef SPIDER_SQL_MODE_TIME_ROUND_FRACTIONAL
+ if (sql_mode & MODE_TIME_ROUND_FRACTIONAL)
+ {
+ if (str->reserve(SPIDER_TIME_ROUND_FRACTIONAL_LEN + SPIDER_SQL_COMMA_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_TIME_ROUND_FRACTIONAL_STR, SPIDER_TIME_ROUND_FRACTIONAL_LEN);
+ str->q_append(SPIDER_SQL_COMMA_STR, SPIDER_SQL_COMMA_LEN);
+ }
+#endif
+ DBUG_RETURN(0);
+}
+
+int spider_db_mbase_util::append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+) {
+ int error_num;
+ uint length;
+ DBUG_ENTER("spider_db_mbase_util::append_sql_mode");
+ DBUG_PRINT("info",("spider this=%p", this));
+ if (str->reserve(SPIDER_SQL_SEMICOLON_LEN + SPIDER_SQL_SQL_MODE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ if (str->length())
+ {
+ str->q_append(SPIDER_SQL_SEMICOLON_STR, SPIDER_SQL_SEMICOLON_LEN);
+ }
+ str->q_append(SPIDER_SQL_SQL_MODE_STR, SPIDER_SQL_SQL_MODE_LEN);
+ length = str->length();
+ if ((error_num = append_sql_mode_internal(str, sql_mode)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->length() > length)
+ {
+ str->length(str->length() - SPIDER_SQL_COMMA_LEN);
+ } else {
+ if (str->reserve(SPIDER_SQL_VALUE_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ }
+ str->q_append(SPIDER_SQL_VALUE_QUOTE_STR, SPIDER_SQL_VALUE_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
int spider_db_mbase_util::append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -4796,9 +6256,10 @@ int spider_db_mbase_util::open_item_func(
}
break;
case Item_func::LIKE_FUNC:
+#ifdef SPIDER_LIKE_FUNC_HAS_GET_NEGATED
if (str)
{
- if (((Item_func_like *)item_func)->negated)
+ if (((Item_func_like *)item_func)->get_negated())
{
func_name = SPIDER_SQL_NOT_LIKE_STR;
func_name_length = SPIDER_SQL_NOT_LIKE_LEN;
@@ -4810,6 +6271,9 @@ int spider_db_mbase_util::open_item_func(
}
}
break;
+#else
+ DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
+#endif
default:
THD *thd = spider->trx->thd;
SPIDER_SHARE *share = spider->share;
@@ -6689,6 +8153,15 @@ int spider_mbase_share::discover_table_structure(
}
#endif
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+bool spider_mbase_share::checksum_support()
+{
+ DBUG_ENTER("spider_mbase_share::checksum_support");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(TRUE);
+}
+#endif
+
spider_mbase_handler::spider_mbase_handler(
ha_spider *spider,
spider_mbase_share *db_share,
@@ -6814,10 +8287,12 @@ int spider_mbase_handler::init()
}
sql.set_charset(share->access_charset);
sql_part.set_charset(share->access_charset);
+ sql_part2.set_charset(share->access_charset);
ha_sql.set_charset(share->access_charset);
insert_sql.set_charset(share->access_charset);
update_sql.set_charset(share->access_charset);
tmp_sql.set_charset(share->access_charset);
+ dup_update_sql.set_charset(share->access_charset);
upd_tmp_tbl_prm.init();
upd_tmp_tbl_prm.field_count = 1;
if (!(link_for_hash = (SPIDER_LINK_FOR_HASH *)
@@ -7622,6 +9097,7 @@ int spider_mbase_handler::append_insert(
) {
SPIDER_SHARE *share = spider->share;
DBUG_ENTER("spider_mbase_handler::append_insert");
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_INSERT;
if (
(
spider->write_can_replace ||
@@ -7631,6 +9107,7 @@ int spider_mbase_handler::append_insert(
) &&
spider->direct_dup_insert
) {
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_REPLACE;
if (str->reserve(SPIDER_SQL_REPLACE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_REPLACE_STR, SPIDER_SQL_REPLACE_LEN);
@@ -7678,6 +9155,7 @@ int spider_mbase_handler::append_insert(
spider->sql_command != SQLCOM_REPLACE &&
spider->sql_command != SQLCOM_REPLACE_SELECT
) {
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_IGNORE;
if (str->reserve(SPIDER_SQL_SQL_IGNORE_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_SQL_IGNORE_STR, SPIDER_SQL_SQL_IGNORE_LEN);
@@ -8895,6 +10373,7 @@ int spider_mbase_handler::append_is_null(
key->flag == HA_READ_KEY_EXACT ||
key->flag == HA_READ_KEY_OR_NEXT
) {
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
if (tgt_final)
{
if (str->reserve(SPIDER_SQL_EQUAL_LEN))
@@ -8905,11 +10384,23 @@ int spider_mbase_handler::append_is_null(
if (str->reserve(SPIDER_SQL_NULL_LEN))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN);
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ if (str->reserve(SPIDER_SQL_EQUAL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_EQUAL_STR, SPIDER_SQL_EQUAL_LEN);
+ str = str_part;
+ if (str->reserve(SPIDER_SQL_NULL_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN);
+ }
+#endif
} else {
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
{
str = str_part;
- /* first index column */
str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
ha_next_pos = str->length();
if (str->reserve(SPIDER_SQL_FIRST_LEN))
@@ -8926,6 +10417,19 @@ int spider_mbase_handler::append_is_null(
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_NULL_STR, SPIDER_SQL_NULL_LEN);
}
+#else
+ if (str_part->length() == SPIDER_SQL_OPEN_PAREN_LEN)
+ {
+ str = str_part;
+ /* first index column */
+ str->length(str->length() - SPIDER_SQL_OPEN_PAREN_LEN);
+ ha_next_pos = str->length();
+ if (str->reserve(SPIDER_SQL_FIRST_LEN))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ str->q_append(SPIDER_SQL_FIRST_STR, SPIDER_SQL_FIRST_LEN);
+ spider->result_list.ha_read_kind = 1;
+ }
+#endif
}
str = str_part2;
}
@@ -9007,7 +10511,9 @@ int spider_mbase_handler::append_where_terminator(
} else {
str_part2->length(str_part2->length() - SPIDER_SQL_AND_LEN);
+#ifdef SPIDER_HANDLER_SUPPORT_MULTIPLE_KEY_PARTS
str_part->length(str_part->length() - SPIDER_SQL_COMMA_LEN);
+#endif
if (!result_list->ha_read_kind)
str_part->q_append(SPIDER_SQL_CLOSE_PAREN_STR,
SPIDER_SQL_CLOSE_PAREN_LEN);
@@ -10516,6 +12022,7 @@ int spider_mbase_handler::append_insert_terminator(
dup_update_sql.length()
) {
DBUG_PRINT("info",("spider add duplicate key update"));
+ direct_insert_kind = SPIDER_SQL_DIRECT_INSERT_KIND_DUP_UPDATE;
str->length(str->length() - SPIDER_SQL_COMMA_LEN);
if (str->reserve(SPIDER_SQL_DUPLICATE_KEY_UPDATE_LEN +
dup_update_sql.length()))
@@ -12177,16 +13684,9 @@ int spider_mbase_handler::show_table_status(
pthread_mutex_unlock(&conn->mta_conn_mutex);
error_num = res->fetch_table_status(
sts_mode,
- share->records,
- share->mean_rec_length,
- share->data_file_length,
- share->max_data_file_length,
- share->index_file_length,
- auto_increment_value,
- share->create_time,
- share->update_time,
- share->check_time
+ share->stat
);
+ auto_increment_value = share->stat.auto_increment_value;
res->free_result();
delete res;
if (error_num)
@@ -12311,16 +13811,9 @@ int spider_mbase_handler::show_table_status(
pthread_mutex_unlock(&conn->mta_conn_mutex);
error_num = res->fetch_table_status(
sts_mode,
- share->records,
- share->mean_rec_length,
- share->data_file_length,
- share->max_data_file_length,
- share->index_file_length,
- auto_increment_value,
- share->create_time,
- share->update_time,
- share->check_time
+ share->stat
);
+ auto_increment_value = share->stat.auto_increment_value;
res->free_result();
delete res;
if (error_num)
@@ -12349,11 +13842,11 @@ int spider_mbase_handler::show_table_status(
}
if (share->static_records_for_status != -1)
{
- share->records = (ha_rows) share->static_records_for_status;
+ share->stat.records = (ha_rows) share->static_records_for_status;
}
if (share->static_mean_rec_length != -1)
{
- share->mean_rec_length = (ulong) share->static_mean_rec_length;
+ share->stat.mean_rec_length = (ulong) share->static_mean_rec_length;
}
if (auto_increment_value > share->lgtm_tblhnd_share->auto_increment_value)
{
@@ -12657,7 +14150,8 @@ int spider_mbase_handler::show_index(
DBUG_RETURN(0);
}
-int spider_mbase_handler::show_records(
+int spider_mbase_handler::simple_action(
+ uint simple_action,
int link_idx
) {
int error_num;
@@ -12665,7 +14159,49 @@ int spider_mbase_handler::show_records(
SPIDER_DB_RESULT *res;
SPIDER_SHARE *share = spider->share;
uint pos = spider->conn_link_idx[link_idx];
- DBUG_ENTER("spider_mbase_handler::show_records");
+ spider_string *str = NULL;
+ DBUG_ENTER("spider_mbase_handler::simple_action");
+ switch (simple_action)
+ {
+ case SPIDER_SIMPLE_RECORDS:
+ DBUG_PRINT("info",("spider simple records"));
+ str = &mysql_share->show_records[pos];
+ break;
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ case SPIDER_SIMPLE_CHECKSUM_TABLE:
+ DBUG_PRINT("info",("spider simple checksum_table"));
+ str = &spider->result_list.sqls[link_idx];
+ str->length(0);
+ if (str->reserve(
+ SPIDER_SQL_CHECKSUM_TABLE_LEN +
+ mysql_share->db_nm_max_length +
+ SPIDER_SQL_DOT_LEN +
+ mysql_share->table_nm_max_length +
+ /* SPIDER_SQL_NAME_QUOTE_LEN */ 4 +
+ ((spider->action_flags & T_QUICK) ? SPIDER_SQL_SQL_QUICK_LEN : 0) +
+ ((spider->action_flags & T_EXTEND) ? SPIDER_SQL_SQL_EXTENDED_LEN : 0)
+ ))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_CHECKSUM_TABLE_STR,
+ SPIDER_SQL_CHECKSUM_TABLE_LEN);
+ mysql_share->append_table_name(str, pos);
+ if (spider->action_flags & T_QUICK)
+ {
+ str->q_append(SPIDER_SQL_SQL_QUICK_STR, SPIDER_SQL_SQL_QUICK_LEN);
+ }
+ if (spider->action_flags & T_EXTEND)
+ {
+ str->q_append(SPIDER_SQL_SQL_EXTENDED_STR,
+ SPIDER_SQL_SQL_EXTENDED_LEN);
+ }
+ break;
+#endif
+ default:
+ DBUG_ASSERT(0);
+ DBUG_RETURN(0);
+ }
pthread_mutex_lock(&conn->mta_conn_mutex);
SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos);
conn->need_mon = &spider->need_mons[link_idx];
@@ -12678,8 +14214,8 @@ int spider_mbase_handler::show_records(
(
spider_db_query(
conn,
- mysql_share->show_records[pos].ptr(),
- mysql_share->show_records[pos].length(),
+ str->ptr(),
+ str->length(),
-1,
&spider->need_mons[link_idx]) &&
(error_num = spider_db_errorno(conn))
@@ -12712,8 +14248,8 @@ int spider_mbase_handler::show_records(
share);
if (spider_db_query(
conn,
- mysql_share->show_records[pos].ptr(),
- mysql_share->show_records[pos].length(),
+ str->ptr(),
+ str->length(),
-1,
&spider->need_mons[link_idx])
) {
@@ -12755,10 +14291,22 @@ int spider_mbase_handler::show_records(
conn->mta_conn_mutex_unlock_later = FALSE;
SPIDER_CLEAR_FILE_POS(&conn->mta_conn_mutex_file_pos);
pthread_mutex_unlock(&conn->mta_conn_mutex);
- error_num = res->fetch_table_records(
- 1,
- spider->table_rows
- );
+ switch (simple_action)
+ {
+ case SPIDER_SIMPLE_RECORDS:
+ DBUG_PRINT("info",("spider simple records"));
+ error_num = res->fetch_table_records(1, spider->table_rows);
+ break;
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ case SPIDER_SIMPLE_CHECKSUM_TABLE:
+ DBUG_PRINT("info",("spider simple checksum_table"));
+ error_num = res->fetch_table_checksum(spider);
+ break;
+#endif
+ default:
+ DBUG_ASSERT(0);
+ break;
+ }
res->free_result();
delete res;
if (error_num)
@@ -12766,10 +14314,34 @@ int spider_mbase_handler::show_records(
DBUG_PRINT("info", ("spider error_num=%d 7", error_num));
DBUG_RETURN(error_num);
}
+ DBUG_RETURN(0);
+}
+
+int spider_mbase_handler::show_records(
+ int link_idx
+) {
+ int error_num;
+ DBUG_ENTER("spider_mbase_handler::show_records");
+ error_num = simple_action(SPIDER_SIMPLE_RECORDS, link_idx);
+ if (error_num)
+ {
+ DBUG_PRINT("info", ("spider error_num=%d", error_num));
+ DBUG_RETURN(error_num);
+ }
spider->trx->direct_aggregate_count++;
DBUG_RETURN(0);
}
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+int spider_mbase_handler::checksum_table(
+ int link_idx
+) {
+ DBUG_ENTER("spider_mbase_handler::checksum_table");
+ DBUG_RETURN(simple_action(SPIDER_SIMPLE_CHECKSUM_TABLE, link_idx));
+ DBUG_RETURN(0);
+}
+#endif
+
int spider_mbase_handler::show_last_insert_id(
int link_idx,
ulonglong &last_insert_id
@@ -13772,7 +15344,7 @@ int spider_mbase_handler::append_list_item_select(
))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN);
- if ((error_num = spider_db_mbase_utility->append_name(str,
+ if ((error_num = spider_db_mbase_utility->append_escaped_name(str,
item_name, length)))
{
DBUG_RETURN(error_num);
diff --git a/storage/spider/spd_db_mysql.h b/storage/spider/spd_db_mysql.h
index d50bb0d1f9d..626bb4d5624 100644
--- a/storage/spider/spd_db_mysql.h
+++ b/storage/spider/spd_db_mysql.h
@@ -29,6 +29,17 @@ public:
uint name_length,
CHARSET_INFO *name_charset
);
+ int append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+ );
+ int append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+ );
bool is_name_quote(
const char head_code
);
@@ -64,6 +75,18 @@ public:
spider_string *str,
bool sql_log_off
);
+ int append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+ );
+ virtual int append_sql_mode_internal(
+ spider_string *str,
+ sql_mode_t sql_mode
+ );
+ int append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+ );
int append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -179,6 +202,13 @@ class spider_db_mysql_util: public spider_db_mbase_util
public:
spider_db_mysql_util();
~spider_db_mysql_util();
+ int append_column_value(
+ ha_spider *spider,
+ spider_string *str,
+ Field *field,
+ const uchar *new_ptr,
+ CHARSET_INFO *access_charset
+ );
};
class spider_db_mariadb_util: public spider_db_mbase_util
@@ -186,6 +216,17 @@ class spider_db_mariadb_util: public spider_db_mbase_util
public:
spider_db_mariadb_util();
~spider_db_mariadb_util();
+ int append_sql_mode_internal(
+ spider_string *str,
+ sql_mode_t sql_mode
+ );
+ int append_column_value(
+ ha_spider *spider,
+ spider_string *str,
+ Field *field,
+ const uchar *new_ptr,
+ CHARSET_INFO *access_charset
+ );
};
class spider_db_mbase_row: public spider_db_row
@@ -267,20 +308,22 @@ public:
);
int fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
+ );
+ int fetch_simple_action(
+ uint simple_action,
+ uint position,
+ void *param
);
int fetch_table_records(
int mode,
ha_rows &records
);
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ int fetch_table_checksum(
+ ha_spider *spider
+ );
+#endif
int fetch_table_cardinality(
int mode,
TABLE *table,
@@ -410,6 +453,11 @@ public:
);
int next_result();
uint affected_rows();
+ uint matched_rows();
+ bool inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+ );
ulonglong last_insert_id();
int set_character_set(
const char *csname
@@ -466,6 +514,16 @@ public:
bool sql_log_off,
int *need_mon
);
+ bool set_wait_timeout_in_bulk_sql();
+ int set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+ );
+ bool set_sql_mode_in_bulk_sql();
+ int set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+ );
bool set_time_zone_in_bulk_sql();
int set_time_zone(
Time_zone *time_zone,
@@ -660,6 +718,9 @@ public:
spider_string *str
);
#endif
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ bool checksum_support();
+#endif
protected:
int create_table_names_str();
void free_table_names_str();
@@ -745,6 +806,7 @@ public:
spider_mbase_share *mysql_share;
SPIDER_LINK_FOR_HASH *link_for_hash;
uchar *minimum_select_bitmap;
+ uchar direct_insert_kind;
spider_mbase_handler(
ha_spider *spider,
spider_mbase_share *share,
@@ -1439,9 +1501,18 @@ public:
int link_idx,
int crd_mode
);
+ int simple_action(
+ uint simple_action,
+ int link_idx
+ );
int show_records(
int link_idx
);
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ int checksum_table(
+ int link_idx
+ );
+#endif
int show_last_insert_id(
int link_idx,
ulonglong &last_insert_id
diff --git a/storage/spider/spd_db_oracle.cc b/storage/spider/spd_db_oracle.cc
index 08d7d3e083d..dff0060b0c7 100644
--- a/storage/spider/spd_db_oracle.cc
+++ b/storage/spider/spd_db_oracle.cc
@@ -927,30 +927,22 @@ SPIDER_DB_ROW *spider_db_oracle_result::fetch_row_from_tmp_table(
int spider_db_oracle_result::fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
) {
DBUG_ENTER("spider_db_oracle_result::fetch_table_status");
DBUG_PRINT("info",("spider this=%p", this));
/* TODO: develop later */
- records = 2;
- mean_rec_length = 65535;
- data_file_length = 65535;
- max_data_file_length = 65535;
- index_file_length = 65535;
+ stat.records = 2;
+ stat.mean_rec_length = 65535;
+ stat.data_file_length = 65535;
+ stat.max_data_file_length = 65535;
+ stat.index_file_length = 65535;
/*
auto_increment_value = 0;
*/
- create_time = (time_t) 0;
- update_time = (time_t) 0;
- check_time = (time_t) 0;
+ stat.create_time = (time_t) 0;
+ stat.update_time = (time_t) 0;
+ stat.check_time = (time_t) 0;
DBUG_RETURN(0);
}
@@ -1349,7 +1341,7 @@ int spider_db_oracle::connect(
this->connect_retry_interval = connect_retry_interval;
if ((error_num = spider_create_conn_thread(conn)))
DBUG_RETURN(error_num);
- spider_bg_conn_simple_action(conn, SPIDER_BG_SIMPLE_CONNECT, TRUE, NULL,
+ spider_bg_conn_simple_action(conn, SPIDER_SIMPLE_CONNECT, TRUE, NULL,
0, NULL);
if (stored_error_num)
@@ -1440,7 +1432,7 @@ void spider_db_oracle::disconnect()
DBUG_PRINT("info",("spider this=%p", this));
if (!conn->bg_init)
DBUG_VOID_RETURN;
- spider_bg_conn_simple_action(conn, SPIDER_BG_SIMPLE_DISCONNECT, TRUE, NULL,
+ spider_bg_conn_simple_action(conn, SPIDER_SIMPLE_DISCONNECT, TRUE, NULL,
0, NULL);
DBUG_VOID_RETURN;
}
@@ -1739,6 +1731,22 @@ uint spider_db_oracle::affected_rows()
DBUG_RETURN(update_rows);
}
+uint spider_db_oracle::matched_rows()
+{
+ DBUG_ENTER("spider_db_oracle::matched_rows");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(0);
+}
+
+bool spider_db_oracle::inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+) {
+ DBUG_ENTER("spider_db_oracle::inserted_info");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
ulonglong spider_db_oracle::last_insert_id()
{
DBUG_ENTER("spider_db_oracle::last_insert_id");
@@ -2104,6 +2112,40 @@ int spider_db_oracle::set_sql_log_off(
DBUG_RETURN(0);
}
+bool spider_db_oracle::set_wait_timeout_in_bulk_sql()
+{
+ DBUG_ENTER("spider_db_oracle::set_wait_timeout_in_bulk_sql");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
+int spider_db_oracle::set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+) {
+ DBUG_ENTER("spider_db_oracle::set_wait_timeout");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
+bool spider_db_oracle::set_sql_mode_in_bulk_sql()
+{
+ DBUG_ENTER("spider_db_oracle::set_sql_mode_in_bulk_sql");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_RETURN(FALSE);
+}
+
+int spider_db_oracle::set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+) {
+ DBUG_ENTER("spider_db_oracle::set_sql_mode");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
bool spider_db_oracle::set_time_zone_in_bulk_sql()
{
DBUG_ENTER("spider_db_oracle::set_time_zone_in_bulk_sql");
@@ -2519,6 +2561,57 @@ int spider_db_oracle_util::append_name_with_charset(
DBUG_RETURN(0);
}
+int spider_db_oracle_util::append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_oracle_util::append_name");
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ if ((error_num = spider_db_append_name_with_quote_str_internal(
+ str, name, name_length, dbton_id)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
+int spider_db_oracle_util::append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+) {
+ int error_num;
+ DBUG_ENTER("spider_db_oracle_util::append_name_with_charset");
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN * 2 + name_length * 2))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ if ((error_num = spider_db_append_name_with_quote_str_internal(
+ str, name, name_length, name_charset, dbton_id)))
+ {
+ DBUG_RETURN(error_num);
+ }
+ if (str->reserve(SPIDER_SQL_NAME_QUOTE_LEN))
+ {
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ }
+ str->q_append(SPIDER_SQL_NAME_QUOTE_STR, SPIDER_SQL_NAME_QUOTE_LEN);
+ DBUG_RETURN(0);
+}
+
bool spider_db_oracle_util::is_name_quote(
const char head_code
) {
@@ -2810,6 +2903,26 @@ int spider_db_oracle_util::append_sql_log_off(
DBUG_RETURN(0);
}
+int spider_db_oracle_util::append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+) {
+ DBUG_ENTER("spider_db_oracle_util::append_wait_timeout");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
+int spider_db_oracle_util::append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+) {
+ DBUG_ENTER("spider_db_oracle_util::append_sql_mode");
+ DBUG_PRINT("info",("spider this=%p", this));
+ /* nothing to do */
+ DBUG_RETURN(0);
+}
+
int spider_db_oracle_util::append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -4016,13 +4129,31 @@ int spider_db_oracle_util::open_item_func(
case Item_func::LE_FUNC:
case Item_func::GE_FUNC:
case Item_func::GT_FUNC:
- case Item_func::LIKE_FUNC:
if (str)
{
func_name = (char*) item_func->func_name();
func_name_length = strlen(func_name);
}
break;
+ case Item_func::LIKE_FUNC:
+#ifdef SPIDER_LIKE_FUNC_HAS_GET_NEGATED
+ if (str)
+ {
+ if (((Item_func_like *)item_func)->get_negated())
+ {
+ func_name = SPIDER_SQL_NOT_LIKE_STR;
+ func_name_length = SPIDER_SQL_NOT_LIKE_LEN;
+ }
+ else
+ {
+ func_name = (char*)item_func->func_name();
+ func_name_length = strlen(func_name);
+ }
+ }
+ break;
+#else
+ DBUG_RETURN(ER_SPIDER_COND_SKIP_NUM);
+#endif
default:
THD *thd = spider->trx->thd;
SPIDER_SHARE *share = spider->share;
@@ -5380,10 +5511,12 @@ int spider_oracle_handler::init()
}
sql.set_charset(share->access_charset);
sql_part.set_charset(share->access_charset);
+ sql_part2.set_charset(share->access_charset);
ha_sql.set_charset(share->access_charset);
insert_sql.set_charset(share->access_charset);
update_sql.set_charset(share->access_charset);
tmp_sql.set_charset(share->access_charset);
+ dup_update_sql.set_charset(share->access_charset);
upd_tmp_tbl_prm.init();
upd_tmp_tbl_prm.field_count = 1;
if (!(link_for_hash = (SPIDER_LINK_FOR_HASH *)
@@ -11096,15 +11229,15 @@ int spider_oracle_handler::show_table_status(
if (error_num)
DBUG_RETURN(error_num);
*/
- if (!share->records)
- share->records = 10000;
- share->mean_rec_length = 65535;
- share->data_file_length = 65535;
- share->max_data_file_length = 65535;
- share->index_file_length = 65535;
- share->create_time = (time_t) 0;
- share->update_time = (time_t) 0;
- share->check_time = (time_t) 0;
+ if (!share->stat.records)
+ share->stat.records = 10000;
+ share->stat.mean_rec_length = 65535;
+ share->stat.data_file_length = 65535;
+ share->stat.max_data_file_length = 65535;
+ share->stat.index_file_length = 65535;
+ share->stat.create_time = (time_t) 0;
+ share->stat.update_time = (time_t) 0;
+ share->stat.check_time = (time_t) 0;
} else {
pthread_mutex_lock(&conn->mta_conn_mutex);
SPIDER_SET_FILE_POS(&conn->mta_conn_mutex_file_pos);
@@ -11188,16 +11321,9 @@ int spider_oracle_handler::show_table_status(
pthread_mutex_unlock(&conn->mta_conn_mutex);
error_num = res->fetch_table_status(
sts_mode,
- share->records,
- share->mean_rec_length,
- share->data_file_length,
- share->max_data_file_length,
- share->index_file_length,
- auto_increment_value,
- share->create_time,
- share->update_time,
- share->check_time
+ share->stat
);
+ auto_increment_value = share->stat.auto_increment_value;
res->free_result();
delete res;
if (error_num)
@@ -12725,7 +12851,7 @@ int spider_oracle_handler::append_list_item_select(
))
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
str->q_append(SPIDER_SQL_SPACE_STR, SPIDER_SQL_SPACE_LEN);
- if ((error_num = spider_db_oracle_utility.append_name(str,
+ if ((error_num = spider_db_oracle_utility.append_escaped_name(str,
item_name, length)))
{
DBUG_RETURN(error_num);
diff --git a/storage/spider/spd_db_oracle.h b/storage/spider/spd_db_oracle.h
index 28836f9e340..ebdc23a9bfa 100644
--- a/storage/spider/spd_db_oracle.h
+++ b/storage/spider/spd_db_oracle.h
@@ -32,6 +32,17 @@ public:
uint name_length,
CHARSET_INFO *name_charset
);
+ int append_escaped_name(
+ spider_string *str,
+ const char *name,
+ uint name_length
+ );
+ int append_escaped_name_with_charset(
+ spider_string *str,
+ const char *name,
+ uint name_length,
+ CHARSET_INFO *name_charset
+ );
bool is_name_quote(
const char head_code
);
@@ -67,6 +78,14 @@ public:
spider_string *str,
bool sql_log_off
);
+ int append_wait_timeout(
+ spider_string *str,
+ int wait_timeout
+ );
+ int append_sql_mode(
+ spider_string *str,
+ sql_mode_t sql_mode
+ );
int append_time_zone(
spider_string *str,
Time_zone *time_zone
@@ -235,15 +254,7 @@ public:
);
int fetch_table_status(
int mode,
- ha_rows &records,
- ulong &mean_rec_length,
- ulonglong &data_file_length,
- ulonglong &max_data_file_length,
- ulonglong &index_file_length,
- ulonglong &auto_increment_value,
- time_t &create_time,
- time_t &update_time,
- time_t &check_time
+ ha_statistics &stat
);
int fetch_table_records(
int mode,
@@ -374,6 +385,11 @@ public:
);
int next_result();
uint affected_rows();
+ uint matched_rows();
+ bool inserted_info(
+ spider_db_handler *handler,
+ ha_copy_info *copy_info
+ );
ulonglong last_insert_id();
int set_character_set(
const char *csname
@@ -430,6 +446,16 @@ public:
bool sql_log_off,
int *need_mon
);
+ bool set_wait_timeout_in_bulk_sql();
+ int set_wait_timeout(
+ int wait_timeout,
+ int *need_mon
+ );
+ bool set_sql_mode_in_bulk_sql();
+ int set_sql_mode(
+ sql_mode_t sql_mode,
+ int *need_mon
+ );
bool set_time_zone_in_bulk_sql();
int set_time_zone(
Time_zone *time_zone,
diff --git a/storage/spider/spd_environ.h b/storage/spider/spd_environ.h
index 5e66a912582..728cc7e1781 100644
--- a/storage/spider/spd_environ.h
+++ b/storage/spider/spd_environ.h
@@ -25,6 +25,7 @@
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100100
#define SPIDER_SUPPORT_CREATE_OR_REPLACE_TABLE
+#define SPIDER_NET_HAS_THD
#endif
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100211
@@ -49,5 +50,7 @@
#if defined(MARIADB_BASE_VERSION) && MYSQL_VERSION_ID >= 100400
#define SPIDER_USE_CONST_ITEM_FOR_STRING_INT_REAL_DECIMAL_DATE_ITEM
#define SPIDER_SQL_CACHE_IS_IN_LEX
+#define SPIDER_LIKE_FUNC_HAS_GET_NEGATED
+#define HA_HAS_CHECKSUM_EXTENDED
#endif
#endif /* SPD_ENVIRON_INCLUDED */
diff --git a/storage/spider/spd_err.h b/storage/spider/spd_err.h
index a80d903bd6e..9889fcfa7fb 100644
--- a/storage/spider/spd_err.h
+++ b/storage/spider/spd_err.h
@@ -124,6 +124,9 @@
#define ER_SPIDER_CON_COUNT_ERROR_STR "Too many connections between spider and remote"
#define ER_SPIDER_TABLE_OPEN_TIMEOUT_NUM 12714
#define ER_SPIDER_TABLE_OPEN_TIMEOUT_STR "Table %s.%s open timeout"
+#define ER_SPIDER_SAME_SERVER_LINK_NUM 12720
+#define ER_SPIDER_SAME_SERVER_LINK_STR1 "Host:%s and Socket:%s aim self server. Please change spider_same_server_link parameter if this link is required."
+#define ER_SPIDER_SAME_SERVER_LINK_STR2 "Host:%s and Port:%ld aim self server. Please change spider_same_server_link parameter if this link is required."
#define ER_SPIDER_COND_SKIP_NUM 12801
#define ER_SPIDER_UNKNOWN_NUM 12500
diff --git a/storage/spider/spd_group_by_handler.cc b/storage/spider/spd_group_by_handler.cc
index 3b57092c4ce..314ecd018a5 100644
--- a/storage/spider/spd_group_by_handler.cc
+++ b/storage/spider/spd_group_by_handler.cc
@@ -1639,21 +1639,18 @@ group_by_handler *spider_create_group_by_handler(
if (from->table->part_info)
{
DBUG_PRINT("info",("spider partition handler"));
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
- ha_partition *partition = (ha_partition *) from->table->file;
- part_id_range *part_spec = partition->get_part_spec();
- DBUG_PRINT("info",("spider part_spec->start_part=%u", part_spec->start_part));
- DBUG_PRINT("info",("spider part_spec->end_part=%u", part_spec->end_part));
- if (
- part_spec->start_part == partition->get_no_current_part_id() ||
- part_spec->start_part != part_spec->end_part
- ) {
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
+ partition_info *part_info = from->table->part_info;
+ uint bits = bitmap_bits_set(&part_info->read_partitions);
+ DBUG_PRINT("info",("spider bits=%u", bits));
+ if (bits != 1)
+ {
DBUG_PRINT("info",("spider using multiple partitions is not supported by this feature yet"));
#else
DBUG_PRINT("info",("spider partition is not supported by this feature yet"));
#endif
DBUG_RETURN(NULL);
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
}
#endif
}
@@ -1671,17 +1668,18 @@ group_by_handler *spider_create_group_by_handler(
/* all tables are const_table */
DBUG_RETURN(NULL);
}
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
if (from->table->part_info)
{
+ partition_info *part_info = from->table->part_info;
+ uint part = bitmap_get_first_set(&part_info->read_partitions);
ha_partition *partition = (ha_partition *) from->table->file;
- part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
- spider = (ha_spider *) handlers[part_spec->start_part];
+ spider = (ha_spider *) handlers[part];
} else {
#endif
spider = (ha_spider *) from->table->file;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
}
#endif
share = spider->share;
@@ -1702,17 +1700,18 @@ group_by_handler *spider_create_group_by_handler(
{
if (from->table->const_table)
continue;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
if (from->table->part_info)
{
+ partition_info *part_info = from->table->part_info;
+ uint part = bitmap_get_first_set(&part_info->read_partitions);
ha_partition *partition = (ha_partition *) from->table->file;
- part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
- spider = (ha_spider *) handlers[part_spec->start_part];
+ spider = (ha_spider *) handlers[part];
} else {
#endif
spider = (ha_spider *) from->table->file;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
}
#endif
share = spider->share;
@@ -1740,17 +1739,18 @@ group_by_handler *spider_create_group_by_handler(
do {
if (from->table->const_table)
continue;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
if (from->table->part_info)
{
+ partition_info *part_info = from->table->part_info;
+ uint part = bitmap_get_first_set(&part_info->read_partitions);
ha_partition *partition = (ha_partition *) from->table->file;
- part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
- spider = (ha_spider *) handlers[part_spec->start_part];
+ spider = (ha_spider *) handlers[part];
} else {
#endif
spider = (ha_spider *) from->table->file;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
}
#endif
share = spider->share;
@@ -1888,17 +1888,18 @@ group_by_handler *spider_create_group_by_handler(
{
from = from->next_local;
}
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
if (from->table->part_info)
{
+ partition_info *part_info = from->table->part_info;
+ uint part = bitmap_get_first_set(&part_info->read_partitions);
ha_partition *partition = (ha_partition *) from->table->file;
- part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
- spider = (ha_spider *) handlers[part_spec->start_part];
+ spider = (ha_spider *) handlers[part];
} else {
#endif
spider = (ha_spider *) from->table->file;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
}
#endif
share = spider->share;
@@ -1976,17 +1977,18 @@ group_by_handler *spider_create_group_by_handler(
continue;
fields->clear_conn_holder_from_conn();
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
if (from->table->part_info)
{
+ partition_info *part_info = from->table->part_info;
+ uint part = bitmap_get_first_set(&part_info->read_partitions);
ha_partition *partition = (ha_partition *) from->table->file;
- part_id_range *part_spec = partition->get_part_spec();
handler **handlers = partition->get_child_handlers();
- spider = (ha_spider *) handlers[part_spec->start_part];
+ spider = (ha_spider *) handlers[part];
} else {
#endif
spider = (ha_spider *) from->table->file;
-#if defined(PARTITION_HAS_GET_CHILD_HANDLERS) && defined(PARTITION_HAS_GET_PART_SPEC)
+#if defined(PARTITION_HAS_GET_CHILD_HANDLERS)
}
#endif
share = spider->share;
diff --git a/storage/spider/spd_include.h b/storage/spider/spd_include.h
index c32b476b474..2249d3e699c 100644
--- a/storage/spider/spd_include.h
+++ b/storage/spider/spd_include.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -13,7 +14,7 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
-#define SPIDER_DETAIL_VERSION "3.3.14"
+#define SPIDER_DETAIL_VERSION "3.3.15"
#define SPIDER_HEX_VERSION 0x0303
#if MYSQL_VERSION_ID < 50500
@@ -260,7 +261,7 @@ const char SPIDER_empty_string = "";
#define SPIDER_TMP_SHARE_LONG_COUNT 19
#define SPIDER_TMP_SHARE_LONGLONG_COUNT 3
-#define SPIDER_MEM_CALC_LIST_NUM 257
+#define SPIDER_MEM_CALC_LIST_NUM 268
#define SPIDER_CONN_META_BUF_LEN 64
#define SPIDER_BACKUP_DASTATUS \
@@ -292,6 +293,8 @@ typedef struct st_spider_thread
volatile bool killed;
volatile bool thd_wait;
volatile bool first_free_wait;
+ volatile bool init_command;
+ volatile int error;
pthread_t thread;
pthread_cond_t cond;
pthread_mutex_t mutex;
@@ -449,6 +452,8 @@ typedef struct st_spider_conn
bool disable_reconnect;
int autocommit;
int sql_log_off;
+ int wait_timeout;
+ sql_mode_t sql_mode;
THD *thd;
void *another_ha_first;
void *another_ha_last;
@@ -555,8 +560,10 @@ typedef struct st_spider_conn
bool queued_ping;
bool queued_trx_isolation;
bool queued_semi_trx_isolation;
+ bool queued_wait_timeout;
bool queued_autocommit;
bool queued_sql_log_off;
+ bool queued_sql_mode;
bool queued_time_zone;
bool queued_trx_start;
bool queued_xa_start;
@@ -567,8 +574,10 @@ typedef struct st_spider_conn
int queued_ping_link_idx;
int queued_trx_isolation_val;
int queued_semi_trx_isolation_val;
+ int queued_wait_timeout_val;
bool queued_autocommit_val;
bool queued_sql_log_off_val;
+ sql_mode_t queued_sql_mode_val;
Time_zone *queued_time_zone_val;
XID *queued_xa_start_xid;
@@ -652,15 +661,7 @@ typedef struct st_spider_patition_share
volatile bool crd_init;
volatile time_t sts_get_time;
volatile time_t crd_get_time;
- ulonglong data_file_length;
- ulonglong max_data_file_length;
- ulonglong index_file_length;
- ulonglong auto_increment_value;
- ha_rows records;
- ulong mean_rec_length;
- time_t check_time;
- time_t create_time;
- time_t update_time;
+ ha_statistics stat;
longlong *cardinality;
/*
@@ -887,17 +888,7 @@ typedef struct st_spider_share
volatile bool auto_increment_init;
volatile ulonglong auto_increment_lclval;
*/
- ulonglong data_file_length;
- ulonglong max_data_file_length;
- ulonglong index_file_length;
-/*
- ulonglong auto_increment_value;
-*/
- ha_rows records;
- ulong mean_rec_length;
- time_t check_time;
- time_t create_time;
- time_t update_time;
+ ha_statistics stat;
longlong static_records_for_status;
longlong static_mean_rec_length;
@@ -1461,7 +1452,7 @@ typedef struct st_spider_ip_port_conn {
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
my_hash_value_type key_hash_value;
#endif
- char remote_ip_str[SPIDER_CONN_META_BUF_LEN];
+ char *remote_ip_str;
long remote_port;
ulong ip_port_count;
volatile ulong waiting_count;
diff --git a/storage/spider/spd_init_query.h b/storage/spider/spd_init_query.h
new file mode 100644
index 00000000000..4c58f8d80a4
--- /dev/null
+++ b/storage/spider/spd_init_query.h
@@ -0,0 +1,782 @@
+/* Copyright (C) 2010-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ This SQL script creates system tables for SPIDER
+ or fixes incompatibilities if ones already exist.
+*/
+
+static LEX_STRING spider_init_queries[] = {
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_xa("
+ " format_id int not null default 0,"
+ " gtrid_length int not null default 0,"
+ " bqual_length int not null default 0,"
+ " data char(128) charset binary not null default '',"
+ " status char(8) not null default '',"
+ " primary key (data, format_id, gtrid_length),"
+ " key idx1 (status)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_xa_member("
+ " format_id int not null default 0,"
+ " gtrid_length int not null default 0,"
+ " bqual_length int not null default 0,"
+ " data char(128) charset binary not null default '',"
+ " scheme char(64) not null default '',"
+ " host char(64) not null default '',"
+ " port char(5) not null default '',"
+ " socket text not null,"
+ " username char(64) not null default '',"
+ " password char(64) not null default '',"
+ " ssl_ca text,"
+ " ssl_capath text,"
+ " ssl_cert text,"
+ " ssl_cipher char(64) default null,"
+ " ssl_key text,"
+ " ssl_verify_server_cert tinyint not null default 0,"
+ " default_file text,"
+ " default_group char(64) default null,"
+ " key idx1 (data, format_id, gtrid_length, host)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_xa_failed_log("
+ " format_id int not null default 0,"
+ " gtrid_length int not null default 0,"
+ " bqual_length int not null default 0,"
+ " data char(128) charset binary not null default '',"
+ " scheme char(64) not null default '',"
+ " host char(64) not null default '',"
+ " port char(5) not null default '',"
+ " socket text not null,"
+ " username char(64) not null default '',"
+ " password char(64) not null default '',"
+ " ssl_ca text,"
+ " ssl_capath text,"
+ " ssl_cert text,"
+ " ssl_cipher char(64) default null,"
+ " ssl_key text,"
+ " ssl_verify_server_cert tinyint not null default 0,"
+ " default_file text,"
+ " default_group char(64) default null,"
+ " thread_id int default null,"
+ " status char(8) not null default '',"
+ " failed_time timestamp not null default current_timestamp,"
+ " key idx1 (data, format_id, gtrid_length, host)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_tables("
+ " db_name char(64) not null default '',"
+ " table_name char(199) not null default '',"
+ " link_id int not null default 0,"
+ " priority bigint not null default 0,"
+ " server char(64) default null,"
+ " scheme char(64) default null,"
+ " host char(64) default null,"
+ " port char(5) default null,"
+ " socket text,"
+ " username char(64) default null,"
+ " password char(64) default null,"
+ " ssl_ca text,"
+ " ssl_capath text,"
+ " ssl_cert text,"
+ " ssl_cipher char(64) default null,"
+ " ssl_key text,"
+ " ssl_verify_server_cert tinyint not null default 0,"
+ " monitoring_binlog_pos_at_failing tinyint not null default 0,"
+ " default_file text,"
+ " default_group char(64) default null,"
+ " tgt_db_name char(64) default null,"
+ " tgt_table_name char(64) default null,"
+ " link_status tinyint not null default 1,"
+ " block_status tinyint not null default 0,"
+ " static_link_id char(64) default null,"
+ " primary key (db_name, table_name, link_id),"
+ " key idx1 (priority),"
+ " unique key uidx1 (db_name, table_name, static_link_id)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_link_mon_servers("
+ " db_name char(64) not null default '',"
+ " table_name char(199) not null default '',"
+ " link_id char(64) not null default '',"
+ " sid int unsigned not null default 0,"
+ " server char(64) default null,"
+ " scheme char(64) default null,"
+ " host char(64) default null,"
+ " port char(5) default null,"
+ " socket text,"
+ " username char(64) default null,"
+ " password char(64) default null,"
+ " ssl_ca text,"
+ " ssl_capath text,"
+ " ssl_cert text,"
+ " ssl_cipher char(64) default null,"
+ " ssl_key text,"
+ " ssl_verify_server_cert tinyint not null default 0,"
+ " default_file text,"
+ " default_group char(64) default null,"
+ " primary key (db_name, table_name, link_id, sid)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_link_failed_log("
+ " db_name char(64) not null default '',"
+ " table_name char(199) not null default '',"
+ " link_id char(64) not null default '',"
+ " failed_time timestamp not null default current_timestamp"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_table_position_for_recovery("
+ " db_name char(64) not null default '',"
+ " table_name char(199) not null default '',"
+ " failed_link_id int not null default 0,"
+ " source_link_id int not null default 0,"
+ " file text,"
+ " position text,"
+ " gtid text,"
+ " primary key (db_name, table_name, failed_link_id, source_link_id)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_table_sts("
+ " db_name char(64) not null default '',"
+ " table_name char(199) not null default '',"
+ " data_file_length bigint unsigned not null default 0,"
+ " max_data_file_length bigint unsigned not null default 0,"
+ " index_file_length bigint unsigned not null default 0,"
+ " records bigint unsigned not null default 0,"
+ " mean_rec_length bigint unsigned not null default 0,"
+ " check_time datetime not null default '0000-00-00 00:00:00',"
+ " create_time datetime not null default '0000-00-00 00:00:00',"
+ " update_time datetime not null default '0000-00-00 00:00:00',"
+ " checksum bigint unsigned default null,"
+ " primary key (db_name, table_name)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+ {C_STRING_WITH_LEN(
+ "create table if not exists mysql.spider_table_crd("
+ " db_name char(64) not null default '',"
+ " table_name char(199) not null default '',"
+ " key_seq int unsigned not null default 0,"
+ " cardinality bigint not null default 0,"
+ " primary key (db_name, table_name, key_seq)"
+ ") engine=MyISAM default charset=utf8 collate=utf8_bin"
+ )},
+/*
+ If tables already exist and their definition differ
+ from the latest ones, we fix them here.
+*/
+ {C_STRING_WITH_LEN(
+ "drop procedure if exists mysql.spider_fix_one_table"
+ )},
+ {C_STRING_WITH_LEN(
+ "drop procedure if exists mysql.spider_fix_system_tables"
+ )},
+ {C_STRING_WITH_LEN(
+ "create procedure mysql.spider_fix_one_table"
+ " (tab_name char(255) charset utf8 collate utf8_bin,"
+ " test_col_name char(255) charset utf8 collate utf8_bin,"
+ " _sql text charset utf8 collate utf8_bin)"
+ "begin"
+ " set @col_exists := 0;"
+ " select 1 into @col_exists from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = tab_name"
+ " AND COLUMN_NAME = test_col_name;"
+ " if @col_exists = 0 then"
+ " select @stmt := _sql;"
+ " prepare sp_stmt1 from @stmt;"
+ " execute sp_stmt1;"
+ " end if;"
+ "end;"
+ )},
+ {C_STRING_WITH_LEN(
+ "create procedure mysql.spider_fix_system_tables()"
+ "begin"
+ " select substring_index(substring_index(version(), '-', 2), '-', -1)"
+ " into @server_name;"
+ " select substring_index(version(), '.', 1)"
+ " into @server_major_version;"
+ " select substring_index(substring_index(version(), '.', 2), '.', -1)"
+ " into @server_minor_version;"
+/*
+ Fix for 0.5
+*/
+ " call mysql.spider_fix_one_table('spider_tables', 'server',"
+ " 'alter table mysql.spider_tables"
+ " add server char(64) default null,"
+ " add scheme char(64) default null,"
+ " add host char(64) default null,"
+ " add port char(5) default null,"
+ " add socket char(64) default null,"
+ " add username char(64) default null,"
+ " add password char(64) default null,"
+ " add tgt_db_name char(64) default null,"
+ " add tgt_table_name char(64) default null');"
+/*
+ Fix for version 0.17
+*/
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_xa'"
+ " AND COLUMN_NAME = 'data';"
+ " if @col_type != 'binary(128)' then"
+ " alter table mysql.spider_xa"
+ " modify data binary(128) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_xa_member'"
+ " AND COLUMN_NAME = 'data';"
+ " if @col_type != 'binary(128)' then"
+ " alter table mysql.spider_xa_member"
+ " modify data binary(128) not null default '';"
+ " end if;"
+/*
+ Fix for version 2.7
+*/
+ " call mysql.spider_fix_one_table('spider_tables', 'link_id',"
+ " 'alter table mysql.spider_tables"
+ " add column link_id int not null default 0 after table_name,"
+ " drop primary key,"
+ " add primary key (db_name, table_name, link_id)');"
+/*
+ Fix for version 2.8
+*/
+ " call mysql.spider_fix_one_table('spider_tables', 'link_status',"
+ " 'alter table mysql.spider_tables"
+ " add column link_status tinyint not null default 1');"
+/*
+ Fix for version 2.10
+*/
+ " call mysql.spider_fix_one_table('spider_xa_member', 'ssl_ca',"
+ " 'alter table mysql.spider_xa_member"
+ " add column ssl_ca char(64) default null after password,"
+ " add column ssl_capath char(64) default null after ssl_ca,"
+ " add column ssl_cert char(64) default null after ssl_capath,"
+ " add column ssl_cipher char(64) default null after ssl_cert,"
+ " add column ssl_key char(64) default null after ssl_cipher,"
+ " add column ssl_verify_server_cert tinyint not null default 0"
+ " after ssl_key,"
+ " add column default_file char(64) default null"
+ " after ssl_verify_server_cert,"
+ " add column default_group char(64) default null after default_file');"
+ " call mysql.spider_fix_one_table('spider_tables', 'ssl_ca',"
+ " 'alter table mysql.spider_tables"
+ " add column ssl_ca char(64) default null after password,"
+ " add column ssl_capath char(64) default null after ssl_ca,"
+ " add column ssl_cert char(64) default null after ssl_capath,"
+ " add column ssl_cipher char(64) default null after ssl_cert,"
+ " add column ssl_key char(64) default null after ssl_cipher,"
+ " add column ssl_verify_server_cert tinyint not null default 0"
+ " after ssl_key,"
+ " add column default_file char(64) default null"
+ " after ssl_verify_server_cert,"
+ " add column default_group char(64) default null after default_file');"
+ " call mysql.spider_fix_one_table('spider_link_mon_servers', 'ssl_ca',"
+ " 'alter table mysql.spider_link_mon_servers"
+ " add column ssl_ca char(64) default null after password,"
+ " add column ssl_capath char(64) default null after ssl_ca,"
+ " add column ssl_cert char(64) default null after ssl_capath,"
+ " add column ssl_cipher char(64) default null after ssl_cert,"
+ " add column ssl_key char(64) default null after ssl_cipher,"
+ " add column ssl_verify_server_cert tinyint not null default 0"
+ " after ssl_key,"
+ " add column default_file char(64) default null"
+ " after ssl_verify_server_cert,"
+ " add column default_group char(64) default null after default_file');"
+/*
+ Fix for version 2.28
+*/
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_mon_servers'"
+ " AND COLUMN_NAME = 'sid';"
+ " if @col_type != 'int(10) unsigned' then"
+ " alter table mysql.spider_link_mon_servers"
+ " modify sid int unsigned not null default 0;"
+ " end if;"
+/*
+ Fix for version 3.1
+*/
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_xa_member'"
+ " AND COLUMN_NAME = 'socket';"
+ " if @col_type = 'char(64)' then"
+ " alter table mysql.spider_xa_member"
+ " drop primary key,"
+ " add index idx1 (data, format_id, gtrid_length, host),"
+ " modify socket text not null,"
+ " modify ssl_ca text,"
+ " modify ssl_capath text,"
+ " modify ssl_cert text,"
+ " modify ssl_key text,"
+ " modify default_file text;"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_tables'"
+ " AND COLUMN_NAME = 'socket';"
+ " if @col_type = 'char(64)' then"
+ " alter table mysql.spider_tables"
+ " modify socket text,"
+ " modify ssl_ca text,"
+ " modify ssl_capath text,"
+ " modify ssl_cert text,"
+ " modify ssl_key text,"
+ " modify default_file text;"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_mon_servers'"
+ " AND COLUMN_NAME = 'socket';"
+ " if @col_type = 'char(64)' then"
+ " alter table mysql.spider_link_mon_servers"
+ " modify socket text,"
+ " modify ssl_ca text,"
+ " modify ssl_capath text,"
+ " modify ssl_cert text,"
+ " modify ssl_key text,"
+ " modify default_file text;"
+ " end if;"
+/*
+ Fix for version 3.3.0
+*/
+ " call mysql.spider_fix_one_table('spider_tables',"
+ " 'monitoring_binlog_pos_at_failing',"
+ " 'alter table mysql.spider_tables"
+ " add monitoring_binlog_pos_at_failing tinyint not null default 0"
+ " after ssl_verify_server_cert');"
+/*
+ Fix for version 3.3.6
+*/
+ " call mysql.spider_fix_one_table('spider_tables', 'block_status',"
+ " 'alter table mysql.spider_tables"
+ " add column block_status tinyint not null default 0"
+ " after link_status');"
+ " call mysql.spider_fix_one_table('spider_tables', 'static_link_id',"
+ " 'alter table mysql.spider_tables"
+ " add column static_link_id char(64) default null after block_status,"
+ " add unique index uidx1 (db_name, table_name, static_link_id)');"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_mon_servers'"
+ " AND COLUMN_NAME = 'link_id';"
+ " if @col_type != 'char(64)' then"
+ " alter table mysql.spider_link_mon_servers"
+ " modify link_id char(64) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_failed_log'"
+ " AND COLUMN_NAME = 'link_id';"
+ " if @col_type != 'char(64)' then"
+ " alter table mysql.spider_link_failed_log"
+ " modify link_id char(64) not null default '';"
+ " end if;"
+/*
+ Fix for version 3.3.10
+*/
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_tables'"
+ " AND COLUMN_NAME = 'table_name';"
+ " if @col_type != 'char(199)' then"
+ " alter table mysql.spider_tables"
+ " modify table_name char(199) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_mon_servers'"
+ " AND COLUMN_NAME = 'table_name';"
+ " if @col_type != 'char(199)' then"
+ " alter table mysql.spider_link_mon_servers"
+ " modify table_name char(199) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_failed_log'"
+ " AND COLUMN_NAME = 'table_name';"
+ " if @col_type != 'char(199)' then"
+ " alter table mysql.spider_link_failed_log"
+ " modify table_name char(199) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_table_position_for_recovery'"
+ " AND COLUMN_NAME = 'table_name';"
+ " if @col_type != 'char(199)' then"
+ " alter table mysql.spider_table_position_for_recovery"
+ " modify table_name char(199) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_table_sts'"
+ " AND COLUMN_NAME = 'table_name';"
+ " if @col_type != 'char(199)' then"
+ " alter table mysql.spider_table_sts"
+ " modify table_name char(199) not null default '';"
+ " end if;"
+ " select COLUMN_TYPE INTO @col_type from INFORMATION_SCHEMA.COLUMNS"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_table_crd'"
+ " AND COLUMN_NAME = 'table_name';"
+ " if @col_type != 'char(199)' then"
+ " alter table mysql.spider_table_crd"
+ " modify table_name char(199) not null default '';"
+ " end if;"
+/*
+ Fix for version 3.3.15
+*/
+ " call mysql.spider_fix_one_table('spider_table_sts', 'checksum',"
+ " 'alter table mysql.spider_table_sts"
+ " add column checksum bigint unsigned default null after update_time');"
+/*
+ Fix for MariaDB 10.4: Crash-Safe system tables
+*/
+ " if @server_name = 'MariaDB' and"
+ " ("
+ " @server_major_version > 10 or"
+ " ("
+ " @server_major_version = 10 and"
+ " @server_minor_version >= 4"
+ " )"
+ " )"
+ " then"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_failed_log';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_link_failed_log"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_link_mon_servers';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_link_mon_servers"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_table_crd';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_table_crd"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_table_position_for_recovery';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_table_position_for_recovery"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_table_sts';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_table_sts"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_tables';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_tables"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_xa';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_xa"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_xa_failed_log';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_xa_failed_log"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " select ENGINE INTO @engine_name from INFORMATION_SCHEMA.TABLES"
+ " where TABLE_SCHEMA = 'mysql'"
+ " AND TABLE_NAME = 'spider_xa_member';"
+ " if @engine_name != 'Aria' then"
+ " alter table mysql.spider_xa_member"
+ " engine=Aria transactional=1;"
+ " end if;"
+ " end if;"
+ " if @server_name = 'MariaDB' and"
+ " ("
+ " @server_major_version > 10 or"
+ " ("
+ " @server_major_version = 10 and"
+ " @server_minor_version >= 6"
+ " )"
+ " )"
+ " then"
+ " /* table for ddl pushdown */"
+ " create table if not exists mysql.spider_rewrite_tables("
+ " table_id bigint unsigned not null auto_increment,"
+ " db_name char(64) not null default '',"
+ " table_name char(64) not null default '',"
+ " primary key (table_id),"
+ " unique uk1(db_name, table_name)"
+ " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;"
+ " create table if not exists mysql.spider_rewrite_table_tables("
+ " table_id bigint unsigned not null,"
+ " partition_id bigint unsigned not null auto_increment,"
+ " partition_method varchar(18) default '',"
+ " partition_expression varchar(64) default '',"
+ " subpartition_method varchar(12) default '',"
+ " subpartition_expression varchar(64) default '',"
+ " connection_str text not null default '',"
+ " comment_str text not null default '',"
+ " primary key (table_id, partition_id),"
+ " unique uk1(table_id, partition_method, partition_expression,"
+ " subpartition_method, subpartition_expression)"
+ " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;"
+ " create table if not exists mysql.spider_rewrite_table_partitions("
+ " table_id bigint unsigned not null,"
+ " partition_id bigint unsigned not null,"
+ " partition_ordinal_position bigint unsigned not null auto_increment,"
+ " partition_name varchar(64) not null default '',"
+ " partition_description varchar(64) not null default '',"
+ " connection_str text not null default '',"
+ " comment_str text not null default '',"
+ " primary key (table_id, partition_id, partition_ordinal_position),"
+ " unique key uk1 (table_id, partition_id, partition_name)"
+ " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;"
+ " create table if not exists mysql.spider_rewrite_table_subpartitions("
+ " table_id bigint unsigned not null,"
+ " partition_id bigint unsigned not null,"
+ " partition_ordinal_position bigint unsigned not null,"
+ " subpartition_ordinal_position bigint unsigned not null"
+ " auto_increment,"
+ " subpartition_name varchar(64) not null default '',"
+ " subpartition_description varchar(64) not null default '',"
+ " connection_str text not null default '',"
+ " comment_str text not null default '',"
+ " primary key (table_id, partition_id, partition_ordinal_position,"
+ " subpartition_ordinal_position),"
+ " unique key uk1 (table_id, partition_id, partition_ordinal_position,"
+ " subpartition_name)"
+ " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;"
+ " create table if not exists mysql.spider_rewritten_tables("
+ " db_name char(64) not null,"
+ " table_name char(64) not null,"
+ " table_id bigint unsigned not null,"
+ " partition_id bigint unsigned not null,"
+ " primary key (db_name, table_name, table_id, partition_id)"
+ " ) engine=Aria transactional=1 default charset=utf8 collate=utf8_bin;"
+ " end if;"
+ "end;"
+ )},
+ {C_STRING_WITH_LEN(
+ "call mysql.spider_fix_system_tables"
+ )},
+ {C_STRING_WITH_LEN(
+ "drop procedure mysql.spider_fix_one_table"
+ )},
+ {C_STRING_WITH_LEN(
+ "drop procedure mysql.spider_fix_system_tables"
+ )},
+/*
+ Install a plugin and UDFs
+*/
+ {C_STRING_WITH_LEN(
+ "drop procedure if exists mysql.spider_plugin_installer"
+ )},
+ {C_STRING_WITH_LEN(
+ "create procedure mysql.spider_plugin_installer()"
+ "begin"
+ " set @win_plugin := IF(@@version_compile_os like 'Win%', 1, 0);"
+/*
+ Install spider plugin
+*/
+/*
+ " set @have_spider_i_s_plugin := 0;"
+ " select @have_spider_i_s_plugin := 1 from INFORMATION_SCHEMA.plugins"
+ " where PLUGIN_NAME = 'SPIDER';"
+ " set @have_spider_plugin := 0;"
+ " select @have_spider_plugin := 1 from mysql.plugin"
+ " where name = 'spider';"
+ " if @have_spider_i_s_plugin = 0 then"
+ " if @have_spider_plugin = 1 then"
+ " / *"
+ " spider plugin is present in mysql.plugin but not in"
+ " information_schema.plugins. Remove spider plugin entry"
+ " in mysql.plugin first."
+ " * /"
+ " delete from mysql.plugin where name = 'spider';"
+ " end if;"
+ " if @win_plugin = 0 then "
+ " install plugin spider soname 'ha_spider.so';"
+ " else"
+ " install plugin spider soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+*/
+/*
+ Install spider_alloc_mem plugin
+*/
+ " set @have_spider_i_s_alloc_mem_plugin := 0;"
+ " select @have_spider_i_s_alloc_mem_plugin := 1"
+ " from INFORMATION_SCHEMA.plugins"
+ " where PLUGIN_NAME = 'SPIDER_ALLOC_MEM';"
+ " set @have_spider_alloc_mem_plugin := 0;"
+ " select @have_spider_alloc_mem_plugin := 1 from mysql.plugin"
+ " where name = 'spider_alloc_mem';"
+ " if @have_spider_i_s_alloc_mem_plugin = 0 then"
+ " if @have_spider_alloc_mem_plugin = 1 then"
+ " /*"
+ " spider_alloc_mem plugin is present in mysql.plugin but not in"
+ " information_schema.plugins. Remove spider_alloc_mem plugin entry"
+ " in mysql.plugin first."
+ " */"
+ " delete from mysql.plugin where name = 'spider_alloc_mem';"
+ " end if;"
+ " if @win_plugin = 0 then "
+ " install plugin spider_alloc_mem soname 'ha_spider.so';"
+ " else"
+ " install plugin spider_alloc_mem soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " set @have_spider_direct_sql_udf := 0;"
+ " select @have_spider_direct_sql_udf := 1 from mysql.func"
+ " where name = 'spider_direct_sql';"
+ " if @have_spider_direct_sql_udf = 0 then"
+ " if @win_plugin = 0 then "
+ " create function spider_direct_sql returns int"
+ " soname 'ha_spider.so';"
+ " else"
+ " create function spider_direct_sql returns int"
+ " soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " set @have_spider_bg_direct_sql_udf := 0;"
+ " select @have_spider_bg_direct_sql_udf := 1 from mysql.func"
+ " where name = 'spider_bg_direct_sql';"
+ " if @have_spider_bg_direct_sql_udf = 0 then"
+ " if @win_plugin = 0 then "
+ " create aggregate function spider_bg_direct_sql returns int"
+ " soname 'ha_spider.so';"
+ " else"
+ " create aggregate function spider_bg_direct_sql returns int"
+ " soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " set @have_spider_ping_table_udf := 0;"
+ " select @have_spider_ping_table_udf := 1 from mysql.func"
+ " where name = 'spider_ping_table';"
+ " if @have_spider_ping_table_udf = 0 then"
+ " if @win_plugin = 0 then "
+ " create function spider_ping_table returns int"
+ " soname 'ha_spider.so';"
+ " else"
+ " create function spider_ping_table returns int"
+ " soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " set @have_spider_copy_tables_udf := 0;"
+ " select @have_spider_copy_tables_udf := 1 from mysql.func"
+ " where name = 'spider_copy_tables';"
+ " if @have_spider_copy_tables_udf = 0 then"
+ " if @win_plugin = 0 then "
+ " create function spider_copy_tables returns int"
+ " soname 'ha_spider.so';"
+ " else"
+ " create function spider_copy_tables returns int"
+ " soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " set @have_spider_flush_table_mon_cache_udf := 0;"
+ " select @have_spider_flush_table_mon_cache_udf := 1 from mysql.func"
+ " where name = 'spider_flush_table_mon_cache';"
+ " if @have_spider_flush_table_mon_cache_udf = 0 then"
+ " if @win_plugin = 0 then "
+ " create function spider_flush_table_mon_cache returns int"
+ " soname 'ha_spider.so';"
+ " else"
+ " create function spider_flush_table_mon_cache returns int"
+ " soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " if @server_name = 'MariaDB' and"
+ " ("
+ " @server_major_version > 10 or"
+ " ("
+ " @server_major_version = 10 and"
+ " @server_minor_version >= 6"
+ " )"
+ " )"
+ " then"
+/*
+ Install spider_rewrite plugin
+*/
+ " set @have_spider_i_s_rewrite_plugin := 0;"
+ " select @have_spider_i_s_rewrite_plugin := 1"
+ " from INFORMATION_SCHEMA.plugins"
+ " where PLUGIN_NAME = 'SPIDER_REWRITE';"
+ " set @have_spider_rewrite_plugin := 0;"
+ " select @have_spider_rewrite_plugin := 1 from mysql.plugin"
+ " where name = 'spider_rewrite';"
+ " if @have_spider_i_s_rewrite_plugin = 0 then"
+ " if @have_spider_rewrite_plugin = 1 then"
+ " /*"
+ " spider_rewrite plugin is present in mysql.plugin but not in"
+ " information_schema.plugins. Remove spider_rewrite plugin entry"
+ " in mysql.plugin first."
+ " */"
+ " delete from mysql.plugin where name = 'spider_rewrite';"
+ " end if;"
+ " if @win_plugin = 0 then "
+ " install plugin spider_rewrite soname 'ha_spider.so';"
+ " else"
+ " install plugin spider_rewrite soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " set @have_spider_flush_rewrite_cache_udf := 0;"
+ " select @have_spider_flush_rewrite_cache_udf := 1 from mysql.func"
+ " where name = 'spider_flush_rewrite_cache';"
+ " if @have_spider_flush_rewrite_cache_udf = 0 then"
+ " if @win_plugin = 0 then "
+ " create function spider_flush_rewrite_cache returns int"
+ " soname 'ha_spider.so';"
+ " else"
+ " create function spider_flush_rewrite_cache returns int"
+ " soname 'ha_spider.dll';"
+ " end if;"
+ " end if;"
+ " end if;"
+ "end;"
+ )},
+ {C_STRING_WITH_LEN(
+ "call mysql.spider_plugin_installer"
+ )},
+ {C_STRING_WITH_LEN(
+ "drop procedure mysql.spider_plugin_installer"
+ )},
+ {C_STRING_WITH_LEN("")}
+};
diff --git a/storage/spider/spd_malloc.cc b/storage/spider/spd_malloc.cc
index 2b5a5002c23..40b37ff4377 100644
--- a/storage/spider/spd_malloc.cc
+++ b/storage/spider/spd_malloc.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2012-2017 Kentoku Shiba
+/* Copyright (C) 2012-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -1126,6 +1127,7 @@ void spider_string::q_append(
) {
DBUG_ENTER("spider_string::q_append");
DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_ASSERT(str.alloced_length() >= str.length() + data_len);
str.q_append(data, data_len);
DBUG_VOID_RETURN;
}
@@ -1238,6 +1240,21 @@ void spider_string::append_escape_string(
DBUG_VOID_RETURN;
}
+void spider_string::append_escape_string(
+ const char *st,
+ uint len,
+ CHARSET_INFO *cs
+) {
+ DBUG_ENTER("spider_string::append_escape_string");
+ DBUG_PRINT("info",("spider this=%p", this));
+ DBUG_ASSERT(mem_calc_inited);
+ DBUG_ASSERT((!current_alloc_mem && !str.is_alloced()) ||
+ current_alloc_mem == str.alloced_length());
+ str.length(str.length() + escape_string_for_mysql(
+ cs, (char *) str.ptr() + str.length(), 0, st, len));
+ DBUG_VOID_RETURN;
+}
+
bool spider_string::append_for_single_quote(
const char *st,
uint len
diff --git a/storage/spider/spd_malloc.h b/storage/spider/spd_malloc.h
index abbeb58d71c..9e97e039e04 100644
--- a/storage/spider/spd_malloc.h
+++ b/storage/spider/spd_malloc.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2012-2014 Kentoku Shiba
+/* Copyright (C) 2012-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -19,7 +20,7 @@
#define spider_bulk_malloc(A,B,C,...) \
spider_bulk_alloc_mem(A,B,__func__,__FILE__,__LINE__,C,__VA_ARGS__)
#define spider_current_trx \
- (current_thd ? ((SPIDER_TRX *) thd_get_ha_data(current_thd, spider_hton_ptr)) : NULL)
+ (current_thd && spider_hton_ptr->slot != HA_SLOT_UNDEF ? ((SPIDER_TRX *) thd_get_ha_data(current_thd, spider_hton_ptr)) : NULL)
#define init_calc_mem(A) init_mem_calc(A,__func__,__FILE__,__LINE__)
diff --git a/storage/spider/spd_param.cc b/storage/spider/spd_param.cc
index 61fd4339ca5..446ccc22141 100644
--- a/storage/spider/spd_param.cc
+++ b/storage/spider/spd_param.cc
@@ -3355,6 +3355,76 @@ int spider_param_slave_trx_isolation()
DBUG_RETURN(spider_slave_trx_isolation);
}
+/*
+ -1 :not set
+ 0-:seconds of timeout
+ */
+static MYSQL_THDVAR_INT(
+ remote_wait_timeout, /* name */
+ PLUGIN_VAR_RQCMDARG, /* opt */
+ "Wait timeout on remote server", /* comment */
+ NULL, /* check */
+ NULL, /* update */
+ -1, /* def */
+ -1, /* min */
+ 2147483647, /* max */
+ 0 /* blk */
+);
+
+int spider_param_remote_wait_timeout(
+ THD *thd
+) {
+ DBUG_ENTER("spider_param_remote_wait_timeout");
+ if (likely(thd))
+ DBUG_RETURN(THDVAR(thd, remote_wait_timeout));
+ DBUG_RETURN(-1);
+}
+
+/*
+ -1 :not set
+ 0-:seconds of timeout
+ */
+static MYSQL_THDVAR_INT(
+ wait_timeout, /* name */
+ PLUGIN_VAR_RQCMDARG, /* opt */
+ "Wait timeout of setting to remote server", /* comment */
+ NULL, /* check */
+ NULL, /* update */
+ 604800, /* def */
+ -1, /* min */
+ 2147483647, /* max */
+ 0 /* blk */
+);
+
+int spider_param_wait_timeout(
+ THD *thd
+) {
+ DBUG_ENTER("spider_param_wait_timeout");
+ if (likely(thd))
+ DBUG_RETURN(THDVAR(thd, wait_timeout));
+ DBUG_RETURN(604800);
+}
+
+/*
+ FALSE: no sync
+ TRUE: sync
+ */
+static MYSQL_THDVAR_BOOL(
+ sync_sql_mode, /* name */
+ PLUGIN_VAR_OPCMDARG, /* opt */
+ "Sync sql_mode", /* comment */
+ NULL, /* check */
+ NULL, /* update */
+ TRUE /* def */
+);
+
+bool spider_param_sync_sql_mode(
+ THD *thd
+) {
+ DBUG_ENTER("spider_param_sync_sql_mode");
+ DBUG_RETURN(THDVAR(thd, sync_sql_mode));
+}
+
static struct st_mysql_storage_engine spider_storage_engine =
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
@@ -3505,6 +3575,9 @@ static struct st_mysql_sys_var* spider_system_variables[] = {
MYSQL_SYSVAR(table_crd_thread_count),
#endif
MYSQL_SYSVAR(slave_trx_isolation),
+ MYSQL_SYSVAR(remote_wait_timeout),
+ MYSQL_SYSVAR(wait_timeout),
+ MYSQL_SYSVAR(sync_sql_mode),
NULL
};
diff --git a/storage/spider/spd_param.h b/storage/spider/spd_param.h
index 4318515dd72..9ffb9e8c278 100644
--- a/storage/spider/spd_param.h
+++ b/storage/spider/spd_param.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -421,3 +422,12 @@ uint spider_param_table_sts_thread_count();
uint spider_param_table_crd_thread_count();
#endif
int spider_param_slave_trx_isolation();
+int spider_param_remote_wait_timeout(
+ THD *thd
+);
+int spider_param_wait_timeout(
+ THD *thd
+);
+bool spider_param_sync_sql_mode(
+ THD *thd
+);
diff --git a/storage/spider/spd_sys_table.cc b/storage/spider/spd_sys_table.cc
index 9c97050d41c..ada48c4982d 100644
--- a/storage/spider/spd_sys_table.cc
+++ b/storage/spider/spd_sys_table.cc
@@ -229,85 +229,264 @@ TABLE *spider_open_sys_table(
}
}
#endif
- if (table_name_length == SPIDER_SYS_XA_TABLE_NAME_LEN)
+ switch (table_name_length)
{
- if (
- !memcmp(table_name,
- SPIDER_SYS_XA_TABLE_NAME_STR, SPIDER_SYS_XA_TABLE_NAME_LEN) &&
- table->s->fields != SPIDER_SYS_XA_COL_CNT
- ) {
- spider_close_sys_table(thd, table, open_tables_backup, need_lock);
- table = NULL;
- my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
- ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
- SPIDER_SYS_XA_TABLE_NAME_STR);
- *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
- goto error_col_num_chk;
- }
- } else if (table_name_length == SPIDER_SYS_XA_MEMBER_TABLE_NAME_LEN)
- {
- if (
- !memcmp(table_name,
- SPIDER_SYS_XA_MEMBER_TABLE_NAME_STR,
- SPIDER_SYS_XA_MEMBER_TABLE_NAME_LEN) &&
- table->s->fields != SPIDER_SYS_XA_MEMBER_COL_CNT
- ) {
- spider_close_sys_table(thd, table, open_tables_backup, need_lock);
- table = NULL;
- my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
- ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
- SPIDER_SYS_XA_MEMBER_TABLE_NAME_STR);
- *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
- goto error_col_num_chk;
- }
- } else if (table_name_length == SPIDER_SYS_TABLES_TABLE_NAME_LEN)
- {
- if (
- !memcmp(table_name,
- SPIDER_SYS_TABLES_TABLE_NAME_STR,
- SPIDER_SYS_TABLES_TABLE_NAME_LEN) &&
- table->s->fields != SPIDER_SYS_TABLES_COL_CNT
- ) {
- spider_close_sys_table(thd, table, open_tables_backup, need_lock);
- table = NULL;
- my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
- ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
- SPIDER_SYS_TABLES_TABLE_NAME_STR);
- *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
- goto error_col_num_chk;
- }
- } else if (table_name_length == SPIDER_SYS_LINK_MON_TABLE_NAME_LEN)
- {
- if (
- !memcmp(table_name,
- SPIDER_SYS_LINK_MON_TABLE_NAME_STR,
- SPIDER_SYS_LINK_MON_TABLE_NAME_LEN) &&
- table->s->fields != SPIDER_SYS_LINK_MON_TABLE_COL_CNT
- ) {
- spider_close_sys_table(thd, table, open_tables_backup, need_lock);
- table = NULL;
- my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
- ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
- SPIDER_SYS_LINK_MON_TABLE_NAME_STR);
- *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
- goto error_col_num_chk;
- }
- } else if (table_name_length == SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_LEN)
- {
- if (
- !memcmp(table_name,
- SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR,
- SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_LEN) &&
- table->s->fields != SPIDER_SYS_POS_FOR_RECOVERY_TABLE_COL_CNT
- ) {
- spider_close_sys_table(thd, table, open_tables_backup, need_lock);
- table = NULL;
- my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
- ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
- SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR);
- *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
- goto error_col_num_chk;
- }
+ case 9:
+ if (!memcmp(table_name, SPIDER_SYS_XA_TABLE_NAME_STR,
+ SPIDER_SYS_XA_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_XA"));
+ if (table->s->fields != SPIDER_SYS_XA_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_XA_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 13:
+ if (!memcmp(table_name, SPIDER_SYS_TABLES_TABLE_NAME_STR,
+ SPIDER_SYS_TABLES_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_TABLES"));
+ if (table->s->fields != SPIDER_SYS_TABLES_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_TABLES_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 16:
+ if (!memcmp(table_name, SPIDER_SYS_XA_MEMBER_TABLE_NAME_STR,
+ SPIDER_SYS_XA_MEMBER_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_XA_MEMBER"));
+ if (table->s->fields != SPIDER_SYS_XA_MEMBER_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_XA_MEMBER_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ if (!memcmp(table_name, SPIDER_SYS_TABLE_STS_TABLE_NAME_STR,
+ SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_TABLE_STS"));
+ if (table->s->fields != SPIDER_SYS_TABLE_STS_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_TABLE_STS_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ if (!memcmp(table_name, SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR,
+ SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_TABLE_CRD"));
+ if (table->s->fields != SPIDER_SYS_TABLE_CRD_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 20:
+ if (!memcmp(table_name, SPIDER_SYS_XA_FAILED_TABLE_NAME_STR,
+ SPIDER_SYS_XA_FAILED_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_XA_FAILED"));
+ if (table->s->fields != SPIDER_SYS_XA_FAILED_TABLE_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_XA_FAILED_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 21:
+ if (!memcmp(table_name, SPIDER_SYS_RW_TBLS_TABLE_NAME_STR,
+ SPIDER_SYS_RW_TBLS_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_RW_TBLS"));
+ if (table->s->fields != SPIDER_SYS_RW_TBLS_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_RW_TBLS_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 22:
+ if (!memcmp(table_name, SPIDER_SYS_LINK_FAILED_TABLE_NAME_STR,
+ SPIDER_SYS_LINK_FAILED_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_LINK_FAILED"));
+ if (table->s->fields != SPIDER_SYS_LINK_FAILED_TABLE_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_LINK_FAILED_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 23:
+ if (!memcmp(table_name, SPIDER_SYS_LINK_MON_TABLE_NAME_STR,
+ SPIDER_SYS_LINK_MON_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_LINK_MON"));
+ if (table->s->fields != SPIDER_SYS_LINK_MON_TABLE_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_LINK_MON_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ if (!memcmp(table_name, SPIDER_SYS_RWN_TBLS_TABLE_NAME_STR,
+ SPIDER_SYS_RWN_TBLS_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_RWN_TBLS"));
+ if (table->s->fields != SPIDER_SYS_RWN_TBLS_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_RWN_TBLS_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 27:
+ if (!memcmp(table_name, SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_STR,
+ SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_RW_TBL_TBLS"));
+ if (table->s->fields != SPIDER_SYS_RW_TBL_TBLS_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 31:
+ if (!memcmp(table_name, SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_STR,
+ SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_RW_TBL_PTTS"));
+ if (table->s->fields != SPIDER_SYS_RW_TBL_PTTS_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ case 34:
+ if (!memcmp(table_name, SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR,
+ SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_POS_FOR_RECOVERY"));
+ if (table->s->fields != SPIDER_SYS_POS_FOR_RECOVERY_TABLE_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ if (!memcmp(table_name, SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_STR,
+ SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_LEN))
+ {
+ DBUG_PRINT("info",("spider checking for SYS_RW_TBL_SPTTS"));
+ if (table->s->fields != SPIDER_SYS_RW_TBL_SPTTS_COL_CNT)
+ {
+ spider_close_sys_table(thd, table, open_tables_backup, need_lock);
+ table = NULL;
+ my_printf_error(ER_SPIDER_SYS_TABLE_VERSION_NUM,
+ ER_SPIDER_SYS_TABLE_VERSION_STR, MYF(0),
+ SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_STR);
+ *error_num = ER_SPIDER_SYS_TABLE_VERSION_NUM;
+ goto error_col_num_chk;
+ }
+ break;
+ }
+ DBUG_ASSERT(0);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ break;
}
DBUG_RETURN(table);
@@ -1240,28 +1419,29 @@ void spider_store_binlog_pos_gtid(
void spider_store_table_sts_info(
TABLE *table,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time
+ ha_statistics *stat
) {
MYSQL_TIME mysql_time;
DBUG_ENTER("spider_store_table_sts_info");
- table->field[2]->store((longlong) *data_file_length, TRUE);
- table->field[3]->store((longlong) *max_data_file_length, TRUE);
- table->field[4]->store((longlong) *index_file_length, TRUE);
- table->field[5]->store((longlong) *records, TRUE);
- table->field[6]->store((longlong) *mean_rec_length, TRUE);
- spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) *check_time);
+ table->field[2]->store((longlong) stat->data_file_length, TRUE);
+ table->field[3]->store((longlong) stat->max_data_file_length, TRUE);
+ table->field[4]->store((longlong) stat->index_file_length, TRUE);
+ table->field[5]->store((longlong) stat->records, TRUE);
+ table->field[6]->store((longlong) stat->mean_rec_length, TRUE);
+ spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->check_time);
table->field[7]->store_time(&mysql_time);
- spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) *create_time);
+ spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->create_time);
table->field[8]->store_time(&mysql_time);
- spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) *update_time);
+ spd_tz_system->gmt_sec_to_TIME(&mysql_time, (my_time_t) stat->update_time);
table->field[9]->store_time(&mysql_time);
+ if (stat->checksum_null)
+ {
+ table->field[10]->set_null();
+ table->field[10]->reset();
+ } else {
+ table->field[10]->set_notnull();
+ table->field[10]->store((longlong) stat->checksum, TRUE);
+ }
DBUG_VOID_RETURN;
}
@@ -1386,14 +1566,7 @@ int spider_insert_or_update_table_sts(
TABLE *table,
const char *name,
uint name_length,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time
+ ha_statistics *stat
) {
int error_num;
char table_key[MAX_KEY_LENGTH];
@@ -1402,14 +1575,7 @@ int spider_insert_or_update_table_sts(
spider_store_tables_name(table, name, name_length);
spider_store_table_sts_info(
table,
- data_file_length,
- max_data_file_length,
- index_file_length,
- records,
- mean_rec_length,
- check_time,
- create_time,
- update_time
+ stat
);
if ((error_num = spider_check_sys_table_for_update_all_columns(table, table_key)))
@@ -2427,6 +2593,7 @@ int spider_get_sys_tables_static_link_id(
) {
int error_num = 0;
DBUG_ENTER("spider_get_sys_tables_static_link_id");
+ *static_link_id = NULL;
if (
!table->field[24]->is_null() &&
(*static_link_id = get_field(mem_root, table->field[24]))
@@ -2441,14 +2608,7 @@ int spider_get_sys_tables_static_link_id(
void spider_get_sys_table_sts_info(
TABLE *table,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time
+ ha_statistics *stat
) {
MYSQL_TIME mysql_time;
#ifdef MARIADB_BASE_VERSION
@@ -2458,35 +2618,43 @@ void spider_get_sys_table_sts_info(
#endif
long not_used_long;
DBUG_ENTER("spider_get_sys_table_sts_info");
- *data_file_length = (ulonglong) table->field[2]->val_int();
- *max_data_file_length = (ulonglong) table->field[3]->val_int();
- *index_file_length = (ulonglong) table->field[4]->val_int();
- *records = (ha_rows) table->field[5]->val_int();
- *mean_rec_length = (ulong) table->field[6]->val_int();
+ stat->data_file_length = (ulonglong) table->field[2]->val_int();
+ stat->max_data_file_length = (ulonglong) table->field[3]->val_int();
+ stat->index_file_length = (ulonglong) table->field[4]->val_int();
+ stat->records = (ha_rows) table->field[5]->val_int();
+ stat->mean_rec_length = (ulong) table->field[6]->val_int();
table->field[7]->get_date(&mysql_time, SPIDER_date_mode_t(0));
#ifdef MARIADB_BASE_VERSION
- *check_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat->check_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- *check_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat->check_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
table->field[8]->get_date(&mysql_time, SPIDER_date_mode_t(0));
#ifdef MARIADB_BASE_VERSION
- *create_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat->create_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- *create_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat->create_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
table->field[9]->get_date(&mysql_time, SPIDER_date_mode_t(0));
#ifdef MARIADB_BASE_VERSION
- *update_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat->update_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_uint);
#else
- *update_time = (time_t) my_system_gmt_sec(&mysql_time,
+ stat->update_time = (time_t) my_system_gmt_sec(&mysql_time,
&not_used_long, &not_used_my_bool);
#endif
+ if (table->field[10]->is_null())
+ {
+ stat->checksum_null = TRUE;
+ stat->checksum = 0;
+ } else {
+ stat->checksum_null = FALSE;
+ stat->checksum = (ha_checksum) table->field[10]->val_int();
+ }
DBUG_VOID_RETURN;
}
@@ -2907,14 +3075,7 @@ int spider_sys_insert_or_update_table_sts(
THD *thd,
const char *name,
uint name_length,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time,
+ ha_statistics *stat,
bool need_lock
) {
int error_num;
@@ -2937,14 +3098,7 @@ int spider_sys_insert_or_update_table_sts(
table_sts,
name,
name_length,
- data_file_length,
- max_data_file_length,
- index_file_length,
- records,
- mean_rec_length,
- check_time,
- create_time,
- update_time
+ stat
)))
goto error;
spider_close_sys_table(thd, table_sts, &open_tables_backup, need_lock);
@@ -3079,14 +3233,7 @@ int spider_sys_get_table_sts(
THD *thd,
const char *name,
uint name_length,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time,
+ ha_statistics *stat,
bool need_lock
) {
int error_num;
@@ -3119,14 +3266,7 @@ int spider_sys_get_table_sts(
} else {
spider_get_sys_table_sts_info(
table_sts,
- data_file_length,
- max_data_file_length,
- index_file_length,
- records,
- mean_rec_length,
- check_time,
- create_time,
- update_time
+ stat
);
}
diff --git a/storage/spider/spd_sys_table.h b/storage/spider/spd_sys_table.h
index 9e2d54c3e28..df933ec61b8 100644
--- a/storage/spider/spd_sys_table.h
+++ b/storage/spider/spd_sys_table.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -14,23 +15,33 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#define SPIDER_SYS_XA_TABLE_NAME_STR "spider_xa"
-#define SPIDER_SYS_XA_TABLE_NAME_LEN (sizeof(SPIDER_SYS_XA_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_XA_TABLE_NAME_LEN 9
#define SPIDER_SYS_XA_MEMBER_TABLE_NAME_STR "spider_xa_member"
-#define SPIDER_SYS_XA_MEMBER_TABLE_NAME_LEN (sizeof(SPIDER_SYS_XA_MEMBER_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_XA_MEMBER_TABLE_NAME_LEN 16
#define SPIDER_SYS_TABLES_TABLE_NAME_STR "spider_tables"
-#define SPIDER_SYS_TABLES_TABLE_NAME_LEN (sizeof(SPIDER_SYS_TABLES_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_TABLES_TABLE_NAME_LEN 13
#define SPIDER_SYS_LINK_MON_TABLE_NAME_STR "spider_link_mon_servers"
-#define SPIDER_SYS_LINK_MON_TABLE_NAME_LEN (sizeof(SPIDER_SYS_LINK_MON_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_LINK_MON_TABLE_NAME_LEN 23
#define SPIDER_SYS_LINK_FAILED_TABLE_NAME_STR "spider_link_failed_log"
-#define SPIDER_SYS_LINK_FAILED_TABLE_NAME_LEN (sizeof(SPIDER_SYS_LINK_FAILED_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_LINK_FAILED_TABLE_NAME_LEN 22
#define SPIDER_SYS_XA_FAILED_TABLE_NAME_STR "spider_xa_failed_log"
-#define SPIDER_SYS_XA_FAILED_TABLE_NAME_LEN (sizeof(SPIDER_SYS_XA_FAILED_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_XA_FAILED_TABLE_NAME_LEN 20
#define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR "spider_table_position_for_recovery"
-#define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_LEN (sizeof(SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_NAME_LEN 34
#define SPIDER_SYS_TABLE_STS_TABLE_NAME_STR "spider_table_sts"
-#define SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN (sizeof(SPIDER_SYS_TABLE_STS_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_TABLE_STS_TABLE_NAME_LEN 16
#define SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR "spider_table_crd"
-#define SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN (sizeof(SPIDER_SYS_TABLE_CRD_TABLE_NAME_STR) - 1)
+#define SPIDER_SYS_TABLE_CRD_TABLE_NAME_LEN 16
+#define SPIDER_SYS_RW_TBLS_TABLE_NAME_STR "spider_rewrite_tables"
+#define SPIDER_SYS_RW_TBLS_TABLE_NAME_LEN 21
+#define SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_STR "spider_rewrite_table_tables"
+#define SPIDER_SYS_RW_TBL_TBLS_TABLE_NAME_LEN 27
+#define SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_STR "spider_rewrite_table_partitions"
+#define SPIDER_SYS_RW_TBL_PTTS_TABLE_NAME_LEN 31
+#define SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_STR "spider_rewrite_table_subpartitions"
+#define SPIDER_SYS_RW_TBL_SPTTS_TABLE_NAME_LEN 34
+#define SPIDER_SYS_RWN_TBLS_TABLE_NAME_STR "spider_rewritten_tables"
+#define SPIDER_SYS_RWN_TBLS_TABLE_NAME_LEN 23
#define SPIDER_SYS_XA_PREPARED_STR "PREPARED"
#define SPIDER_SYS_XA_NOT_YET_STR "NOT YET"
@@ -47,11 +58,18 @@
#define SPIDER_SYS_TABLES_IDX1_COL_CNT 1
#define SPIDER_SYS_TABLES_UIDX1_COL_CNT 3
#define SPIDER_SYS_LINK_MON_TABLE_COL_CNT 19
+#define SPIDER_SYS_LINK_FAILED_TABLE_COL_CNT 4
+#define SPIDER_SYS_XA_FAILED_TABLE_COL_CNT 21
#define SPIDER_SYS_POS_FOR_RECOVERY_TABLE_COL_CNT 7
-#define SPIDER_SYS_TABLE_STS_COL_CNT 10
+#define SPIDER_SYS_TABLE_STS_COL_CNT 11
#define SPIDER_SYS_TABLE_STS_PK_COL_CNT 2
#define SPIDER_SYS_TABLE_CRD_COL_CNT 4
#define SPIDER_SYS_TABLE_CRD_PK_COL_CNT 3
+#define SPIDER_SYS_RW_TBLS_COL_CNT 3
+#define SPIDER_SYS_RW_TBL_TBLS_COL_CNT 8
+#define SPIDER_SYS_RW_TBL_PTTS_COL_CNT 7
+#define SPIDER_SYS_RW_TBL_SPTTS_COL_CNT 8
+#define SPIDER_SYS_RWN_TBLS_COL_CNT 4
#define SPIDER_SYS_LINK_MON_TABLE_DB_NAME_SIZE 64
#define SPIDER_SYS_LINK_MON_TABLE_TABLE_NAME_SIZE 64
@@ -289,14 +307,7 @@ void spider_store_binlog_pos_gtid(
void spider_store_table_sts_info(
TABLE *table,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time
+ ha_statistics *stat
);
void spider_store_table_crd_info(
@@ -330,14 +341,7 @@ int spider_insert_or_update_table_sts(
TABLE *table,
const char *name,
uint name_length,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time
+ ha_statistics *stat
);
int spider_insert_or_update_table_crd(
@@ -493,14 +497,7 @@ int spider_get_sys_tables_static_link_id(
void spider_get_sys_table_sts_info(
TABLE *table,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time
+ ha_statistics *stat
);
void spider_get_sys_table_crd_info(
@@ -564,14 +561,7 @@ int spider_sys_insert_or_update_table_sts(
THD *thd,
const char *name,
uint name_length,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time,
+ ha_statistics *stat,
bool need_lock
);
@@ -602,14 +592,7 @@ int spider_sys_get_table_sts(
THD *thd,
const char *name,
uint name_length,
- ulonglong *data_file_length,
- ulonglong *max_data_file_length,
- ulonglong *index_file_length,
- ha_rows *records,
- ulong *mean_rec_length,
- time_t *check_time,
- time_t *create_time,
- time_t *update_time,
+ ha_statistics *stat,
bool need_lock
);
diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc
index 83c5a37555f..ec7549a38c7 100644
--- a/storage/spider/spd_table.cc
+++ b/storage/spider/spd_table.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -29,6 +30,7 @@
#include "sql_servers.h"
#include "sql_select.h"
#include "tztime.h"
+#include "sql_parse.h"
#endif
#include "spd_err.h"
#include "spd_param.h"
@@ -44,6 +46,7 @@
#include "spd_direct_sql.h"
#include "spd_malloc.h"
#include "spd_group_by_handler.h"
+#include "spd_init_query.h"
/* Background thread management */
#ifdef SPIDER_HAS_NEXT_THREAD_ID
@@ -122,8 +125,13 @@ HASH *spd_db_att_xid_cache;
struct charset_info_st *spd_charset_utf8_bin;
const char **spd_defaults_extra_file;
const char **spd_defaults_file;
+const char **spd_mysqld_unix_port;
+uint *spd_mysqld_port;
bool volatile *spd_abort_loop;
Time_zone *spd_tz_system;
+static int *spd_mysqld_server_started;
+static pthread_mutex_t *spd_LOCK_server_started;
+static pthread_cond_t *spd_COND_server_started;
extern long spider_conn_mutex_id;
handlerton *spider_hton_ptr;
SPIDER_DBTON spider_dbton[SPIDER_DBTON_SIZE];
@@ -4378,6 +4386,9 @@ SPIDER_SHARE *spider_create_share(
uchar *tmp_cardinality_upd, *tmp_table_mon_mutex_bitmap;
char buf[MAX_FIELD_WIDTH], *buf_pos;
char link_idx_str[SPIDER_SQL_INT_LEN];
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ bool checksum_support = TRUE;
+#endif
DBUG_ENTER("spider_create_share");
length = (uint) strlen(table_name);
bitmap_size = spider_bitmap_size(table_share->fields);
@@ -4536,8 +4547,24 @@ SPIDER_SHARE *spider_create_share(
{
goto error_init_dbton;
}
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ if (
+ spider_dbton[roop_count].db_access_type == SPIDER_DB_ACCESS_TYPE_SQL &&
+ !share->dbton_share[roop_count]->checksum_support()
+ ) {
+ checksum_support = FALSE;
+ }
+#endif
}
}
+#ifdef HA_HAS_CHECKSUM_EXTENDED
+ if (checksum_support)
+ {
+ share->additional_table_flags |=
+ HA_HAS_OLD_CHECKSUM |
+ HA_HAS_NEW_CHECKSUM;
+ }
+#endif
DBUG_RETURN(share);
/*
@@ -5003,8 +5030,7 @@ SPIDER_SHARE *spider_get_share(
share->init_error = TRUE;
share->init_error_time = (time_t) time((time_t*) 0);
share->init = TRUE;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_conn_keys;
}
if (
@@ -5051,8 +5077,7 @@ SPIDER_SHARE *spider_get_share(
share->init_error = TRUE;
share->init_error_time = (time_t) time((time_t*) 0);
share->init = TRUE;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
spider->conns[roop_count]->error_mode &= spider->error_mode;
}
@@ -5070,8 +5095,7 @@ SPIDER_SHARE *spider_get_share(
share->init_error = TRUE;
share->init_error_time = (time_t) time((time_t*) 0);
share->init = TRUE;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
char *table_name = db + table_share->db.length + 1;
memcpy(db, table_share->db.str, table_share->db.length);
@@ -5086,16 +5110,14 @@ SPIDER_SHARE *spider_get_share(
share->init_error = TRUE;
share->init_error_time = (time_t) time((time_t*) 0);
share->init = TRUE;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
} else if (search_link_idx == -2)
{
*error_num = HA_ERR_OUT_OF_MEM;
share->init_error = TRUE;
share->init_error_time = (time_t) time((time_t*) 0);
share->init = TRUE;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
spider->search_link_idx = search_link_idx;
@@ -5152,8 +5174,7 @@ SPIDER_SHARE *spider_get_share(
share->init = TRUE;
pthread_mutex_unlock(&share->crd_mutex);
pthread_mutex_unlock(&share->sts_mutex);
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
}
@@ -5162,28 +5183,48 @@ SPIDER_SHARE *spider_get_share(
!same_server_link ||
load_sts_at_startup
) &&
- spider_get_sts(share, spider->search_link_idx, tmp_time,
+ (*error_num = spider_get_sts(share, spider->search_link_idx, tmp_time,
spider, sts_interval, sts_mode,
#ifdef WITH_PARTITION_STORAGE_ENGINE
sts_sync,
#endif
- 1, HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO)
+ 1, HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO))
) {
- thd->clear_error();
+ if (*error_num != ER_SPIDER_SYS_TABLE_VERSION_NUM)
+ {
+ thd->clear_error();
+ } else {
+ pthread_mutex_unlock(&share->crd_mutex);
+ pthread_mutex_unlock(&share->sts_mutex);
+ share->init_error = TRUE;
+ share->init_error_time = (time_t) time((time_t*) 0);
+ share->init = TRUE;
+ goto error_after_alloc_dbton_handler;
+ }
}
if (
(
!same_server_link ||
load_crd_at_startup
) &&
- spider_get_crd(share, spider->search_link_idx, tmp_time,
+ (*error_num = spider_get_crd(share, spider->search_link_idx, tmp_time,
spider, table, crd_interval, crd_mode,
#ifdef WITH_PARTITION_STORAGE_ENGINE
crd_sync,
#endif
- 1)
+ 1))
) {
- thd->clear_error();
+ if (*error_num != ER_SPIDER_SYS_TABLE_VERSION_NUM)
+ {
+ thd->clear_error();
+ } else {
+ pthread_mutex_unlock(&share->crd_mutex);
+ pthread_mutex_unlock(&share->sts_mutex);
+ share->init_error = TRUE;
+ share->init_error_time = (time_t) time((time_t*) 0);
+ share->init = TRUE;
+ goto error_after_alloc_dbton_handler;
+ }
}
pthread_mutex_unlock(&share->crd_mutex);
pthread_mutex_unlock(&share->sts_mutex);
@@ -5520,7 +5561,7 @@ SPIDER_SHARE *spider_get_share(
spider->dbton_handler[dbton_id] = NULL;
}
}
- goto error_but_no_delete;
+ goto error_after_alloc_conn_keys;
}
if (
@@ -5564,8 +5605,7 @@ SPIDER_SHARE *spider_get_share(
FALSE
);
}
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
spider->conns[roop_count]->error_mode &= spider->error_mode;
}
@@ -5580,8 +5620,7 @@ SPIDER_SHARE *spider_get_share(
if (!db)
{
*error_num = HA_ERR_OUT_OF_MEM;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
char *table_name = db + table_share->db.length + 1;
memcpy(db, table_share->db.str, table_share->db.length);
@@ -5593,13 +5632,11 @@ SPIDER_SHARE *spider_get_share(
ER_SPIDER_ALL_LINKS_FAILED_STR, MYF(0), db, table_name);
my_afree(db);
*error_num = ER_SPIDER_ALL_LINKS_FAILED_NUM;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
} else if (search_link_idx == -2)
{
*error_num = HA_ERR_OUT_OF_MEM;
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
spider->search_link_idx = search_link_idx;
@@ -5658,8 +5695,7 @@ SPIDER_SHARE *spider_get_share(
spider_init_error_table->init_error_msg, MYF(0));
pthread_mutex_unlock(&share->crd_mutex);
pthread_mutex_unlock(&share->sts_mutex);
- spider_free_share(share);
- goto error_but_no_delete;
+ goto error_after_alloc_dbton_handler;
}
}
@@ -5668,28 +5704,42 @@ SPIDER_SHARE *spider_get_share(
!same_server_link ||
load_sts_at_startup
) &&
- spider_get_sts(share, spider->search_link_idx,
+ (*error_num = spider_get_sts(share, spider->search_link_idx,
tmp_time, spider, sts_interval, sts_mode,
#ifdef WITH_PARTITION_STORAGE_ENGINE
sts_sync,
#endif
- 1, HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO)
+ 1, HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_AUTO))
) {
- thd->clear_error();
+ if (*error_num != ER_SPIDER_SYS_TABLE_VERSION_NUM)
+ {
+ thd->clear_error();
+ } else {
+ pthread_mutex_unlock(&share->crd_mutex);
+ pthread_mutex_unlock(&share->sts_mutex);
+ goto error_after_alloc_dbton_handler;
+ }
}
if (
(
!same_server_link ||
load_crd_at_startup
) &&
- spider_get_crd(share, spider->search_link_idx,
+ (*error_num = spider_get_crd(share, spider->search_link_idx,
tmp_time, spider, table, crd_interval, crd_mode,
#ifdef WITH_PARTITION_STORAGE_ENGINE
crd_sync,
#endif
- 1)
+ 1))
) {
- thd->clear_error();
+ if (*error_num != ER_SPIDER_SYS_TABLE_VERSION_NUM)
+ {
+ thd->clear_error();
+ } else {
+ pthread_mutex_unlock(&share->crd_mutex);
+ pthread_mutex_unlock(&share->sts_mutex);
+ goto error_after_alloc_dbton_handler;
+ }
}
}
share->init_error = FALSE;
@@ -5702,6 +5752,22 @@ SPIDER_SHARE *spider_get_share(
DBUG_PRINT("info",("spider share=%p", share));
DBUG_RETURN(share);
+error_after_alloc_dbton_handler:
+ for (roop_count = 0; roop_count < (int) share->use_dbton_count; ++roop_count)
+ {
+ uint dbton_id = share->use_dbton_ids[roop_count];
+ if (spider->dbton_handler[dbton_id])
+ {
+ delete spider->dbton_handler[dbton_id];
+ spider->dbton_handler[dbton_id] = NULL;
+ }
+ }
+error_after_alloc_conn_keys:
+ spider_free(spider_current_trx, spider->conn_keys, MYF(0));
+ spider->conn_keys = NULL;
+ spider_free_share(share);
+ goto error_but_no_delete;
+
error_hash_insert:
spider_free_share_resource_only(share);
error_alloc_share:
@@ -5780,14 +5846,7 @@ int spider_free_share(
thd,
share->lgtm_tblhnd_share->table_name,
share->lgtm_tblhnd_share->table_name_length,
- &share->data_file_length,
- &share->max_data_file_length,
- &share->index_file_length,
- &share->records,
- &share->mean_rec_length,
- &share->check_time,
- &share->create_time,
- &share->update_time,
+ &share->stat,
FALSE
);
}
@@ -6163,21 +6222,7 @@ void spider_copy_sts_to_pt_share(
SPIDER_SHARE *share
) {
DBUG_ENTER("spider_copy_sts_to_pt_share");
- memcpy(&partition_share->data_file_length, &share->data_file_length,
- sizeof(ulonglong) * 4 + sizeof(ha_rows) +
- sizeof(ulong) + sizeof(time_t) * 3);
-/*
- partition_share->data_file_length = share->data_file_length;
- partition_share->max_data_file_length = share->max_data_file_length;
- partition_share->index_file_length = share->index_file_length;
- partition_share->auto_increment_value =
- share->lgtm_tblhnd_share->auto_increment_value;
- partition_share->records = share->records;
- partition_share->mean_rec_length = share->mean_rec_length;
- partition_share->check_time = share->check_time;
- partition_share->create_time = share->create_time;
- partition_share->update_time = share->update_time;
-*/
+ partition_share->stat = share->stat;
DBUG_VOID_RETURN;
}
@@ -6186,23 +6231,7 @@ void spider_copy_sts_to_share(
SPIDER_PARTITION_SHARE *partition_share
) {
DBUG_ENTER("spider_copy_sts_to_share");
- memcpy(&share->data_file_length, &partition_share->data_file_length,
- sizeof(ulonglong) * 4 + sizeof(ha_rows) +
- sizeof(ulong) + sizeof(time_t) * 3);
-/*
- share->data_file_length = partition_share->data_file_length;
- share->max_data_file_length = partition_share->max_data_file_length;
- share->index_file_length = partition_share->index_file_length;
- share->lgtm_tblhnd_share->auto_increment_value =
- partition_share->auto_increment_value;
- DBUG_PRINT("info",("spider auto_increment_value=%llu",
- share->lgtm_tblhnd_share->auto_increment_value));
- share->records = partition_share->records;
- share->mean_rec_length = partition_share->mean_rec_length;
- share->check_time = partition_share->check_time;
- share->create_time = partition_share->create_time;
- share->update_time = partition_share->update_time;
-*/
+ share->stat = partition_share->stat;
DBUG_VOID_RETURN;
}
@@ -6541,6 +6570,30 @@ handler* spider_create_handler(
MEM_ROOT *mem_root
) {
DBUG_ENTER("spider_create_handler");
+#ifndef WITHOUT_SPIDER_BG_SEARCH
+ SPIDER_THREAD *thread = &spider_table_sts_threads[0];
+ if (unlikely(thread->init_command))
+ {
+ THD *thd = current_thd;
+ pthread_cond_t *cond = thd->mysys_var->current_cond;
+ pthread_mutex_t *mutex = thd->mysys_var->current_mutex;
+ /* wait for finishing init_command */
+ pthread_mutex_lock(&thread->mutex);
+ if (unlikely(thread->init_command))
+ {
+ thd->mysys_var->current_cond = &thread->sync_cond;
+ thd->mysys_var->current_mutex = &thread->mutex;
+ pthread_cond_wait(&thread->sync_cond, &thread->mutex);
+ }
+ pthread_mutex_unlock(&thread->mutex);
+ thd->mysys_var->current_cond = cond;
+ thd->mysys_var->current_mutex = mutex;
+ if (thd->killed)
+ {
+ DBUG_RETURN(NULL);
+ }
+ }
+#endif
DBUG_RETURN(new (mem_root) ha_spider(hton, table));
}
@@ -6952,6 +7005,10 @@ int spider_db_init(
GetProcAddress(current_module, "my_defaults_extra_file");
spd_defaults_file = (const char **)
GetProcAddress(current_module, "my_defaults_file");
+ spd_mysqld_unix_port = (const char **)
+ GetProcAddress(current_module, "?mysqld_unix_port@@3PADA");
+ spd_mysqld_port = (uint *)
+ GetProcAddress(current_module, "?mysqld_port@@3IA");
spd_abort_loop = (bool volatile *)
GetProcAddress(current_module, "?abort_loop@@3_NC");
spd_tz_system = *(Time_zone **)
@@ -6960,6 +7017,13 @@ int spider_db_init(
#else
GetProcAddress(current_module, "?my_tz_SYSTEM@@3PAVTime_zone@@A");
#endif
+ spd_mysqld_server_started = (int *)
+ GetProcAddress(current_module, "?mysqld_server_started@@3HA");
+ spd_LOCK_server_started = (pthread_mutex_t *)
+ GetProcAddress(current_module,
+ "?LOCK_server_started@@3Ust_mysql_mutex@@A");
+ spd_COND_server_started = (pthread_cond_t *)
+ GetProcAddress(current_module, "?COND_server_started@@3Ust_mysql_cond@@A");
#else
#ifndef SPIDER_HAS_NEXT_THREAD_ID
spd_db_att_thread_id = &thread_id;
@@ -6978,8 +7042,13 @@ int spider_db_init(
spd_charset_utf8_bin = &my_charset_utf8_bin;
spd_defaults_extra_file = &my_defaults_extra_file;
spd_defaults_file = &my_defaults_file;
+ spd_mysqld_unix_port = (const char **) &mysqld_unix_port;
+ spd_mysqld_port = &mysqld_port;
spd_abort_loop = &abort_loop;
spd_tz_system = my_tz_SYSTEM;
+ spd_mysqld_server_started = &mysqld_server_started;
+ spd_LOCK_server_started = &LOCK_server_started;
+ spd_COND_server_started = &COND_server_started;
#endif
#ifdef HAVE_PSI_INTERFACE
@@ -7265,6 +7334,7 @@ int spider_db_init(
NullS))
)
goto error_alloc_mon_mutxes;
+ spider_table_sts_threads[0].init_command = TRUE;
for (roop_count = 0;
roop_count < (int) spider_param_table_sts_thread_count();
@@ -7316,7 +7386,6 @@ int spider_db_init(
}
}
}
-
DBUG_RETURN(0);
#ifndef WITHOUT_SPIDER_BG_SEARCH
@@ -7617,10 +7686,8 @@ int spider_get_sts(
if (
sts_sync == 0
) {
-#endif
/* get */
get_type = 1;
-#ifdef WITH_PARTITION_STORAGE_ENGINE
} else if (
!share->partition_share->sts_init
) {
@@ -7659,14 +7726,7 @@ int spider_get_sts(
current_thd,
share->lgtm_tblhnd_share->table_name,
share->lgtm_tblhnd_share->table_name_length,
- &share->data_file_length,
- &share->max_data_file_length,
- &share->index_file_length,
- &share->records,
- &share->mean_rec_length,
- &share->check_time,
- &share->create_time,
- &share->update_time,
+ &share->stat,
FALSE
);
if (
@@ -7774,10 +7834,8 @@ int spider_get_crd(
if (
crd_sync == 0
) {
-#endif
/* get */
get_type = 1;
-#ifdef WITH_PARTITION_STORAGE_ENGINE
} else if (
!share->partition_share->crd_init
) {
@@ -8397,16 +8455,9 @@ void spider_free_tmp_dbton_handler(
TABLE_LIST *spider_get_parent_table_list(
ha_spider *spider
) {
- TABLE *table = spider->get_table();
- TABLE_LIST *table_list = table->pos_in_table_list;
+ TABLE *table = spider->get_top_table();
DBUG_ENTER("spider_get_parent_table_list");
- if (table_list)
- {
- while (table_list->parent_l)
- table_list = table_list->parent_l;
- DBUG_RETURN(table_list);
- }
- DBUG_RETURN(NULL);
+ DBUG_RETURN(table->pos_in_table_list);
}
List<Index_hint> *spider_get_index_hints(
@@ -8840,6 +8891,13 @@ bool spider_check_direct_order_limit(
break;
}
}
+ if (!spider_all_part_in_order((ORDER *) select_lex->group_list.first,
+ spider->get_table()))
+ {
+ DBUG_PRINT("info",("spider FALSE by group condition"));
+ first_check = FALSE;
+ spider->result_list.direct_distinct = FALSE;
+ }
#endif
}
@@ -8905,6 +8963,98 @@ bool spider_check_direct_order_limit(
DBUG_RETURN(FALSE);
}
+#ifdef HANDLER_HAS_DIRECT_AGGREGATE
+bool spider_all_part_in_order(
+ ORDER *order,
+ TABLE *table
+) {
+ TABLE_LIST *parent;
+ partition_info *part_info;
+ Field **part_fields;
+ ORDER *ptr;
+ Item *item;
+ Item_field *item_field;
+ DBUG_ENTER("spider_all_part_in_order");
+ while (TRUE)
+ {
+ DBUG_PRINT("info", ("spider table_name = %s", table->s->db.str));
+ DBUG_PRINT("info",("spider part_info=%p", table->part_info));
+ if ((part_info = table->part_info))
+ {
+ for (part_fields = part_info->full_part_field_array;
+ *part_fields; ++part_fields)
+ {
+ DBUG_PRINT("info", ("spider part_field = %s",
+ SPIDER_field_name_str(*part_fields)));
+ for (ptr = order; ptr; ptr = ptr->next)
+ {
+ item = *ptr->item;
+ if (item->type() != Item::FIELD_ITEM)
+ {
+ continue;
+ }
+ item_field = (Item_field *) item;
+ Field *field = item_field->field;
+ if (!field)
+ {
+ continue;
+ }
+ DBUG_PRINT("info", ("spider field_name = %s.%s",
+ field->table->s->db.str, SPIDER_field_name_str(field)));
+ if (*part_fields == spider_field_exchange(table->file, field))
+ {
+ break;
+ }
+ }
+ if (!ptr)
+ {
+ DBUG_RETURN(FALSE);
+ }
+ }
+ }
+ if (!(parent = table->pos_in_table_list->parent_l))
+ {
+ break;
+ }
+ table = parent->table;
+ }
+ DBUG_RETURN(TRUE);
+}
+
+Field *spider_field_exchange(
+ handler *handler,
+ Field *field
+) {
+ DBUG_ENTER("spider_field_exchange");
+#ifdef HA_CAN_BULK_ACCESS
+ if (handler->is_bulk_access_clone)
+ {
+ handler = handler->pt_clone_source_handler;
+ }
+#endif
+ DBUG_PRINT("info",("spider in field=%p", field));
+ DBUG_PRINT("info",("spider in field->table=%p", field->table));
+#ifdef HANDLER_HAS_TOP_TABLE_FIELDS
+ if (handler->set_top_table_fields)
+ {
+ DBUG_PRINT("info",("spider top_table=%p", handler->top_table));
+ if (field->table != handler->top_table)
+ DBUG_RETURN(NULL);
+ if (!(field = handler->top_table_field[field->field_index]))
+ DBUG_RETURN(NULL);
+ } else {
+#endif
+ DBUG_PRINT("info",("spider table=%p", handler->get_table()));
+ if (field->table != handler->get_table())
+ DBUG_RETURN(NULL);
+#ifdef HANDLER_HAS_TOP_TABLE_FIELDS
+ }
+#endif
+ DBUG_PRINT("info",("spider out field=%p", field));
+ DBUG_RETURN(field);
+}
+#endif
+
int spider_set_direct_limit_offset(
ha_spider *spider
) {
@@ -9199,7 +9349,9 @@ int spider_discover_table_structure(
str.q_append(share->table_name.str, share->table_name.length);
str.q_append(SPIDER_SQL_LCL_NAME_QUOTE_STR, SPIDER_SQL_LCL_NAME_QUOTE_LEN);
str.q_append(SPIDER_SQL_OPEN_PAREN_STR, SPIDER_SQL_OPEN_PAREN_LEN);
+#ifdef WITH_PARTITION_STORAGE_ENGINE
str_len = str.length();
+#endif
#ifdef SPIDER_HAS_HASH_VALUE_TYPE
my_hash_value_type hash_value = my_calc_hash(&spider_open_tables,
(uchar*) table_name, table_name_length);
@@ -9874,6 +10026,53 @@ void *spider_table_bg_sts_action(
trx->thd = thd;
/* init end */
+ if (thread->init_command)
+ {
+ uint i = 0;
+ tmp_disable_binlog(thd);
+ thd->security_ctx->skip_grants();
+ thd->client_capabilities |= CLIENT_MULTI_RESULTS;
+ if (!(*spd_mysqld_server_started) && !thd->killed)
+ {
+ pthread_mutex_lock(spd_LOCK_server_started);
+ thd->mysys_var->current_cond = spd_COND_server_started;
+ thd->mysys_var->current_mutex = spd_LOCK_server_started;
+ if (!(*spd_mysqld_server_started) && !thd->killed)
+ {
+ pthread_cond_wait(spd_COND_server_started, spd_LOCK_server_started);
+ }
+ pthread_mutex_unlock(spd_LOCK_server_started);
+ thd->mysys_var->current_cond = &thread->cond;
+ thd->mysys_var->current_mutex = &thread->mutex;
+ }
+ while (spider_init_queries[i].length && !thd->killed)
+ {
+ dispatch_command(COM_QUERY, thd, spider_init_queries[i].str,
+ (uint) spider_init_queries[i].length, FALSE, FALSE);
+ if (unlikely(thd->is_error()))
+ {
+ fprintf(stderr, "[ERROR] %s\n", spider_stmt_da_message(thd));
+ thd->clear_error();
+ break;
+ }
+ ++i;
+ }
+ thd->mysys_var->current_cond = &thread->cond;
+ thd->mysys_var->current_mutex = &thread->mutex;
+ thd->client_capabilities -= CLIENT_MULTI_RESULTS;
+ reenable_binlog(thd);
+ thread->init_command = FALSE;
+ pthread_cond_broadcast(&thread->sync_cond);
+ }
+ if (thd->killed)
+ {
+ thread->killed = TRUE;
+ }
+ if (thd->killed)
+ {
+ thread->killed = TRUE;
+ }
+
while (TRUE)
{
DBUG_PRINT("info",("spider bg sts loop start"));
diff --git a/storage/spider/spd_table.h b/storage/spider/spd_table.h
index 362ebf263ca..baeec2a9a3b 100644
--- a/storage/spider/spd_table.h
+++ b/storage/spider/spd_table.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2017 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -638,6 +639,18 @@ bool spider_check_direct_order_limit(
ha_spider *spider
);
+#ifdef HANDLER_HAS_DIRECT_AGGREGATE
+bool spider_all_part_in_order(
+ ORDER *order,
+ TABLE *table
+);
+
+Field *spider_field_exchange(
+ handler *handler,
+ Field *field
+);
+#endif
+
int spider_set_direct_limit_offset(
ha_spider* spider
);
diff --git a/storage/spider/spd_trx.cc b/storage/spider/spd_trx.cc
index bb9f11793cb..b47b75a93cf 100644
--- a/storage/spider/spd_trx.cc
+++ b/storage/spider/spd_trx.cc
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2018 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -1667,6 +1668,32 @@ int spider_check_and_set_sql_log_off(
DBUG_RETURN(0);
}
+int spider_check_and_set_wait_timeout(
+ THD *thd,
+ SPIDER_CONN *conn,
+ int *need_mon
+) {
+ int wait_timeout;
+ DBUG_ENTER("spider_check_and_set_wait_timeout");
+
+ wait_timeout = spider_param_wait_timeout(thd);
+ if (wait_timeout > 0)
+ {
+ spider_conn_queue_wait_timeout(conn, wait_timeout);
+ }
+ DBUG_RETURN(0);
+}
+
+int spider_check_and_set_sql_mode(
+ THD *thd,
+ SPIDER_CONN *conn,
+ int *need_mon
+) {
+ DBUG_ENTER("spider_check_and_set_sql_mode");
+ spider_conn_queue_sql_mode(conn, thd->variables.sql_mode);
+ DBUG_RETURN(0);
+}
+
int spider_check_and_set_time_zone(
THD *thd,
SPIDER_CONN *conn,
@@ -1690,8 +1717,9 @@ int spider_check_and_set_time_zone(
DBUG_RETURN(0);
}
-int spider_xa_lock(
- XID_STATE *xid_state
+static int spider_xa_lock(
+ XID_STATE *xid_state,
+ XID *xid
) {
THD *thd = current_thd;
int error_num;
@@ -1709,7 +1737,7 @@ int spider_xa_lock(
#endif
old_proc_info = thd_proc_info(thd, "Locking xid by Spider");
#ifdef SPIDER_XID_USES_xid_cache_iterate
- if (xid_cache_insert(thd, xid_state))
+ if (xid_cache_insert(thd, xid_state, xid))
{
error_num = (spider_stmt_da_sql_errno(thd) == ER_XAER_DUPID ?
ER_SPIDER_XA_LOCKED_NUM : HA_ERR_OUT_OF_MEM);
@@ -1774,7 +1802,7 @@ error:
DBUG_RETURN(error_num);
}
-int spider_xa_unlock(
+static int spider_xa_unlock(
XID_STATE *xid_state
) {
THD *thd = current_thd;
@@ -1866,6 +1894,11 @@ int spider_internal_start_trx(
if (
(error_num = spider_check_and_set_sql_log_off(thd, conn,
&spider->need_mons[link_idx])) ||
+ (error_num = spider_check_and_set_wait_timeout(thd, conn,
+ &spider->need_mons[link_idx])) ||
+ (spider_param_sync_sql_mode(thd) &&
+ (error_num = spider_check_and_set_sql_mode(thd, conn,
+ &spider->need_mons[link_idx]))) ||
(sync_autocommit &&
(error_num = spider_check_and_set_autocommit(thd, conn,
&spider->need_mons[link_idx])))
@@ -1891,7 +1924,7 @@ int spider_internal_start_trx(
if (!trx->trx_start)
{
if (
- thd->transaction.xid_state.xa_state == XA_ACTIVE &&
+ thd->transaction.xid_state.is_explicit_XA() &&
spider_param_support_xa()
) {
trx->trx_xa = TRUE;
@@ -1929,12 +1962,10 @@ int spider_internal_start_trx(
thd->server_id));
#endif
- trx->internal_xid_state.xa_state = XA_ACTIVE;
- trx->internal_xid_state.xid.set(&trx->xid);
#ifdef SPIDER_XID_STATE_HAS_in_thd
trx->internal_xid_state.in_thd = 1;
#endif
- if ((error_num = spider_xa_lock(&trx->internal_xid_state)))
+ if ((error_num = spider_xa_lock(&trx->internal_xid_state, &trx->xid)))
{
if (error_num == ER_SPIDER_XA_LOCKED_NUM)
my_message(error_num, ER_SPIDER_XA_LOCKED_STR, MYF(0));
@@ -2198,7 +2229,6 @@ int spider_internal_xa_commit(
table_xa_opened = FALSE;
}
spider_xa_unlock(&trx->internal_xid_state);
- trx->internal_xid_state.xa_state = XA_NOTR;
DBUG_RETURN(0);
error:
@@ -2209,7 +2239,6 @@ error:
error_in_commit:
error_open_table:
spider_xa_unlock(&trx->internal_xid_state);
- trx->internal_xid_state.xa_state = XA_NOTR;
DBUG_RETURN(error_num);
}
@@ -2436,7 +2465,6 @@ int spider_internal_xa_rollback(
table_xa_opened = FALSE;
}
spider_xa_unlock(&trx->internal_xid_state);
- trx->internal_xid_state.xa_state = XA_NOTR;
DBUG_RETURN(0);
error:
@@ -2447,7 +2475,6 @@ error:
error_in_rollback:
error_open_table:
spider_xa_unlock(&trx->internal_xid_state);
- trx->internal_xid_state.xa_state = XA_NOTR;
DBUG_RETURN(error_num);
}
@@ -2616,8 +2643,6 @@ int spider_internal_xa_prepare(
spider_close_sys_table(thd, table_xa, &open_tables_backup, TRUE);
table_xa_opened = FALSE;
}
- if (internal_xa)
- trx->internal_xid_state.xa_state = XA_PREPARED;
DBUG_RETURN(0);
error:
diff --git a/storage/spider/spd_trx.h b/storage/spider/spd_trx.h
index dec1db4d863..3883ec49723 100644
--- a/storage/spider/spd_trx.h
+++ b/storage/spider/spd_trx.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2008-2014 Kentoku Shiba
+/* Copyright (C) 2008-2019 Kentoku Shiba
+ Copyright (C) 2019 MariaDB corp
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
@@ -99,18 +100,22 @@ int spider_check_and_set_sql_log_off(
int *need_mon
);
-int spider_check_and_set_time_zone(
+int spider_check_and_set_wait_timeout(
THD *thd,
SPIDER_CONN *conn,
int *need_mon
);
-int spider_xa_lock(
- XID_STATE *xid_state
+int spider_check_and_set_sql_mode(
+ THD *thd,
+ SPIDER_CONN *conn,
+ int *need_mon
);
-int spider_xa_unlock(
- XID_STATE *xid_state
+int spider_check_and_set_time_zone(
+ THD *thd,
+ SPIDER_CONN *conn,
+ int *need_mon
);
int spider_start_internal_consistent_snapshot(
diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
index f62bbd2726c..741ca9c64b2 100644
--- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
+++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake
@@ -73,7 +73,6 @@ set_cflags_if_supported(
-Wno-error=tautological-constant-out-of-range-compare
-Wno-error=maybe-uninitialized
-Wno-error=extern-c-compat
- -fno-rtti
-fno-exceptions
-Wno-error=nonnull-compare
)
diff --git a/storage/tokudb/PerconaFT/portability/toku_crash.cc b/storage/tokudb/PerconaFT/portability/toku_crash.cc
index 0af85342a99..297cc29d9ca 100644
--- a/storage/tokudb/PerconaFT/portability/toku_crash.cc
+++ b/storage/tokudb/PerconaFT/portability/toku_crash.cc
@@ -70,7 +70,7 @@ run_gdb(pid_t parent_pid, const char *gdb_path) {
"-ex", "thread apply all bt",
"-ex", "thread apply all bt full",
exe_buf, pid_buf,
- NULL);
+ (char*) NULL);
}
static void
diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc
index 4a101f7e589..67888216849 100644
--- a/storage/tokudb/ha_tokudb.cc
+++ b/storage/tokudb/ha_tokudb.cc
@@ -3715,7 +3715,7 @@ static bool do_unique_checks_fn(THD *thd) {
#endif // defined(TOKU_INCLUDE_RFR) && TOKU_INCLUDE_RFR
-int ha_tokudb::do_uniqueness_checks(uchar* record, DB_TXN* txn, THD* thd) {
+int ha_tokudb::do_uniqueness_checks(const uchar* record, DB_TXN* txn, THD* thd) {
int error = 0;
//
// first do uniqueness checks
@@ -3758,7 +3758,7 @@ cleanup:
return error;
}
-void ha_tokudb::test_row_packing(uchar* record, DBT* pk_key, DBT* pk_val) {
+void ha_tokudb::test_row_packing(const uchar* record, DBT* pk_key, DBT* pk_val) {
int error;
DBT row, key;
//
@@ -3999,7 +3999,7 @@ out:
// 0 on success
// error otherwise
//
-int ha_tokudb::write_row(uchar * record) {
+int ha_tokudb::write_row(const uchar * record) {
TOKUDB_HANDLER_DBUG_ENTER("%p", record);
DBT row, prim_key;
@@ -6937,7 +6937,7 @@ void ha_tokudb::trace_create_table_info(TABLE* form) {
field->flags);
}
for (i = 0; i < form->s->keys; i++) {
- KEY *key = &form->s->key_info[i];
+ KEY *key = &form->key_info[i];
TOKUDB_HANDLER_TRACE(
"key:%d:%s:%d",
i,
@@ -7065,7 +7065,7 @@ int ha_tokudb::create_secondary_dictionary(
sprintf(dict_name, "key-%s", key_info->name.str);
make_name(newname, newname_len, name, dict_name);
- prim_key = (hpk) ? NULL : &form->s->key_info[primary_key];
+ prim_key = (hpk) ? NULL : &form->key_info[primary_key];
//
// setup the row descriptor
@@ -7177,7 +7177,7 @@ int ha_tokudb::create_main_dictionary(
make_name(newname, newname_len, name, "main");
- prim_key = (hpk) ? NULL : &form->s->key_info[primary_key];
+ prim_key = (hpk) ? NULL : &form->key_info[primary_key];
//
// setup the row descriptor
@@ -7442,7 +7442,7 @@ int ha_tokudb::create(
error = write_key_name_to_status(
status_block,
- form->s->key_info[i].name.str,
+ form->key_info[i].name.str,
txn);
if (error) {
goto cleanup;
@@ -7788,13 +7788,18 @@ double ha_tokudb::scan_time() {
DBUG_RETURN(ret_val);
}
+bool ha_tokudb::is_clustering_key(uint index)
+{
+ return index == primary_key || key_is_clustering(&table->key_info[index]);
+}
+
double ha_tokudb::keyread_time(uint index, uint ranges, ha_rows rows)
{
TOKUDB_HANDLER_DBUG_ENTER("%u %u %" PRIu64, index, ranges, (uint64_t) rows);
- double ret_val;
- if (index == primary_key || key_is_clustering(&table->key_info[index])) {
- ret_val = read_time(index, ranges, rows);
- DBUG_RETURN(ret_val);
+ double cost;
+ if (index == primary_key || is_clustering_key(index)) {
+ cost = read_time(index, ranges, rows);
+ DBUG_RETURN(cost);
}
/*
It is assumed that we will read trough the whole key range and that all
@@ -7804,11 +7809,8 @@ double ha_tokudb::keyread_time(uint index, uint ranges, ha_rows rows)
blocks read. This model does not take into account clustered indexes -
engines that support that (e.g. InnoDB) may want to overwrite this method.
*/
- double keys_per_block= (stats.block_size/2.0/
- (table->key_info[index].key_length +
- ref_length) + 1);
- ret_val = (rows + keys_per_block - 1)/ keys_per_block;
- TOKUDB_HANDLER_DBUG_RETURN_DOUBLE(ret_val);
+ cost= handler::keyread_time(index, ranges, rows);
+ TOKUDB_HANDLER_DBUG_RETURN_DOUBLE(cost);
}
//
@@ -8170,7 +8172,7 @@ int ha_tokudb::tokudb_add_index(
for (uint i = 0; i < num_of_keys; i++) {
for (uint j = 0; j < table_arg->s->keys; j++) {
if (strcmp(key_info[i].name.str,
- table_arg->s->key_info[j].name.str) == 0) {
+ table_arg->key_info[j].name.str) == 0) {
error = HA_ERR_WRONG_COMMAND;
goto cleanup;
}
diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h
index 001df43defa..fb1d2cd7a67 100644
--- a/storage/tokudb/ha_tokudb.h
+++ b/storage/tokudb/ha_tokudb.h
@@ -704,11 +704,11 @@ private:
void trace_create_table_info(TABLE* form);
int is_index_unique(bool* is_unique, DB_TXN* txn, DB* db, KEY* key_info, int lock_flags);
int is_val_unique(bool* is_unique, const uchar* record, KEY* key_info, uint dict_index, DB_TXN* txn);
- int do_uniqueness_checks(uchar* record, DB_TXN* txn, THD* thd);
+ int do_uniqueness_checks(const uchar* record, DB_TXN* txn, THD* thd);
void set_main_dict_put_flags(THD* thd, bool opt_eligible, uint32_t* put_flags);
int insert_row_to_main_dictionary(DBT* pk_key, DBT* pk_val, DB_TXN* txn);
int insert_rows_to_dictionaries_mult(DBT* pk_key, DBT* pk_val, DB_TXN* txn, THD* thd);
- void test_row_packing(uchar* record, DBT* pk_key, DBT* pk_val);
+ void test_row_packing(const uchar* record, DBT* pk_key, DBT* pk_val);
uint32_t fill_row_mutator(
uchar* buf,
uint32_t* dropped_columns,
@@ -786,7 +786,7 @@ public:
int rename_table(const char *from, const char *to);
int optimize(THD * thd, HA_CHECK_OPT * check_opt);
int analyze(THD * thd, HA_CHECK_OPT * check_opt);
- int write_row(uchar * buf);
+ int write_row(const uchar * buf);
int update_row(const uchar * old_data, const uchar * new_data);
int delete_row(const uchar * buf);
#if MYSQL_VERSION_ID >= 100000
@@ -872,6 +872,7 @@ public:
bool primary_key_is_clustered() {
return true;
}
+ bool is_clustering_key(uint index);
int cmp_ref(const uchar * ref1, const uchar * ref2);
bool check_if_incompatible_data(HA_CREATE_INFO * info, uint table_changes);
@@ -916,6 +917,9 @@ public:
Item* idx_cond_push(uint keyno, class Item* idx_cond);
void cancel_pushed_idx_cond();
+ bool can_convert_varstring(const Field_varstring* field,
+ const Column_definition&new_type) const;
+
#if defined(TOKU_INCLUDE_ALTER_56) && TOKU_INCLUDE_ALTER_56
public:
enum_alter_inplace_result check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info);
diff --git a/storage/tokudb/ha_tokudb_alter_56.cc b/storage/tokudb/ha_tokudb_alter_56.cc
index 2bcc5dee127..4bdf2cf7bda 100644
--- a/storage/tokudb/ha_tokudb_alter_56.cc
+++ b/storage/tokudb/ha_tokudb_alter_56.cc
@@ -465,10 +465,10 @@ enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(
result = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
}
} else if ((ctx->handler_flags &
- ALTER_COLUMN_EQUAL_PACK_LENGTH) &&
+ ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE) &&
only_flags(
ctx->handler_flags,
- ALTER_COLUMN_EQUAL_PACK_LENGTH |
+ ALTER_COLUMN_TYPE_CHANGE_BY_ENGINE |
ALTER_COLUMN_DEFAULT) &&
table->s->fields == altered_table->s->fields &&
find_changed_fields(
@@ -1180,6 +1180,18 @@ static bool change_varchar_length_is_supported(Field* old_field,
return true;
}
+bool ha_tokudb::can_convert_varstring(const Field_varstring* field,
+ const Column_definition& new_type) const {
+ if (new_type.length < field->field_length ||
+ new_type.char_length < field->char_length() ||
+ !new_type.compression_method() != !field->compression_method() ||
+ new_type.type_handler() != field->type_handler()) {
+ return false;
+ }
+
+ return true;
+}
+
// Return true if all changed field lengths can be changed inplace, otherwise
// return false
static bool change_length_is_supported(TABLE* table,
@@ -1606,7 +1618,7 @@ int ha_tokudb::new_row_descriptor(TABLE* altered_table,
} else {
KEY* prim_key =
hidden_primary_key ? NULL :
- &altered_table->s->key_info[primary_key];
+ &altered_table->key_info[primary_key];
if (idx == primary_key) {
row_descriptor->size = create_main_key_descriptor(
(uchar*)row_descriptor->data,
diff --git a/storage/tokudb/ha_tokudb_update.cc b/storage/tokudb/ha_tokudb_update.cc
index bb59d112680..fec0a42e063 100644
--- a/storage/tokudb/ha_tokudb_update.cc
+++ b/storage/tokudb/ha_tokudb_update.cc
@@ -451,7 +451,7 @@ static bool check_all_update_expressions(
static bool full_field_in_key(TABLE* table, Field* field) {
assert_always(table->s->primary_key < table->s->keys);
- KEY* key = &table->s->key_info[table->s->primary_key];
+ KEY* key = &table->key_info[table->s->primary_key];
for (uint i = 0; i < key->user_defined_key_parts; i++) {
KEY_PART_INFO* key_part = &key->key_part[i];
if (strcmp(field->field_name.str, key_part->field->field_name.str) == 0) {
@@ -517,7 +517,7 @@ static bool check_point_update(Item* conds, TABLE* table) {
MY_BITMAP pk_fields;
if (bitmap_init(&pk_fields, NULL, table->s->fields, FALSE)) // 1 -> failure
return false;
- KEY *key = &table->s->key_info[table->s->primary_key];
+ KEY *key = &table->key_info[table->s->primary_key];
for (uint i = 0; i < key->user_defined_key_parts; i++)
bitmap_set_bit(&pk_fields, key->key_part[i].field->field_index);
@@ -555,7 +555,7 @@ static bool check_point_update(Item* conds, TABLE* table) {
static bool clustering_keys_exist(TABLE *table) {
for (uint keynr = 0; keynr < table->s->keys; keynr++) {
if (keynr != table->s->primary_key &&
- key_is_clustering(&table->s->key_info[keynr]))
+ key_is_clustering(&table->key_info[keynr]))
return true;
}
return false;
diff --git a/storage/tokudb/man/tokuft_logprint.1 b/storage/tokudb/man/tokuft_logprint.1
index 0a9ff539b73..c97f7e19f69 100644
--- a/storage/tokudb/man/tokuft_logprint.1
+++ b/storage/tokudb/man/tokuft_logprint.1
@@ -1,6 +1,6 @@
'\" t
.\"
-.TH "\FBTOKUFT_LOGPRINT\FR" "1" "29 March 2019" "MariaDB 10\&.3" "MariaDB Database System"
+.TH "\FBTOKUFT_LOGPRINT\FR" "1" "28 March 2019" "MariaDB 10\&.4" "MariaDB Database System"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
diff --git a/storage/tokudb/man/tokuftdump.1 b/storage/tokudb/man/tokuftdump.1
index 024b16ba631..a9c900e0045 100644
--- a/storage/tokudb/man/tokuftdump.1
+++ b/storage/tokudb/man/tokuftdump.1
@@ -1,6 +1,6 @@
'\" t
.\"
-.TH "\FBTOKUFTDUMP\FR" "1" "9 May 2017" "MariaDB 10\&.3" "MariaDB Database System"
+.TH "\FBTOKUFTDUMP\FR" "1" "28 March 2019" "MariaDB 10\&.4" "MariaDB Database System"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result
index c7450a1b9c0..aea5bab7cf3 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug28430.result
@@ -51,6 +51,10 @@ DELETE FROM test.regular_tbl WHERE id = del_count;
SET del_count = del_count - 2;
END WHILE;
END|
+Warnings:
+Level Warning
+Code 1287
+Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
CREATE PROCEDURE test.proc_bykey()
BEGIN
DECLARE ins_count INT DEFAULT 1000;
@@ -72,6 +76,10 @@ DELETE FROM test.bykey_tbl WHERE id = del_count;
SET del_count = del_count - 2;
END WHILE;
END|
+Warnings:
+Level Warning
+Code 1287
+Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
CREATE PROCEDURE test.proc_byrange()
BEGIN
DECLARE ins_count INT DEFAULT 1000;
@@ -93,6 +101,10 @@ DELETE FROM test.byrange_tbl WHERE id = del_count;
SET del_count = del_count - 2;
END WHILE;
END|
+Warnings:
+Level Warning
+Code 1287
+Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
CALL test.proc_norm();
SELECT count(*) as "Master regular" FROM test.regular_tbl;
Master regular 500
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result
index f3ffc908504..912b05216da 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_bug30888.result
@@ -26,6 +26,10 @@ DELETE FROM test.regular_tbl WHERE id = del_count;
SET del_count = del_count - 2;
END WHILE;
END|
+Warnings:
+Level Warning
+Code 1287
+Message '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
CALL test.proc_norm();
connection slave;
connection master;
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result
index 5f41fd328c9..a639bf6e76c 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_mixed_dml.result
@@ -484,77 +484,78 @@ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
******************** CREATE USER ********************
CREATE USER 'user_test_rpl'@'localhost' IDENTIFIED BY PASSWORD '*1111111111111111111111111111111111111111';
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
-localhost user_test_rpl *1111111111111111111111111111111111111111 N
+Host User Password plugin authentication_string Select_priv
+localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N
connection slave;
USE test_rpl;
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
-localhost user_test_rpl *1111111111111111111111111111111111111111 N
+Host User Password plugin authentication_string Select_priv
+localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N
connection master;
******************** GRANT ********************
GRANT SELECT ON *.* TO 'user_test_rpl'@'localhost';
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
-localhost user_test_rpl *1111111111111111111111111111111111111111 Y
+Host User Password plugin authentication_string Select_priv
+localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 Y
connection slave;
USE test_rpl;
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
-localhost user_test_rpl *1111111111111111111111111111111111111111 Y
+Host User Password plugin authentication_string Select_priv
+localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 Y
connection master;
******************** REVOKE ********************
REVOKE SELECT ON *.* FROM 'user_test_rpl'@'localhost';
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
-localhost user_test_rpl *1111111111111111111111111111111111111111 N
+Host User Password plugin authentication_string Select_priv
+localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N
connection slave;
USE test_rpl;
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
-localhost user_test_rpl *1111111111111111111111111111111111111111 N
+Host User Password plugin authentication_string Select_priv
+localhost user_test_rpl *1111111111111111111111111111111111111111 mysql_native_password *1111111111111111111111111111111111111111 N
connection master;
******************** SET PASSWORD ********************
SET PASSWORD FOR 'user_test_rpl'@'localhost' = '*0000000000000000000000000000000000000000';
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
+Host User Password plugin authentication_string Select_priv
localhost user_test_rpl *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N
connection slave;
USE test_rpl;
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
+Host User Password plugin authentication_string Select_priv
localhost user_test_rpl *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N
connection master;
******************** RENAME USER ********************
RENAME USER 'user_test_rpl'@'localhost' TO 'user_test_rpl_2'@'localhost';
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
+Host User Password plugin authentication_string Select_priv
localhost user_test_rpl_2 *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N
connection slave;
USE test_rpl;
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
+Host User Password plugin authentication_string Select_priv
localhost user_test_rpl_2 *0000000000000000000000000000000000000000 mysql_native_password *0000000000000000000000000000000000000000 N
connection master;
******************** DROP USER ********************
DROP USER 'user_test_rpl_2'@'localhost';
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
+Host User Password plugin authentication_string Select_priv
connection slave;
USE test_rpl;
SELECT host, user, password, plugin, authentication_string, select_priv FROM mysql.user WHERE user LIKE 'user_test_rpl%';
-host user password plugin authentication_string select_priv
+Host User Password plugin authentication_string Select_priv
connection master;
INSERT INTO t1 VALUES(100, 'test');
******************** ANALYZE ********************
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test_rpl.t1 analyze status Engine-independent statistics collected
test_rpl.t1 analyze status OK
******************** CHECK TABLE ********************
@@ -679,7 +680,6 @@ DROP TRIGGER tr1;
******************** EVENTS ********************
-GRANT EVENT ON *.* TO 'root'@'localhost';
INSERT INTO t1 VALUES(1, 'test1');
CREATE EVENT e1 ON SCHEDULE EVERY '1' SECOND COMMENT 'e_second_comment' DO DELETE FROM t1;
Warnings:
@@ -1103,8 +1103,6 @@ master-bin.000001 # Query # # use `test_rpl`; DELETE FROM t2
master-bin.000001 # Xid # # COMMIT /* XID */
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test_rpl`; DROP TRIGGER tr1
-master-bin.000001 # Gtid # # GTID #-#-#
-master-bin.000001 # Query # # use `test_rpl`; GRANT EVENT ON *.* TO 'root'@'localhost'
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
master-bin.000001 # Query # # use `test_rpl`; INSERT INTO t1 VALUES(1, 'test1')
master-bin.000001 # Xid # # COMMIT /* XID */
diff --git a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
index 593f177569f..e0b6b615bb6 100644
--- a/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
+++ b/storage/tokudb/mysql-test/rpl/r/rpl_tokudb_read_only_ft.result
@@ -24,6 +24,10 @@ unix_timestamp()-@tstart <= 10
connection slave;
connection master;
include/diff_tables.inc [master:test.t, slave:test.t]
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
+Warnings:
+Warning 1287 '<select expression> INTO <destination>;' is deprecated and will be removed in a future release. Please use 'SELECT <select list> INTO <destination> FROM...' instead
connection master;
drop table if exists t;
connection slave;
diff --git a/storage/tokudb/mysql-test/tokudb/include/cluster_key.inc b/storage/tokudb/mysql-test/tokudb/include/cluster_key.inc
index d637b46e8fc..1914da14bb3 100644
--- a/storage/tokudb/mysql-test/tokudb/include/cluster_key.inc
+++ b/storage/tokudb/mysql-test/tokudb/include/cluster_key.inc
@@ -1,7 +1,10 @@
# test for TokuDB clustering keys.
# test assumes that a table 't1' exists with the following columns:
# a int, b int, c int, d int
-insert into t1 values (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),(9,90,900,9000);
+insert into t1 values
+ (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),
+ (5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),
+ (9,90,900,9000),(10,100,1000,10000),(11,110,1100,11000);
#normal queries
@@ -13,20 +16,20 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 950;
+select * from t1 where c > 950;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select a from t1 where a > 8;
-select a from t1 where a > 8;
+explain select a from t1 where a > 10;
+select a from t1 where a > 10;
# ignore rows column
--replace_column 9 NULL;
@@ -35,8 +38,8 @@ select a,b from t1 where b > 30;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 350;
+select a,c from t1 where c > 350;
alter table t1 add index bdca(b,d,c,a) clustering=yes;
@@ -51,25 +54,25 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 950;
+select * from t1 where c > 950;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select b from t1 where b > 30;
-select b from t1 where b > 30;
+explain select b from t1 where b > 70;
+select b from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select b from t1 where c > 750;
-select c from t1 where c > 750;
+explain select b from t1 where c > 950;
+select c from t1 where c > 950;
alter table t1 add e varchar(20);
@@ -77,25 +80,25 @@ alter table t1 add primary key (a,b,c);
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where a > 5;
-select * from t1 where a > 5;
+explain select * from t1 where a > 8;
+select * from t1 where a > 8;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 950;
+select * from t1 where c > 950;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select a from t1 where a > 8;
-select a from t1 where a > 8;
+explain select a from t1 where a > 10;
+select a from t1 where a > 10;
# ignore rows column
--replace_column 9 NULL;
@@ -104,8 +107,8 @@ select a,b from t1 where b > 30;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 350;
+select a,c from t1 where c > 350;
alter table t1 drop primary key;
@@ -116,23 +119,23 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 950;
+select * from t1 where c > 950;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select b from t1 where b > 30;
-select b from t1 where b > 30;
+explain select b from t1 where b > 70;
+select b from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select b from t1 where c > 750;
-select c from t1 where c > 750;
+explain select b from t1 where c > 950;
+select c from t1 where c > 950;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result b/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result
index 71a39eb1f3e..887ccd5f073 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_add_drop.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, c int, d int, key(a), key(b), key(c));
insert into tt values (0,0,0,0),(1,0,0,0),(2,0,1,0),(3,0,1,0);
show indexes from tt;
@@ -9,6 +11,7 @@ tt 1 b 1 b A 4 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -23,6 +26,7 @@ tt 1 c 1 c A 4 NULL NULL YES BTREE
tt 1 d 1 d A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -35,4 +39,5 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
tt 1 d 1 d A 2 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_add_index.result b/storage/tokudb/mysql-test/tokudb/r/card_add_index.result
index 9a929b19a80..ab7c6e330f4 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_add_index.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_add_index.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, c int, primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
show indexes from tt;
@@ -7,6 +9,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -18,6 +21,7 @@ tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -31,6 +35,7 @@ tt 1 b 1 b A 2 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -43,4 +48,5 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 1 b 1 b A 2 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result b/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result
index 2cfdfe11296..f924c8cd12b 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_drop_index.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
show indexes from tt;
@@ -9,6 +11,7 @@ tt 1 b 1 b A 4 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -28,4 +31,5 @@ flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result b/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result
index ed28d2a3226..5980b5795d5 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_drop_index_2.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, c int, primary key(a), key(b), key(c));
insert into tt values (0, 0, 0), (0+1, 0, 0), (0+2, 0, 0), (0+3, 0, 0);
insert into tt values (4, 4, 0), (4+1, 4, 0), (4+2, 4, 0), (4+3, 4, 0);
@@ -136,6 +138,7 @@ tt 1 b 1 b A 500 NULL NULL YES BTREE
tt 1 c 1 c A 500 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -155,4 +158,5 @@ flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 500 NULL NULL BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result b/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result
index 2369d88c274..c560defb1fb 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_drop_pk.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
show indexes from tt;
@@ -9,6 +11,7 @@ tt 1 b 1 b A 4 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -25,4 +28,5 @@ show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 b 1 b A 4 NULL NULL YES BTREE
tt 1 c 1 c A 4 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result b/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result
index 1302cfaf252..a96f3edd4b8 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_no_keys.result
@@ -6,6 +6,7 @@ show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_pk.result b/storage/tokudb/mysql-test/tokudb/r/card_pk.result
index b0317507f7c..173fb696d69 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_pk.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_pk.result
@@ -7,6 +7,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result b/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result
index 3c1b652db15..b1c3e679bb8 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_pk_2.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, primary key(a,b));
insert into tt values (0,0),(0,1),(1,0),(1,1);
show indexes from tt;
@@ -8,6 +10,7 @@ tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 0 PRIMARY 2 b A 4 NULL NULL BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -18,4 +21,5 @@ show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4 NULL NULL BTREE
tt 0 PRIMARY 2 b A 4 NULL NULL BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result b/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result
index 02c8d1f8218..2f527cbbed5 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_pk_sk.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, primary key(a), key(b));
insert into tt values (4*0,4*0+1),(4*0+1,4*0+2),(4*0+2,4*0+3),(4*0+3,4*0+4);
insert into tt values (4*1,4*1+1),(4*1+1,4*1+2),(4*1+2,4*1+3),(4*1+3,4*1+4);
@@ -1007,6 +1009,7 @@ tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE
tt 1 b 1 b A 4000 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -2025,6 +2028,7 @@ tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE
tt 1 b 1 b A 4000 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -2035,4 +2039,5 @@ show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE
tt 1 b 1 b A 2 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result
index 981433fac91..a452be2006a 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result
@@ -1,5 +1,6 @@
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
set global tokudb_cardinality_scale_percent = 10;
show indexes from tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_sk.result b/storage/tokudb/mysql-test/tokudb/r/card_sk.result
index 310fc863a9b..1956c846e03 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_sk.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_sk.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, key(b));
insert into tt values (1,0),(2,1),(3,2),(4,3);
insert into tt values (5,0),(6,1),(7,2),(8,3);
@@ -8,6 +10,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
tt 1 b 1 b A 8 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -16,4 +19,5 @@ flush tables;
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 b 1 b A 8 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result b/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result
index 8ff57b63e5d..f0fcbac0e3a 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_sk_2.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists tt;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table tt (a int, b int, key(a,b));
insert into tt values (0,0),(0,1),(1,0),(1,1);
show indexes from tt;
@@ -8,6 +10,7 @@ tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 a 2 b A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -18,4 +21,5 @@ show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
tt 1 a 1 a A 4 NULL NULL YES BTREE
tt 1 a 2 b A 4 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result b/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result
index cbcab7bdc44..22b0733a933 100644
--- a/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result
+++ b/storage/tokudb/mysql-test/tokudb/r/card_unique_sk.result
@@ -7,6 +7,7 @@ Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_par
tt 0 a 1 a A 4 NULL NULL YES BTREE
analyze table tt;
Table Op Msg_type Msg_text
+test.tt analyze status Engine-independent statistics collected
test.tt analyze status OK
show indexes from tt;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_2968-2.result b/storage/tokudb/mysql-test/tokudb/r/cluster_2968-2.result
index 4c3f971770e..b2749966565 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_2968-2.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_2968-2.result
@@ -1096,7 +1096,7 @@ t CREATE TABLE `t` (
explain select straight_join s.a,t.a from s,t where s.b = t.b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE s index b,b_2,b_3 b_2 10 NULL 1000 Using where; Using index
-1 SIMPLE t ref b,b_2,b_3 b_2 5 test.s.b 1 Using index
+1 SIMPLE t ref b,b_2,b_3 b_3 5 test.s.b 1 Using index
alter table s drop key b_2;
alter table t drop key b_2;
show create table s;
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_create_table.result b/storage/tokudb/mysql-test/tokudb/r/cluster_create_table.result
index 02a90c66398..bbc886fb329 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_create_table.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_create_table.result
@@ -39,16 +39,20 @@ t1 CREATE TABLE `t1` (
KEY `foo` (`c`,`d`) `clustering`=yes,
KEY `bar` (`d`,`c`,`b`,`a`) `clustering`=yes
) ENGINE=TokuDB DEFAULT CHARSET=latin1
-insert into t1 value (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(32,54,12,56);
+insert into t1 value
+(1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),
+(32,54,12,56);
explain select * from t1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 16 NULL 5 Using index
+1 SIMPLE t1 index NULL PRIMARY 16 NULL 7 Using index
select * from t1;
a b c d
1 1 1 1
2 2 2 2
3 3 3 3
4 4 4 4
+5 5 5 5
+6 6 6 6
32 54 12 56
explain select d from t1 where d > 30;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_delete.result b/storage/tokudb/mysql-test/tokudb/r/cluster_delete.result
index 1fd519debef..f85845232dd 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_delete.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_delete.result
@@ -1,7 +1,10 @@
SET DEFAULT_STORAGE_ENGINE='tokudb';
DROP TABLE IF EXISTS t1;
create table t1(a int, b int, c int, d int, primary key(a), key(b) clustering=yes, key (c))engine=tokudb;
-insert into t1 values (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),(9,90,900,9000);
+insert into t1 values
+(1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),
+(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),
+(9,90,900,9000),(10,100,1000,10000),(11,110,1100,11000);
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where
@@ -11,48 +14,47 @@ a b c d
7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where b > 30;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d
-4 40 400 4000
-5 50 500 5000
-6 60 600 6000
-7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where c > 750;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where c > 850;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select * from t1 where c > 750;
+1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
+select * from t1 where c > 850;
a b c d
-8 80 800 8000
9 90 900 9000
-explain select a from t1 where a > 8;
+10 100 1000 10000
+11 110 1100 11000
+explain select a from t1 where a > 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where; Using index
-select a from t1 where a > 8;
+select a from t1 where a > 10;
a
-9
-explain select a,b from t1 where b > 30;
+11
+explain select a,b from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select a,b from t1 where b > 30;
+select a,b from t1 where b > 70;
a b
-4 40
-5 50
-6 60
-7 70
8 80
9 90
-explain select a,b from t1 where c > 750;
+10 100
+11 110
+explain select a,b from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 950;
a c
-8 800
-9 900
+10 1000
+11 1100
delete from t1 where b>30 and b < 60;
select * from t1;
a b c d
@@ -63,15 +65,16 @@ a b c d
7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where a > 5;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where a > 8;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where
-select * from t1 where a > 5;
+select * from t1 where a > 8;
a b c d
-6 60 600 6000
-7 70 700 7000
-8 80 800 8000
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select * from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
@@ -81,19 +84,25 @@ a b c d
7 70 700 7000
8 80 800 8000
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select * from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range c c 5 NULL NULL; Using where
+1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
select * from t1 where c > 750;
a b c d
8 80 800 8000
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select a from t1 where a > 8;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where; Using index
+1 SIMPLE t1 index PRIMARY c 5 NULL NULL; Using where; Using index
select a from t1 where a > 8;
a
9
+10
+11
explain select a,b from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
@@ -103,13 +112,14 @@ a b
7 70
8 80
9 90
-explain select a,b from t1 where c > 750;
+10 100
+11 110
+explain select a,b from t1 where c > 1050;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 1050;
a c
-8 800
-9 900
+11 1100
alter table t1 drop primary key;
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
@@ -120,22 +130,23 @@ a b c d
7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where b > 30;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d
-6 60 600 6000
-7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where c > 750;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where c > 1050;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 1050;
a b c d
-8 80 800 8000
-9 90 900 9000
+11 110 1100 11000
explain select a from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL NULL; Using where
@@ -145,61 +156,76 @@ a
7
8
9
-explain select a,b from t1 where b > 30;
+10
+11
+explain select a,b from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select a,b from t1 where b > 30;
+select a,b from t1 where b > 70;
a b
-6 60
-7 70
8 80
9 90
-explain select a,b from t1 where c > 750;
+10 100
+11 110
+explain select a,b from t1 where c > 1050;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 1050;
a c
-8 800
-9 900
+11 1100
delete from t1 where b > 10 and b < 90;
select * from t1;
a b c d
1 10 100 1000
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL NULL; Using where
select * from t1 where a > 5;
a b c d
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select * from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
select * from t1 where b > 30;
a b c d
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select * from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
select * from t1 where c > 750;
a b c d
9 90 900 9000
+10 100 1000 10000
+11 110 1100 11000
explain select a from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL NULL; Using where
select a from t1 where a > 5;
a
9
+10
+11
explain select a,b from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
select a,b from t1 where b > 30;
a b
9 90
+10 100
+11 110
explain select a,b from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
select a,c from t1 where c > 750;
a c
9 900
+10 1000
+11 1100
drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_key.result b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_key.result
index a594b104444..aa33246bfeb 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_filter_key.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_filter_key.result
@@ -7,22 +7,19 @@ insert into t1 values (2,"20",200);
insert into t1 values (3,"30",300);
insert into t1 values (4,"40",400);
insert into t1 values (5,"50",500);
-explain select * from t1 where a > 2;
+explain select * from t1 where a > 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 3 Using where
-select * from t1 where a > 2;
+1 SIMPLE t1 range a a 5 NULL 2 Using where
+select * from t1 where a > 3;
a b c
-3 30 300
4 40 400
5 50 500
-select b from t1 where a > 2;
+select b from t1 where a > 3;
b
-30
40
50
-select c from t1 where a > 2;
+select c from t1 where a > 3;
c
-300
400
500
delete from t1 where a <2;
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_key.result b/storage/tokudb/mysql-test/tokudb/r/cluster_key.result
index fab288047be..4c2fc08cd48 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_key.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_key.result
@@ -1,7 +1,10 @@
SET DEFAULT_STORAGE_ENGINE='tokudb';
DROP TABLE IF EXISTS t1;
create table t1(a int, b int, c int, d int, primary key(a,b,c), key(b) clustering=yes, key (c))engine=tokudb;
-insert into t1 values (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),(9,90,900,9000);
+insert into t1 values
+(1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),
+(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),
+(9,90,900,9000),(10,100,1000,10000),(11,110,1100,11000);
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where
@@ -11,30 +14,30 @@ a b c d
7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where b > 30;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 4 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d
-4 40 400 4000
-5 50 500 5000
-6 60 600 6000
-7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where c > 750;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 4 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 950;
a b c d
-8 80 800 8000
-9 90 900 9000
-explain select a from t1 where a > 8;
+10 100 1000 10000
+11 110 1100 11000
+explain select a from t1 where a > 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where; Using index
-select a from t1 where a > 8;
+select a from t1 where a > 10;
a
-9
+11
explain select a,b from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b c 4 NULL NULL; Using where; Using index
@@ -46,13 +49,21 @@ a b
7 70
8 80
9 90
-explain select a,b from t1 where c > 750;
+10 100
+11 110
+explain select a,b from t1 where c > 350;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index c c 4 NULL NULL; Using where; Using index
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 350;
a c
+4 400
+5 500
+6 600
+7 700
8 800
9 900
+10 1000
+11 1100
alter table t1 add index bdca(b,d,c,a) clustering=yes;
insert into t1 values (10,10,10,10);
alter table t1 drop index bdca;
@@ -67,79 +78,73 @@ a b c d
8 80 800 8000
9 90 900 9000
10 10 10 10
-explain select * from t1 where b > 30;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 4 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d
-4 40 400 4000
-5 50 500 5000
-6 60 600 6000
-7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where c > 750;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 4 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 950;
a b c d
-8 80 800 8000
-9 90 900 9000
-explain select b from t1 where b > 30;
+10 100 1000 10000
+11 110 1100 11000
+explain select b from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 4 NULL NULL; Using where; Using index
-select b from t1 where b > 30;
+select b from t1 where b > 70;
b
-40
-50
-60
-70
80
90
-explain select b from t1 where c > 750;
+100
+110
+explain select b from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 4 NULL NULL; Using where
-select c from t1 where c > 750;
+select c from t1 where c > 950;
c
-800
-900
+1000
+1100
alter table t1 add e varchar(20);
alter table t1 add primary key (a,b,c);
-explain select * from t1 where a > 5;
+explain select * from t1 where a > 8;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where
-select * from t1 where a > 5;
+select * from t1 where a > 8;
a b c d e
-6 60 600 6000 NULL
-7 70 700 7000 NULL
-8 80 800 8000 NULL
9 90 900 9000 NULL
10 10 10 10 NULL
-explain select * from t1 where b > 30;
+10 100 1000 10000 NULL
+11 110 1100 11000 NULL
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 4 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d e
-4 40 400 4000 NULL
-5 50 500 5000 NULL
-6 60 600 6000 NULL
-7 70 700 7000 NULL
8 80 800 8000 NULL
9 90 900 9000 NULL
-explain select * from t1 where c > 750;
+10 100 1000 10000 NULL
+11 110 1100 11000 NULL
+explain select * from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 4 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 950;
a b c d e
-8 80 800 8000 NULL
-9 90 900 9000 NULL
-explain select a from t1 where a > 8;
+10 100 1000 10000 NULL
+11 110 1100 11000 NULL
+explain select a from t1 where a > 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where; Using index
-select a from t1 where a > 8;
+select a from t1 where a > 10;
a
-9
-10
+11
explain select a,b from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b c 4 NULL NULL; Using where; Using index
@@ -151,13 +156,21 @@ a b
7 70
8 80
9 90
-explain select a,b from t1 where c > 750;
+10 100
+11 110
+explain select a,b from t1 where c > 350;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index c c 4 NULL NULL; Using where; Using index
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 350;
a c
+4 400
+5 500
+6 600
+7 700
8 800
9 900
+10 1000
+11 1100
alter table t1 drop primary key;
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
@@ -169,40 +182,38 @@ a b c d e
8 80 800 8000 NULL
9 90 900 9000 NULL
10 10 10 10 NULL
-explain select * from t1 where b > 30;
+10 100 1000 10000 NULL
+11 110 1100 11000 NULL
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 4 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d e
-4 40 400 4000 NULL
-5 50 500 5000 NULL
-6 60 600 6000 NULL
-7 70 700 7000 NULL
8 80 800 8000 NULL
9 90 900 9000 NULL
-explain select * from t1 where c > 750;
+10 100 1000 10000 NULL
+11 110 1100 11000 NULL
+explain select * from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 4 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 950;
a b c d e
-8 80 800 8000 NULL
-9 90 900 9000 NULL
-explain select b from t1 where b > 30;
+10 100 1000 10000 NULL
+11 110 1100 11000 NULL
+explain select b from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 4 NULL NULL; Using where; Using index
-select b from t1 where b > 30;
+select b from t1 where b > 70;
b
-40
-50
-60
-70
80
90
-explain select b from t1 where c > 750;
+100
+110
+explain select b from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 4 NULL NULL; Using where
-select c from t1 where c > 750;
+select c from t1 where c > 950;
c
-800
-900
+1000
+1100
drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_query_plan.result b/storage/tokudb/mysql-test/tokudb/r/cluster_query_plan.result
index c6754db3981..6b458b36585 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_query_plan.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_query_plan.result
@@ -2,16 +2,16 @@ SET DEFAULT_STORAGE_ENGINE='tokudb';
DROP TABLE IF EXISTS t1;
create table t1(a int, b int, c int, d int, primary key(a), key(b) clustering=yes, key (c))engine=tokudb;
insert into t1 values (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),(7,7,7,7),(8,8,8,8),(9,9,9,9);
-explain select * from t1 where b > 2;
+explain select * from t1 where b > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-explain select * from t1 where c > 2;
+explain select * from t1 where c > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
-explain select * from t1 where a > 4;
+explain select * from t1 where a > 7;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where
-explain select * from t1 where c > 7;
+explain select * from t1 where c > 8;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
explain select * from t1 where b > 7;
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_tokudb_bug_993_2.result b/storage/tokudb/mysql-test/tokudb/r/cluster_tokudb_bug_993_2.result
index 41abded2857..2dcb65cee10 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_tokudb_bug_993_2.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_tokudb_bug_993_2.result
@@ -32,13 +32,13 @@ max(a)
7
explain select a,b from z1 where a < 7;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE z1 range a a 5 NULL 12 Using where; Using index
+1 SIMPLE z1 index a a 10 NULL 14 Using where; Using index
select max(a) from z1 where a < 7;
max(a)
3
explain select a,b from z1 where a < 3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE z1 range a a 5 NULL 9 Using where; Using index
+1 SIMPLE z1 index a a 10 NULL 14 Using where; Using index
select max(a) from z1 where a < 3;
max(a)
1
diff --git a/storage/tokudb/mysql-test/tokudb/r/cluster_update.result b/storage/tokudb/mysql-test/tokudb/r/cluster_update.result
index 14ab9a27dc4..586cf2e23d9 100644
--- a/storage/tokudb/mysql-test/tokudb/r/cluster_update.result
+++ b/storage/tokudb/mysql-test/tokudb/r/cluster_update.result
@@ -1,7 +1,10 @@
SET DEFAULT_STORAGE_ENGINE='tokudb';
DROP TABLE IF EXISTS t1;
create table t1(a int, b int, c int, d int, primary key(a), key(b) clustering=yes, key (c))engine=tokudb;
-insert into t1 values (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),(9,90,900,9000);
+insert into t1 values
+(1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),
+(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),
+(9,90,900,9000),(10,100,1000,10000),(11,110,1100,11000);
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where
@@ -11,48 +14,48 @@ a b c d
7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where b > 30;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d
-4 40 400 4000
-5 50 500 5000
-6 60 600 6000
-7 70 700 7000
8 80 800 8000
9 90 900 9000
-explain select * from t1 where c > 750;
+10 100 1000 10000
+11 110 1100 11000
+explain select * from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 950;
a b c d
-8 80 800 8000
-9 90 900 9000
-explain select a from t1 where a > 8;
+10 100 1000 10000
+11 110 1100 11000
+explain select a from t1 where a > 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where; Using index
select a from t1 where a > 8;
a
9
-explain select a,b from t1 where b > 30;
+10
+11
+explain select a,b from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select a,b from t1 where b > 30;
+select a,b from t1 where b > 70;
a b
-4 40
-5 50
-6 60
-7 70
8 80
9 90
-explain select a,b from t1 where c > 750;
+10 100
+11 110
+explain select a,b from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 950;
a c
-8 800
-9 900
+10 1000
+11 1100
update t1 set c = c+5, b = b+5 where b>30;
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
@@ -63,6 +66,8 @@ a b c d
7 75 705 7000
8 85 805 8000
9 95 905 9000
+10 105 1005 10000
+11 115 1105 11000
explain select * from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
@@ -74,6 +79,8 @@ a b c d
7 75 705 7000
8 85 805 8000
9 95 905 9000
+10 105 1005 10000
+11 115 1105 11000
explain select * from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
@@ -81,12 +88,14 @@ select * from t1 where c > 750;
a b c d
8 85 805 8000
9 95 905 9000
-explain select a from t1 where a > 8;
+10 105 1005 10000
+11 115 1105 11000
+explain select a from t1 where a > 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL NULL; Using where; Using index
-select a from t1 where a > 8;
+select a from t1 where a > 10;
a
-9
+11
explain select a,b from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 NA b b 5 NULL NULL; Using where; Using index
@@ -98,6 +107,8 @@ a b
7 75
8 85
9 95
+10 105
+11 115
explain select a,b from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
@@ -105,6 +116,8 @@ select a,c from t1 where c > 750;
a c
8 805
9 905
+10 1005
+11 1105
alter table t1 drop primary key;
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
@@ -115,24 +128,25 @@ a b c d
7 75 705 7000
8 85 805 8000
9 95 905 9000
-explain select * from t1 where b > 30;
+10 105 1005 10000
+11 115 1105 11000
+explain select * from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select * from t1 where b > 30;
+select * from t1 where b > 70;
a b c d
-4 45 405 4000
-5 55 505 5000
-6 65 605 6000
7 75 705 7000
8 85 805 8000
9 95 905 9000
-explain select * from t1 where c > 750;
+10 105 1005 10000
+11 115 1105 11000
+explain select * from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select * from t1 where c > 750;
+select * from t1 where c > 950;
a b c d
-8 85 805 8000
-9 95 905 9000
+10 105 1005 10000
+11 115 1105 11000
explain select a from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL NULL; Using where
@@ -142,24 +156,25 @@ a
7
8
9
-explain select a,b from t1 where b > 30;
+10
+11
+explain select a,b from t1 where b > 70;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range b b 5 NULL NULL; Using where; Using index
-select a,b from t1 where b > 30;
+select a,b from t1 where b > 70;
a b
-4 45
-5 55
-6 65
7 75
8 85
9 95
-explain select a,b from t1 where c > 750;
+10 105
+11 115
+explain select a,b from t1 where c > 950;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range c c 5 NULL NULL; Using where
-select a,c from t1 where c > 750;
+select a,c from t1 where c > 950;
a c
-8 805
-9 905
+10 1005
+11 1105
update t1 set c = c+5, b = b+5 where b>30;
select * from t1;
a b c d
@@ -172,6 +187,8 @@ a b c d
7 80 710 7000
8 90 810 8000
9 100 910 9000
+10 110 1010 10000
+11 120 1110 11000
explain select * from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL NULL; Using where
@@ -181,6 +198,8 @@ a b c d
7 80 710 7000
8 90 810 8000
9 100 910 9000
+10 110 1010 10000
+11 120 1110 11000
explain select * from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
@@ -192,6 +211,8 @@ a b c d
7 80 710 7000
8 90 810 8000
9 100 910 9000
+10 110 1010 10000
+11 120 1110 11000
explain select * from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
@@ -199,6 +220,8 @@ select * from t1 where c > 750;
a b c d
8 90 810 8000
9 100 910 9000
+10 110 1010 10000
+11 120 1110 11000
explain select a from t1 where a > 5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL NULL; Using where
@@ -208,6 +231,8 @@ a
7
8
9
+10
+11
explain select a,b from t1 where b > 30;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index b b 5 NULL NULL; Using where; Using index
@@ -219,6 +244,8 @@ a b
7 80
8 90
9 100
+10 110
+11 120
explain select a,b from t1 where c > 750;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL c NULL NULL NULL NULL; Using where
@@ -226,4 +253,6 @@ select a,c from t1 where c > 750;
a c
8 810
9 910
+10 1010
+11 1110
drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/compressions.result b/storage/tokudb/mysql-test/tokudb/r/compressions.result
index 435b34b6af3..a65d431d797 100644
--- a/storage/tokudb/mysql-test/tokudb/r/compressions.result
+++ b/storage/tokudb/mysql-test/tokudb/r/compressions.result
@@ -8,4 +8,5 @@ FOUND 1 /compression_method=7/ in dump
FOUND 1 /compression_method=9/ in dump
FOUND 1 /compression_method=10/ in dump
FOUND 1 /compression_method=11/ in dump
+# restart
DROP TABLE t1, t2, t3, t4, t5;
diff --git a/storage/tokudb/mysql-test/tokudb/r/dir_per_db_rename_to_nonexisting_schema.result b/storage/tokudb/mysql-test/tokudb/r/dir_per_db_rename_to_nonexisting_schema.result
index 992f380591f..f73a9e43e4a 100644
--- a/storage/tokudb/mysql-test/tokudb/r/dir_per_db_rename_to_nonexisting_schema.result
+++ b/storage/tokudb/mysql-test/tokudb/r/dir_per_db_rename_to_nonexisting_schema.result
@@ -21,6 +21,7 @@ CALL mtr.add_suppression("because destination db does not exist");
ALTER TABLE test.t1 RENAME foo.t1;
ERROR HY000: Error on rename of './test/t1' to './foo/t1' (errno: 2 "No such file or directory")
DROP TABLE t1;
+# restart
SELECT @@tokudb_data_dir;
@@tokudb_data_dir
NULL
diff --git a/storage/tokudb/mysql-test/tokudb/r/tokudb_mrr.result b/storage/tokudb/mysql-test/tokudb/r/tokudb_mrr.result
index 024580d4258..fd584a3ca0f 100644
--- a/storage/tokudb/mysql-test/tokudb/r/tokudb_mrr.result
+++ b/storage/tokudb/mysql-test/tokudb/r/tokudb_mrr.result
@@ -305,25 +305,25 @@ dummy INT PRIMARY KEY,
a INT UNIQUE,
b INT
) ENGINE=TokuDB;
-INSERT INTO t1 VALUES (1,1,1),(3,3,3),(5,5,5);
+INSERT INTO t1 VALUES (1,1,1),(3,3,3),(5,5,5),(7,7,7),(8,8,8),(9,9,9);
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @@tx_isolation;
@@tx_isolation
REPEATABLE-READ
START TRANSACTION;
-EXPLAIN SELECT * FROM t1 WHERE a >= 2 FOR UPDATE;
+EXPLAIN SELECT * FROM t1 WHERE a >= 8 FOR UPDATE;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range a a 5 NULL 2 Using where
-SELECT * FROM t1 WHERE a >= 2 FOR UPDATE;
+SELECT * FROM t1 WHERE a >= 8 FOR UPDATE;
dummy a b
-3 3 3
-5 5 5
+8 8 8
+9 9 9
connection con2;
SET AUTOCOMMIT=0;
SET TOKUDB_LOCK_TIMEOUT=2;
START TRANSACTION;
-INSERT INTO t1 VALUES (2,2,2);
+INSERT INTO t1 VALUES (8,8,8);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
ROLLBACK;
connection con1;
diff --git a/storage/tokudb/mysql-test/tokudb/r/type_bit.result b/storage/tokudb/mysql-test/tokudb/r/type_bit.result
index c147c203d43..76a032d99c4 100644
--- a/storage/tokudb/mysql-test/tokudb/r/type_bit.result
+++ b/storage/tokudb/mysql-test/tokudb/r/type_bit.result
@@ -759,7 +759,7 @@ CREATE TABLE t1 (a BIT(7), b BIT(9), KEY(a, b));
INSERT INTO t1 VALUES(0, 0), (5, 3), (5, 6), (6, 4), (7, 0);
EXPLAIN SELECT a+0, b+0 FROM t1 WHERE a > 4 and b < 7 ORDER BY 2;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 2 NULL 4 Using where; Using index; Using filesort
+1 SIMPLE t1 index a a 5 NULL 5 Using where; Using index; Using filesort
DROP TABLE t1;
End of 5.0 tests
create table t1(a bit(7));
diff --git a/storage/tokudb/mysql-test/tokudb/r/type_blob.result b/storage/tokudb/mysql-test/tokudb/r/type_blob.result
index 1350bc03045..f3d634d84c1 100644
--- a/storage/tokudb/mysql-test/tokudb/r/type_blob.result
+++ b/storage/tokudb/mysql-test/tokudb/r/type_blob.result
@@ -357,8 +357,6 @@ HELLO MY 1
a 1
hello 1
drop table t1;
-create table t1 (a text, unique (a(21000)));
-ERROR 42000: Specified key was too long; max key length is 3072 bytes
create table t1 (a text, key (a(2100)));
show create table t1;
Table Create Table
@@ -597,6 +595,9 @@ id txt
explain select * from t1 where txt='Chevy' or txt is NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL txt_index NULL NULL NULL 3 Using where
+explain select * from t1 FORCE INDEX (`txt_index`) where txt='Chevy' or txt is NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref_or_null txt_index txt_index 23 const 3 Using where
select * from t1 where txt='Chevy ';
id txt
1 Chevy
@@ -668,6 +669,9 @@ alter table t1 modify column txt blob;
explain select * from t1 where txt='Chevy' or txt is NULL;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL txt_index NULL NULL NULL 4 Using where
+explain select * from t1 FORCE INDEX (`txt_index`) where txt='Chevy' or txt is NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref_or_null txt_index txt_index 23 const 2 Using where
select * from t1 where txt='Chevy' or txt is NULL;
id txt
1 Chevy
@@ -675,6 +679,9 @@ id txt
explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL txt_index NULL NULL NULL 4 Using where; Using filesort
+explain select * from t1 FORCE INDEX (`txt_index`) where txt='Chevy' or txt is NULL order by txt;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref_or_null txt_index txt_index 23 const 2 Using where; Using filesort
select * from t1 where txt='Chevy' or txt is NULL order by txt;
id txt
3 NULL
diff --git a/storage/tokudb/mysql-test/tokudb/r/type_datetime.result b/storage/tokudb/mysql-test/tokudb/r/type_datetime.result
index ed980f8cee1..dbe93b37271 100644
--- a/storage/tokudb/mysql-test/tokudb/r/type_datetime.result
+++ b/storage/tokudb/mysql-test/tokudb/r/type_datetime.result
@@ -363,7 +363,7 @@ greatest(cast('01-01-01' as date), '01-01-02') + 0
20010102
select least(cast('01-01-01' as datetime), '01-01-02') + 0;
least(cast('01-01-01' as datetime), '01-01-02') + 0
-20010101000000.000000
+20010101000000
select cast(least(cast('01-01-01' as datetime), '01-01-02') as signed);
cast(least(cast('01-01-01' as datetime), '01-01-02') as signed)
20010101000000
@@ -401,7 +401,7 @@ if(@bug28261 = f1, '', @bug28261:= f1)
2001-01-01
2002-02-02
Warnings:
-Warning 1292 Incorrect datetime value: ''
+Warning 1292 Truncated incorrect datetime value: ''
select if(@bug28261 = f1, '', @bug28261:= f1) from t1;
if(@bug28261 = f1, '', @bug28261:= f1)
2001-01-01
@@ -425,11 +425,11 @@ f1
2001-01-01 00:00:00
2002-02-02 00:00:00
Warnings:
-Warning 1292 Incorrect datetime value: '2002010'
+Warning 1292 Truncated incorrect datetime value: '2002010'
select * from t1 where f1 between 20020101 and 2007010100000;
f1
Warnings:
-Warning 1292 Incorrect datetime value: '2007010100000'
+Warning 1292 Truncated incorrect datetime value: '2007010100000'
drop table t1;
#
# Bug#27216: functions with parameters of different date types may
@@ -500,7 +500,7 @@ f1
45:44:44
15:44:44
Warnings:
-Warning 1292 Incorrect datetime value: '1'
+Warning 1292 Truncated incorrect datetime value: '1'
drop table t1;
create table t1 (a tinyint);
insert into t1 values (), (), ();
diff --git a/storage/tokudb/mysql-test/tokudb/r/type_varchar.result b/storage/tokudb/mysql-test/tokudb/r/type_varchar.result
index bf98e12ce16..881a4cd66ac 100644
--- a/storage/tokudb/mysql-test/tokudb/r/type_varchar.result
+++ b/storage/tokudb/mysql-test/tokudb/r/type_varchar.result
@@ -13,7 +13,7 @@ t1 CREATE TABLE `t1` (
show create table vchar;
Table Create Table
vchar CREATE TABLE `vchar` (
- `v` varchar(30) DEFAULT NULL,
+ `v` varchar(30)/*old*/ DEFAULT NULL,
`c` char(3) DEFAULT NULL,
`e` enum('abc','def','ghi') DEFAULT NULL,
`t` text DEFAULT NULL
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_add_drop.test b/storage/tokudb/mysql-test/tokudb/t/card_add_drop.test
index 8563bf28ad1..66b26f20123 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_add_drop.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_add_drop.test
@@ -7,6 +7,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, c int, d int, key(a), key(b), key(c));
insert into tt values (0,0,0,0),(1,0,0,0),(2,0,1,0),(3,0,1,0);
@@ -24,5 +27,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_add_index.test b/storage/tokudb/mysql-test/tokudb/t/card_add_index.test
index 455dae55236..54f29fcf289 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_add_index.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_add_index.test
@@ -7,6 +7,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, c int, primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
@@ -30,5 +33,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_drop_index.test b/storage/tokudb/mysql-test/tokudb/t/card_drop_index.test
index b8e7d575dbd..a300f035519 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_drop_index.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_drop_index.test
@@ -7,6 +7,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
@@ -26,5 +29,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_drop_index_2.test b/storage/tokudb/mysql-test/tokudb/t/card_drop_index_2.test
index 88e0f6a413f..9e8b412760c 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_drop_index_2.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_drop_index_2.test
@@ -7,6 +7,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, c int, primary key(a), key(b), key(c));
let $a=0;
while ($a < 500) {
@@ -32,4 +35,5 @@ show indexes from tt;
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_drop_pk.test b/storage/tokudb/mysql-test/tokudb/t/card_drop_pk.test
index 365d920aa80..8de6a1dc7f2 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_drop_pk.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_drop_pk.test
@@ -7,6 +7,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, c int, key(b), key(c), primary key(a));
insert into tt values (1,0,0),(2,0,0),(3,0,1),(4,0,1);
@@ -22,5 +25,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_pk_2.test b/storage/tokudb/mysql-test/tokudb/t/card_pk_2.test
index 826714931aa..b24ff0f26f0 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_pk_2.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_pk_2.test
@@ -5,6 +5,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, primary key(a,b));
insert into tt values (0,0),(0,1),(1,0),(1,1);
@@ -16,5 +19,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_pk_sk.test b/storage/tokudb/mysql-test/tokudb/t/card_pk_sk.test
index f1e11fbbc2a..7e66c677930 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_pk_sk.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_pk_sk.test
@@ -5,6 +5,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, primary key(a), key(b));
let $i=0;
while ($i < 1000) {
@@ -40,6 +43,7 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test b/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test
index 75c53611308..ded6401c09d 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test
@@ -6,6 +6,9 @@ set @orig_throttle = @@session.tokudb_analyze_throttle;
set @orig_time = @@session.tokudb_analyze_time;
set @orig_scale_percent = @@global.tokudb_cardinality_scale_percent;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, c int, d int, primary key(a), key(b), key(c), key(d)) engine=tokudb;
let $i=0;
while ($i < 1000) {
@@ -50,5 +53,6 @@ drop table tt;
set session tokudb_analyze_throttle = @orig_throttle;
set session tokudb_analyze_time = @orig_time;
set global tokudb_cardinality_scale_percent = @orig_scale_percent;
+set @@use_stat_tables = @save_use_stat_tables;
-- enable_query_log
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_sk.test b/storage/tokudb/mysql-test/tokudb/t/card_sk.test
index cf50b8b167b..12c9ddbb811 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_sk.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_sk.test
@@ -5,6 +5,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, key(b));
insert into tt values (1,0),(2,1),(3,2),(4,3);
insert into tt values (5,0),(6,1),(7,2),(8,3);
@@ -17,5 +20,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/card_sk_2.test b/storage/tokudb/mysql-test/tokudb/t/card_sk_2.test
index 2cd4ece972e..f29b938105f 100644
--- a/storage/tokudb/mysql-test/tokudb/t/card_sk_2.test
+++ b/storage/tokudb/mysql-test/tokudb/t/card_sk_2.test
@@ -5,6 +5,9 @@ disable_warnings;
drop table if exists tt;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table tt (a int, b int, key(a,b));
insert into tt values (0,0),(0,1),(1,0),(1,1);
@@ -16,5 +19,6 @@ show indexes from tt;
# test that cardinality is persistent
flush tables;
show indexes from tt;
+set @@use_stat_tables = @save_use_stat_tables;
drop table tt;
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_create_table.test b/storage/tokudb/mysql-test/tokudb/t/cluster_create_table.test
index c2196bf681e..0cace80e092 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_create_table.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_create_table.test
@@ -22,7 +22,9 @@ alter table t1 drop primary key;
alter table t1 add primary key (a,b,c,d);
alter table t1 add key bar(d,c,b,a) clustering=yes;
show create table t1;
-insert into t1 value (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(32,54,12,56);
+insert into t1 value
+ (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6),
+ (32,54,12,56);
explain select * from t1;
select * from t1;
explain select d from t1 where d > 30;
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_delete.test b/storage/tokudb/mysql-test/tokudb/t/cluster_delete.test
index 1c0ebad94e4..cb490920259 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_delete.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_delete.test
@@ -7,8 +7,10 @@ DROP TABLE IF EXISTS t1;
create table t1(a int, b int, c int, d int, primary key(a), key(b) clustering=yes, key (c))engine=tokudb;
-insert into t1 values (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),(9,90,900,9000);
-
+insert into t1 values
+ (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),
+ (5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),
+ (9,90,900,9000),(10,100,1000,10000),(11,110,1100,11000);
#normal queries
@@ -19,38 +21,38 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 850;
+select * from t1 where c > 850;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select a from t1 where a > 8;
-select a from t1 where a > 8;
+explain select a from t1 where a > 10;
+select a from t1 where a > 10;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where b > 30;
-select a,b from t1 where b > 30;
+explain select a,b from t1 where b > 70;
+select a,b from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 950;
+select a,c from t1 where c > 950;
delete from t1 where b>30 and b < 60;
select * from t1;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where a > 5;
-select * from t1 where a > 5;
+explain select * from t1 where a > 8;
+select * from t1 where a > 8;
# ignore rows column
--replace_column 9 NULL;
@@ -76,8 +78,8 @@ select a,b from t1 where b > 30;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 1050;
+select a,c from t1 where c > 1050;
alter table t1 drop primary key;
@@ -88,13 +90,13 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 1050;
+select * from t1 where c > 1050;
#covering indexes
@@ -105,13 +107,13 @@ select a from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where b > 30;
-select a,b from t1 where b > 30;
+explain select a,b from t1 where b > 70;
+select a,b from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 1050;
+select a,c from t1 where c > 1050;
delete from t1 where b > 10 and b < 90;
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_key.test b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_key.test
index 192e56f10a1..dc788d531d6 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_filter_key.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_filter_key.test
@@ -13,10 +13,10 @@ insert into t1 values (3,"30",300);
insert into t1 values (4,"40",400);
insert into t1 values (5,"50",500);
-explain select * from t1 where a > 2;
-select * from t1 where a > 2;
-select b from t1 where a > 2;
-select c from t1 where a > 2;
+explain select * from t1 where a > 3;
+select * from t1 where a > 3;
+select b from t1 where a > 3;
+select c from t1 where a > 3;
#explain delete from t1 where a <2;
delete from t1 where a <2;
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_query_plan.test b/storage/tokudb/mysql-test/tokudb/t/cluster_query_plan.test
index a438653958a..23207f277b2 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_query_plan.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_query_plan.test
@@ -11,18 +11,18 @@ insert into t1 values (1,1,1,1),(2,2,2,2),(3,3,3,3),(4,4,4,4),(5,5,5,5),(6,6,6,6
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 2;
+explain select * from t1 where b > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 2;
+explain select * from t1 where c > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where a > 4;
+explain select * from t1 where a > 7;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 7;
+explain select * from t1 where c > 8;
# ignore rows column
--replace_column 9 NULL;
explain select * from t1 where b > 7;
diff --git a/storage/tokudb/mysql-test/tokudb/t/cluster_update.test b/storage/tokudb/mysql-test/tokudb/t/cluster_update.test
index ce5a0254372..42a004f1f03 100644
--- a/storage/tokudb/mysql-test/tokudb/t/cluster_update.test
+++ b/storage/tokudb/mysql-test/tokudb/t/cluster_update.test
@@ -7,7 +7,10 @@ DROP TABLE IF EXISTS t1;
create table t1(a int, b int, c int, d int, primary key(a), key(b) clustering=yes, key (c))engine=tokudb;
-insert into t1 values (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),(5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),(9,90,900,9000);
+insert into t1 values
+ (1,10,100,1000),(2,20,200,2000),(3,30,300,3000),(4,40,400,4000),
+ (5,50,500,5000),(6,60,600,6000),(7,70,700,7000),(8,80,800,8000),
+ (9,90,900,9000),(10,100,1000,10000),(11,110,1100,11000);
#normal queries
@@ -19,30 +22,30 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 950;
+select * from t1 where c > 950;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select a from t1 where a > 8;
+explain select a from t1 where a > 10;
select a from t1 where a > 8;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where b > 30;
-select a,b from t1 where b > 30;
+explain select a,b from t1 where b > 70;
+select a,b from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 950;
+select a,c from t1 where c > 950;
update t1 set c = c+5, b = b+5 where b>30;
@@ -64,8 +67,8 @@ select * from t1 where c > 750;
#covering indexes
# ignore rows column
--replace_column 9 NULL;
-explain select a from t1 where a > 8;
-select a from t1 where a > 8;
+explain select a from t1 where a > 10;
+select a from t1 where a > 10;
# ignore rows column
--replace_column 4 NA 9 NULL;
@@ -86,13 +89,13 @@ select * from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where b > 30;
-select * from t1 where b > 30;
+explain select * from t1 where b > 70;
+select * from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select * from t1 where c > 750;
-select * from t1 where c > 750;
+explain select * from t1 where c > 950;
+select * from t1 where c > 950;
#covering indexes
# ignore rows column
@@ -102,13 +105,13 @@ select a from t1 where a > 5;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where b > 30;
-select a,b from t1 where b > 30;
+explain select a,b from t1 where b > 70;
+select a,b from t1 where b > 70;
# ignore rows column
--replace_column 9 NULL;
-explain select a,b from t1 where c > 750;
-select a,c from t1 where c > 750;
+explain select a,b from t1 where c > 950;
+select a,c from t1 where c > 950;
update t1 set c = c+5, b = b+5 where b>30;
select * from t1;
diff --git a/storage/tokudb/mysql-test/tokudb/t/tokudb_mrr.test b/storage/tokudb/mysql-test/tokudb/t/tokudb_mrr.test
index 6130933b279..dcee5940907 100644
--- a/storage/tokudb/mysql-test/tokudb/t/tokudb_mrr.test
+++ b/storage/tokudb/mysql-test/tokudb/t/tokudb_mrr.test
@@ -40,16 +40,16 @@ CREATE TABLE t1 (
b INT
) ENGINE=TokuDB;
-INSERT INTO t1 VALUES (1,1,1),(3,3,3),(5,5,5);
+INSERT INTO t1 VALUES (1,1,1),(3,3,3),(5,5,5),(7,7,7),(8,8,8),(9,9,9);
COMMIT;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SELECT @@tx_isolation;
START TRANSACTION;
-EXPLAIN SELECT * FROM t1 WHERE a >= 2 FOR UPDATE;
+EXPLAIN SELECT * FROM t1 WHERE a >= 8 FOR UPDATE;
-SELECT * FROM t1 WHERE a >= 2 FOR UPDATE;
+SELECT * FROM t1 WHERE a >= 8 FOR UPDATE;
connection con2;
@@ -58,7 +58,7 @@ SET TOKUDB_LOCK_TIMEOUT=2;
START TRANSACTION;
--error ER_LOCK_WAIT_TIMEOUT
-INSERT INTO t1 VALUES (2,2,2);
+INSERT INTO t1 VALUES (8,8,8);
ROLLBACK;
connection con1;
diff --git a/storage/tokudb/mysql-test/tokudb/t/type_blob.test b/storage/tokudb/mysql-test/tokudb/t/type_blob.test
index 6a429c46a55..c66986e6c71 100644
--- a/storage/tokudb/mysql-test/tokudb/t/type_blob.test
+++ b/storage/tokudb/mysql-test/tokudb/t/type_blob.test
@@ -133,8 +133,6 @@ select c,count(*) from t1 group by c;
select d,count(*) from t1 group by d;
drop table t1;
--- error 1071
-create table t1 (a text, unique (a(21000))); # should give an error
create table t1 (a text, key (a(2100))); # key is auto-truncated
replace_regex /ENGINE=[a-zA-Z]*/ENGINE=ENGINE/;
show create table t1;
@@ -366,6 +364,7 @@ create table t1 (id integer primary key auto_increment, txt text, index txt_inde
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
explain select * from t1 where txt='Chevy' or txt is NULL;
+explain select * from t1 FORCE INDEX (`txt_index`) where txt='Chevy' or txt is NULL;
select * from t1 where txt='Chevy ';
select * from t1 where txt='Chevy ' or txt='Chevy';
select * from t1 where txt='Chevy' or txt='Chevy ';
@@ -386,8 +385,10 @@ select * from t1 where txt > 'Chevy';
select * from t1 where txt >= 'Chevy';
alter table t1 modify column txt blob;
explain select * from t1 where txt='Chevy' or txt is NULL;
+explain select * from t1 FORCE INDEX (`txt_index`) where txt='Chevy' or txt is NULL;
select * from t1 where txt='Chevy' or txt is NULL;
explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
+explain select * from t1 FORCE INDEX (`txt_index`) where txt='Chevy' or txt is NULL order by txt;
select * from t1 where txt='Chevy' or txt is NULL order by txt;
drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_with_lock_sps.result b/storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_with_lock_sps.result
index 88f28362119..80402df665d 100644
--- a/storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_with_lock_sps.result
+++ b/storage/tokudb/mysql-test/tokudb_alter_table/r/hcad_with_lock_sps.result
@@ -20,7 +20,7 @@ z a b c
999 4 40 400
explain select * from foo where b > 20;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range b b 5 NULL 2 Using where; Using index
+1 SIMPLE foo index b b 5 NULL 4 Using where; Using index
select* from foo where b > 10;
z a b c
999 2 20 200
@@ -40,7 +40,7 @@ a b c
4 40 400
explain select * from foo where b > 20;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range b b 5 NULL 2 Using where; Using index
+1 SIMPLE foo index b b 5 NULL 4 Using where; Using index
select* from foo where b > 10;
a b c
2 20 200
@@ -59,7 +59,7 @@ a b c z
4 40 400 NULL
explain select * from foo where b > 20;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range b b 5 NULL 2 Using where; Using index
+1 SIMPLE foo index b b 5 NULL 4 Using where; Using index
select* from foo where b > 10;
a b c z
2 20 200 NULL
@@ -94,7 +94,7 @@ a b c
3 30 300
4 40 400
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range b b 5 NULL 2 Using where; Using index
+1 SIMPLE foo index b b 5 NULL 4 Using where; Using index
a b c
2 20 200
3 30 300
@@ -110,7 +110,7 @@ a b c
4 40 400
explain select * from foo where b > 20;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range b b 5 NULL 2 Using where; Using index
+1 SIMPLE foo index b b 5 NULL 4 Using where; Using index
select* from foo where b > 10;
a b c
2 20 200
@@ -154,7 +154,7 @@ a b c g
4 40 400 NULL
5 50 500 NULL
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range b b 5 NULL 3 Using where; Using index
+1 SIMPLE foo index b b 5 NULL 5 Using where; Using index
set autocommit=on;
explain select * from foo;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/disabled.def b/storage/tokudb/mysql-test/tokudb_bugs/disabled.def
index d0d1a47e006..b88809fadc2 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/disabled.def
+++ b/storage/tokudb/mysql-test/tokudb_bugs/disabled.def
@@ -1,2 +1,3 @@
5585: times out, too many huge insert...selects
db233: different execution path in mariadb, debug_sync point is not hit
+5733_tokudb: not stable results
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/5733_innodb.result b/storage/tokudb/mysql-test/tokudb_bugs/r/5733_innodb.result
index 10cdb4767f6..ba21899ed92 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/5733_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/5733_innodb.result
@@ -10003,25 +10003,25 @@ insert into t values (9998,0);
insert into t values (9999,0);
explain select id from t where id>0 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where; Using index
+1 SIMPLE t index PRIMARY PRIMARY 8 NULL # Using where; Using index
explain select * from t where id>0 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where
explain select id from t where id>1000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where; Using index
+1 SIMPLE t index PRIMARY PRIMARY 8 NULL # Using where; Using index
explain select * from t where id>1000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where
explain select id from t where id>5000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where; Using index
+1 SIMPLE t index PRIMARY PRIMARY 8 NULL # Using where; Using index
explain select * from t where id>5000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where
explain select id from t where id>6000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where; Using index
+1 SIMPLE t index PRIMARY PRIMARY 8 NULL # Using where; Using index
explain select * from t where id>6000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/5733_tokudb.result b/storage/tokudb/mysql-test/tokudb_bugs/r/5733_tokudb.result
index 1db2c5746e2..0a736a97ec9 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/5733_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/5733_tokudb.result
@@ -10009,7 +10009,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where
explain select id from t where id>1000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where; Using index
+1 SIMPLE t index PRIMARY PRIMARY 8 NULL # Using where; Using index
explain select * from t where id>1000 limit 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t range PRIMARY PRIMARY 8 NULL # Using where
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/PS-3773.result b/storage/tokudb/mysql-test/tokudb_bugs/r/PS-3773.result
index c870ac1c784..14c5554b754 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/PS-3773.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/PS-3773.result
@@ -1,3 +1,4 @@
+# restart: --log-error=MYSQLTEST_VARDIR/tmp/tokudb.bugs.PS-3773.log
CREATE TABLE t1(a INT, b INT, c INT, PRIMARY KEY(a), KEY(b)) ENGINE=TokuDB;
SET tokudb_auto_analyze=0;
INSERT INTO t1 VALUES(0,0,0), (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5);
@@ -6,3 +7,4 @@ SELECT * FROM t1 WHERE b = 2;
ERROR HY000: Index for table 't1' is corrupt; try to repair it
DROP TABLE t1;
FOUND 1 /ha_tokudb::read_full_row on table/ in tokudb.bugs.PS-3773.log
+# restart
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/bulk_fetch.result b/storage/tokudb/mysql-test/tokudb_bugs/r/bulk_fetch.result
index 86943c2d2f6..70201e3a8bb 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/bulk_fetch.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/bulk_fetch.result
@@ -60,13 +60,11 @@ c
400
500
600
-explain select * from foo where c > 300;
+explain select * from foo where c > 500;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE foo range c c 5 NULL 3 Using where; Using index
-select * from foo where c > 300;
+1 SIMPLE foo range c c 5 NULL 1 Using where; Using index
+select * from foo where c > 500;
a b c
-4 40 400
-5 50 500
6 60 600
drop table foo;
create table foo (a int, b int);
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result
index 70bc86e1abc..fb4718353be 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists t;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@use_stat_tables= COMPLEMENTARY;
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -13,9 +15,11 @@ t 0 PRIMARY 1 id A 6 NULL NULL BTREE
t 1 x 1 x A 6 NULL NULL YES BTREE
analyze table t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t 0 PRIMARY 1 id A 6 NULL NULL BTREE
t 1 x 1 x A 6 NULL NULL YES BTREE
+set @@use_stat_tables= @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result
index b6d9fd7da85..9746eb81aa1 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists t;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@use_stat_tables= COMPLEMENTARY;
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -12,9 +14,11 @@ t 0 PRIMARY 1 id A 4 NULL NULL BTREE
t 1 x 1 x A 4 NULL NULL YES BTREE
analyze table t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t 0 PRIMARY 1 id A 4 NULL NULL BTREE
t 1 x 1 x A 4 NULL NULL YES BTREE
+set @@use_stat_tables= @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result
index caaa963c325..f92bc361547 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists t;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -13,9 +15,11 @@ t 0 PRIMARY 1 id A 7 NULL NULL BTREE
t 1 x 1 x A 7 NULL NULL YES BTREE
analyze table t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t 0 PRIMARY 1 id A 7 NULL NULL BTREE
-t 1 x 1 x A 7 NULL NULL YES BTREE
+t 1 x 1 x A 3 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result
index 6d345d98c95..02939dba662 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists t;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -12,9 +14,11 @@ t 0 PRIMARY 1 id A 4 NULL NULL BTREE
t 1 x 1 x A 4 NULL NULL YES BTREE
analyze table t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t 0 PRIMARY 1 id A 4 NULL NULL BTREE
t 1 x 1 x A 4 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result
index 06639c311cf..cb4dfbf9d9b 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_2_pick.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists t;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@use_stat_tables= 'COMPLEMENTARY';
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -13,9 +15,11 @@ t 0 PRIMARY 1 id A 7 NULL NULL BTREE
t 1 x 1 x A 7 NULL NULL YES BTREE
analyze table t;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t 0 PRIMARY 1 id A 7 NULL NULL BTREE
t 1 x 1 x A 7 NULL NULL YES BTREE
+set @@use_stat_tables= @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result
index 62337802688..c9b32d51471 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db757_part_alter_analyze.result
@@ -1,5 +1,7 @@
set default_storage_engine='tokudb';
drop table if exists t;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table t (id int, x int, y int, primary key (id), key (x), key (y))
partition by range(id)
( partition p0 values less than (10), partition p1 values less than maxvalue);
@@ -11,6 +13,7 @@ t 1 x 1 x A 5 NULL NULL YES BTREE
t 1 y 1 y A 5 NULL NULL YES BTREE
alter table t analyze partition p0;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -19,6 +22,7 @@ t 1 x 1 x A 5 NULL NULL YES BTREE
t 1 y 1 y A 5 NULL NULL YES BTREE
alter table t analyze partition p1;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -33,6 +37,7 @@ t 1 x 1 x A 9 NULL NULL YES BTREE
t 1 y 1 y A 9 NULL NULL YES BTREE
alter table t analyze partition p0;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
@@ -41,10 +46,12 @@ t 1 x 1 x A 9 NULL NULL YES BTREE
t 1 y 1 y A 9 NULL NULL YES BTREE
alter table t analyze partition p1;
Table Op Msg_type Msg_text
+test.t analyze status Engine-independent statistics collected
test.t analyze status OK
show indexes from t;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
t 0 PRIMARY 1 id A 9 NULL NULL BTREE
t 1 x 1 x A 9 NULL NULL YES BTREE
t 1 y 1 y A 9 NULL NULL YES BTREE
+set @@use_stat_tables = @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store.result b/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store.result
index 65503b908ca..2f025dcfb3d 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store.result
@@ -2,6 +2,7 @@ SET DEFAULT_STORAGE_ENGINE = 'tokudb';
DROP TABLE IF EXISTS foo,bar;
create table foo (a int, b int);
create table bar (a int, key(a));
+# restart
show create table foo;
Table Create Table
foo CREATE TABLE `foo` (
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store2.result b/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store2.result
index b202da70fcf..f661af9a20e 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store2.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store2.result
@@ -5,6 +5,7 @@ create table foo (a bigint, b bigint);
create table bar (a int);
alter table foo drop column a;
alter table bar add column b int, add column c int;
+# restart
show create table foo;
Table Create Table
foo CREATE TABLE `foo` (
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store3.result b/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store3.result
index 08f157f5223..ca33bc0c64b 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store3.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/frm_store3.result
@@ -4,6 +4,7 @@ create table foo (a int, b int, key(b,a), primary key (a))engine=TokuDB;
create table bar (a bigint)engine=TokuDB;
alter table foo drop index b;
alter table bar add index (a);
+# restart
show create table foo;
Table Create Table
foo CREATE TABLE `foo` (
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/index_read.result b/storage/tokudb/mysql-test/tokudb_bugs/r/index_read.result
index 5d5c4d43cd8..5a5ba28bb82 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/r/index_read.result
+++ b/storage/tokudb/mysql-test/tokudb_bugs/r/index_read.result
@@ -150,13 +150,11 @@ a b c
2 20 200
1 100 100
1 10 100
-explain select * from foo where a>=4;
+explain select * from foo where a>=5;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE foo range a a 4 NULL NULL; Using where
-select * from foo where a>=4;
+select * from foo where a>=5;
a b c
-4 40 400
-4 400 400
5 50 500
5 500 500
6 60 600
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/bulk_fetch.test b/storage/tokudb/mysql-test/tokudb_bugs/t/bulk_fetch.test
index 41b8f1fa37f..11ce1e74b8c 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/bulk_fetch.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/bulk_fetch.test
@@ -26,8 +26,8 @@ alter table foo drop index b;
alter table foo add index c(c) clustering=yes;
select c from foo;
-explain select * from foo where c > 300;
-select * from foo where c > 300;
+explain select * from foo where c > 500;
+select * from foo where c > 500;
drop table foo;
# simple test on hidden primary key
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash.test
index 97dda1cb1b8..440a79a43d7 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash.test
@@ -5,6 +5,8 @@ set default_storage_engine='tokudb';
disable_warnings;
drop table if exists t;
enable_warnings;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@use_stat_tables= COMPLEMENTARY;
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
insert into t values (1,1),(3,1),(5,1);
@@ -12,4 +14,5 @@ insert into t values (2,1),(4,1),(6,1);
show indexes from t;
analyze table t;
show indexes from t;
+set @@use_stat_tables= @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1.test
index 3ef66a4b1e6..b395b70b62c 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1.test
@@ -5,10 +5,14 @@ set default_storage_engine='tokudb';
disable_warnings;
drop table if exists t;
enable_warnings;
+set @save_use_stat_tables= @@use_stat_tables;
+set @@use_stat_tables= COMPLEMENTARY;
+
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
insert into t values (1,1),(3,1),(5,1);
show indexes from t;
analyze table t;
show indexes from t;
+set @@use_stat_tables= @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1_pick.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1_pick.test
index b8044641109..c96c58f31ed 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1_pick.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_1_pick.test
@@ -5,6 +5,8 @@ set default_storage_engine='tokudb';
disable_warnings;
drop table if exists t;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
insert into t values (1,1),(3,2),(5,3);
@@ -12,4 +14,5 @@ insert into t values (2,1),(4,1),(6,1),(8,1);
show indexes from t;
analyze table t;
show indexes from t;
+set @@use_stat_tables = @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2.test
index ca10218cb05..de32dfd7f54 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2.test
@@ -5,10 +5,14 @@ set default_storage_engine='tokudb';
disable_warnings;
drop table if exists t;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
+
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
insert into t values (2,1),(4,1),(6,1);
show indexes from t;
analyze table t;
show indexes from t;
+set @@use_stat_tables = @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2_pick.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2_pick.test
index 2cc55ec864d..999ce6ba14f 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2_pick.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db756_card_part_hash_2_pick.test
@@ -5,6 +5,9 @@ set default_storage_engine='tokudb';
disable_warnings;
drop table if exists t;
enable_warnings;
+
+set @save_use_stat_tables= @@use_stat_tables;
+set @@use_stat_tables= 'COMPLEMENTARY';
create table t (id int, x int, primary key (id), key (x)) partition by hash(id) partitions 2;
show indexes from t;
insert into t values (1,1),(3,2),(5,3),(7,4);
@@ -12,4 +15,5 @@ insert into t values (2,1),(4,1),(6,1);
show indexes from t;
analyze table t;
show indexes from t;
+set @@use_stat_tables= @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/db757_part_alter_analyze.test b/storage/tokudb/mysql-test/tokudb_bugs/t/db757_part_alter_analyze.test
index fc1599591be..ab9d816be4b 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/db757_part_alter_analyze.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/db757_part_alter_analyze.test
@@ -4,6 +4,8 @@ set default_storage_engine='tokudb';
disable_warnings;
drop table if exists t;
enable_warnings;
+set @save_use_stat_tables = @@use_stat_tables;
+set @@use_stat_tables = COMPLEMENTARY;
create table t (id int, x int, y int, primary key (id), key (x), key (y))
partition by range(id)
@@ -22,5 +24,6 @@ alter table t analyze partition p0;
show indexes from t;
alter table t analyze partition p1;
show indexes from t;
+set @@use_stat_tables = @save_use_stat_tables;
drop table t;
diff --git a/storage/tokudb/mysql-test/tokudb_bugs/t/index_read.test b/storage/tokudb/mysql-test/tokudb_bugs/t/index_read.test
index 03664415349..c79a6341b3a 100644
--- a/storage/tokudb/mysql-test/tokudb_bugs/t/index_read.test
+++ b/storage/tokudb/mysql-test/tokudb_bugs/t/index_read.test
@@ -117,8 +117,8 @@ select * from foo where a<3 order by a desc;
#HA_READ_KEY_OR_NEXT
# ignore rows column
--replace_column 9 NULL;
-explain select * from foo where a>=4;
-select * from foo where a>=4;
+explain select * from foo where a>=5;
+select * from foo where a>=5;
#HA_READ_KEY_OR_PREV not used anymore
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/r/clustering.result b/storage/tokudb/mysql-test/tokudb_mariadb/r/clustering.result
index 28c758ff628..fca204e28eb 100644
--- a/storage/tokudb/mysql-test/tokudb_mariadb/r/clustering.result
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/r/clustering.result
@@ -12,6 +12,7 @@ insert t1 values (1, 1, 1);
insert t1 select a+1, a+1, a+1 from t1;
insert t1 select a+2, a+2, a+2 from t1;
insert t1 select a+4, a+4, a+4 from t1;
+insert t1 select a+8, a+8, a+8 from t1;
select * from t1;
a b c
1 1 1
@@ -22,10 +23,18 @@ a b c
6 6 6
7 7 7
8 8 8
-explain select a,c from t1 where a > 2;
+9 9 9
+10 10 10
+11 11 11
+12 12 12
+13 13 13
+14 14 14
+15 15 15
+16 16 16
+explain select a,c from t1 where a > 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 5 NULL 6 Using where; Using index
-explain select b,c from t1 where b > 2;
+1 SIMPLE t1 index a a 5 NULL 16 Using where; Using index
+explain select b,c from t1 where b > 4;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ALL b NULL NULL NULL 8 Using where
+1 SIMPLE t1 ALL b NULL NULL NULL 16 Using where
drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb_mariadb/t/clustering.test b/storage/tokudb/mysql-test/tokudb_mariadb/t/clustering.test
index 58d806ee365..ce7ef42a7f3 100644
--- a/storage/tokudb/mysql-test/tokudb_mariadb/t/clustering.test
+++ b/storage/tokudb/mysql-test/tokudb_mariadb/t/clustering.test
@@ -6,10 +6,11 @@ insert t1 values (1, 1, 1);
insert t1 select a+1, a+1, a+1 from t1;
insert t1 select a+2, a+2, a+2 from t1;
insert t1 select a+4, a+4, a+4 from t1;
+insert t1 select a+8, a+8, a+8 from t1;
select * from t1;
-explain select a,c from t1 where a > 2;
-explain select b,c from t1 where b > 2;
+explain select a,c from t1 where a > 4;
+explain select b,c from t1 where b > 4;
drop table t1;
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_2_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_2_tokudb.result
index 410e6fd0ba2..994be80c4fe 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_2_tokudb.result
@@ -517,6 +517,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1009,6 +1010,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1516,6 +1518,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2017,6 +2020,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2516,6 +2520,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3026,6 +3031,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3538,6 +3544,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4038,6 +4045,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4531,6 +4539,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5023,6 +5032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5530,6 +5540,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6031,6 +6042,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6530,6 +6542,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7040,6 +7053,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7552,6 +7566,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8052,6 +8067,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8562,6 +8578,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9070,6 +9087,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9593,6 +9611,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10110,6 +10129,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10625,6 +10645,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11151,6 +11172,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11679,6 +11701,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12195,6 +12218,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12704,6 +12728,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13212,6 +13237,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13735,6 +13761,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14252,6 +14279,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14767,6 +14795,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15293,6 +15322,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15821,6 +15851,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16337,6 +16368,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16832,6 +16864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17325,6 +17358,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17833,6 +17867,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18335,6 +18370,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18835,6 +18871,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19346,6 +19383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19859,6 +19897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20360,6 +20399,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20854,6 +20894,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21347,6 +21388,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21855,6 +21897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22357,6 +22400,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22857,6 +22901,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23368,6 +23413,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23881,6 +23927,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24382,6 +24429,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24876,6 +24924,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25369,6 +25418,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25877,6 +25927,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26379,6 +26430,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26879,6 +26931,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27390,6 +27443,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27903,6 +27957,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28404,6 +28459,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_tokudb.result
index 093dbbe11c5..8b57e929951 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_1_tokudb.result
@@ -835,6 +835,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1327,6 +1328,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1834,6 +1836,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2335,6 +2338,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2836,6 +2840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3346,6 +3351,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3858,6 +3864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4358,6 +4365,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4851,6 +4859,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5343,6 +5352,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5850,6 +5860,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6351,6 +6362,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6852,6 +6864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7362,6 +7375,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7874,6 +7888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8374,6 +8389,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8884,6 +8900,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9392,6 +9409,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9915,6 +9933,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10432,6 +10451,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10949,6 +10969,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11475,6 +11496,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12003,6 +12025,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12519,6 +12542,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13028,6 +13052,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13536,6 +13561,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14059,6 +14085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14576,6 +14603,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15093,6 +15121,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15619,6 +15648,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16147,6 +16177,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16663,6 +16694,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_2_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_2_tokudb.result
index a05ce5cb71b..7103426b454 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter1_2_tokudb.result
@@ -464,6 +464,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -904,6 +905,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1359,6 +1361,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1808,6 +1811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2257,6 +2261,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2715,6 +2720,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3175,6 +3181,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3623,6 +3630,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4064,6 +4072,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4504,6 +4513,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4959,6 +4969,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5408,6 +5419,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5857,6 +5869,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6315,6 +6328,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6775,6 +6789,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7223,6 +7238,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7680,6 +7696,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8136,6 +8153,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8607,6 +8625,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9072,6 +9091,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9537,6 +9557,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10011,6 +10032,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10487,6 +10509,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10951,6 +10974,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11396,6 +11420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11836,6 +11861,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12291,6 +12317,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12740,6 +12767,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13187,6 +13215,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13645,6 +13674,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14105,6 +14135,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14553,6 +14584,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14994,6 +15026,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15434,6 +15467,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15889,6 +15923,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16338,6 +16373,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16785,6 +16821,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17243,6 +17280,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17703,6 +17741,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18151,6 +18190,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18609,6 +18649,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19065,6 +19106,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19536,6 +19578,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20001,6 +20044,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20464,6 +20508,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20938,6 +20983,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21414,6 +21460,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21878,6 +21925,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22335,6 +22383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22791,6 +22840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23262,6 +23312,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23727,6 +23778,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24190,6 +24242,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24664,6 +24717,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25140,6 +25194,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25604,6 +25659,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26046,6 +26102,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26486,6 +26543,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26941,6 +26999,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27390,6 +27449,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27837,6 +27897,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28295,6 +28356,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28755,6 +28817,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -29203,6 +29266,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -29644,6 +29708,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30084,6 +30149,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30539,6 +30605,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30988,6 +31055,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -31435,6 +31503,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -31893,6 +31962,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -32353,6 +32423,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -32801,6 +32872,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -33258,6 +33330,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -33714,6 +33787,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -34185,6 +34259,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -34650,6 +34725,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -35113,6 +35189,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -35587,6 +35664,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -36063,6 +36141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -36527,6 +36606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_1_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_1_tokudb.result
index a398ac33f42..eba06e441c9 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_1_tokudb.result
@@ -481,6 +481,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -937,6 +938,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1408,6 +1410,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1873,6 +1876,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2338,6 +2342,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2812,6 +2817,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3288,6 +3294,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3752,6 +3759,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4248,6 +4256,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4742,6 +4751,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5251,6 +5261,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5754,6 +5765,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6257,6 +6269,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6769,6 +6782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7283,6 +7297,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7785,6 +7800,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8280,6 +8296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8774,6 +8791,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9283,6 +9301,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9786,6 +9805,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10289,6 +10309,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10801,6 +10822,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11315,6 +11337,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11817,6 +11840,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12327,6 +12351,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12835,6 +12860,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13358,6 +13384,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13875,6 +13902,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14392,6 +14420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14918,6 +14947,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15446,6 +15476,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15962,6 +15993,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16471,6 +16503,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16979,6 +17012,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17502,6 +17536,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18019,6 +18054,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18536,6 +18572,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19062,6 +19099,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19590,6 +19628,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20106,6 +20145,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_2_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_2_tokudb.result
index 60cc765a570..6acd1198d16 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_1_2_tokudb.result
@@ -477,6 +477,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -933,6 +934,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1404,6 +1406,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1869,6 +1872,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2332,6 +2336,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2806,6 +2811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3282,6 +3288,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3746,6 +3753,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4243,6 +4251,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4738,6 +4747,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5248,6 +5258,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5752,6 +5763,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6254,6 +6266,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6767,6 +6780,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7282,6 +7296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7785,6 +7800,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8281,6 +8297,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8776,6 +8793,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9286,6 +9304,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9790,6 +9809,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10292,6 +10312,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10805,6 +10826,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11320,6 +11342,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11823,6 +11846,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12333,6 +12357,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12841,6 +12866,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13364,6 +13390,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13881,6 +13908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14396,6 +14424,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14922,6 +14951,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15450,6 +15480,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15966,6 +15997,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16475,6 +16507,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16983,6 +17016,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17506,6 +17540,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18023,6 +18058,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18538,6 +18574,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19064,6 +19101,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19592,6 +19630,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20108,6 +20147,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_1_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_1_tokudb.result
index 0b5d8289ecc..6f58b3de45a 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_1_tokudb.result
@@ -483,6 +483,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -941,6 +942,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1414,6 +1416,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1879,6 +1882,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2346,6 +2350,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2820,6 +2825,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3298,6 +3304,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3764,6 +3771,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4261,6 +4269,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4757,6 +4766,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5268,6 +5278,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5771,6 +5782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6276,6 +6288,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6788,6 +6801,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7304,6 +7318,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7808,6 +7823,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8305,6 +8321,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8801,6 +8818,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9312,6 +9330,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9815,6 +9834,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10320,6 +10340,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10832,6 +10853,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11348,6 +11370,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11852,6 +11875,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12364,6 +12388,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12874,6 +12899,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13399,6 +13425,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13916,6 +13943,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14435,6 +14463,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14961,6 +14990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15491,6 +15521,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16009,6 +16040,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16520,6 +16552,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17030,6 +17063,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17555,6 +17589,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18072,6 +18107,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18591,6 +18627,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19117,6 +19154,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19647,6 +19685,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20165,6 +20204,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_2_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_2_tokudb.result
index 67bae3acecb..2a1049bb5ee 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_2_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter2_2_2_tokudb.result
@@ -479,6 +479,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -938,6 +939,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1412,6 +1414,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1882,6 +1885,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2350,6 +2354,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2829,6 +2834,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3308,6 +3314,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3775,6 +3782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4275,6 +4283,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4773,6 +4782,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5286,6 +5296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5795,6 +5806,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6302,6 +6314,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6820,6 +6833,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7338,6 +7352,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7844,6 +7859,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8343,6 +8359,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8841,6 +8858,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9354,6 +9372,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9863,6 +9882,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10370,6 +10390,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10888,6 +10909,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11406,6 +11428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11912,6 +11935,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12425,6 +12449,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12936,6 +12961,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13462,6 +13488,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13984,6 +14011,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14504,6 +14532,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15035,6 +15064,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15566,6 +15596,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16085,6 +16116,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16597,6 +16629,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17108,6 +17141,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17634,6 +17668,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18156,6 +18191,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18676,6 +18712,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19207,6 +19244,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19738,6 +19776,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20257,6 +20296,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter4_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter4_tokudb.result
index 808f646dd48..27c473e0a5a 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter4_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_alter4_tokudb.result
@@ -60,6 +60,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -483,6 +484,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -519,6 +521,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -945,6 +948,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -989,6 +993,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -1418,6 +1423,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1460,6 +1466,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -1885,6 +1892,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1925,6 +1933,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -2352,6 +2361,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2396,6 +2406,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -2828,6 +2839,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2872,6 +2884,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -3306,6 +3319,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3346,6 +3360,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -3772,6 +3787,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3810,6 +3826,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -4233,6 +4250,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4269,6 +4287,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -4695,6 +4714,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4739,6 +4759,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -5168,6 +5189,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5210,6 +5232,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -5635,6 +5658,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5675,6 +5699,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -6102,6 +6127,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6146,6 +6172,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -6578,6 +6605,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6622,6 +6650,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -7056,6 +7085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7096,6 +7126,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION part_1,part_2;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -7522,6 +7553,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7983,6 +8015,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8445,6 +8478,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8918,6 +8952,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9385,6 +9420,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9852,6 +9888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10328,6 +10365,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10806,6 +10844,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11272,6 +11311,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11733,6 +11773,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12195,6 +12236,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12668,6 +12710,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13135,6 +13178,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13602,6 +13646,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14078,6 +14123,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14556,6 +14602,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15022,6 +15069,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15060,6 +15108,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -15483,6 +15532,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15519,6 +15569,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -15945,6 +15996,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15989,6 +16041,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -16418,6 +16471,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16460,6 +16514,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -16885,6 +16940,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16925,6 +16981,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -17352,6 +17409,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17396,6 +17454,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -17828,6 +17887,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17872,6 +17932,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -18306,6 +18367,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18346,6 +18408,7 @@ SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
WHERE f_int1 BETWEEN 1 AND @max_row_div2 - 1;
ALTER TABLE t1 ANALYZE PARTITION ALL;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
INSERT INTO t1(f_int1,f_int2,f_char1,f_char2,f_charbig)
SELECT f_int1,f_int2,f_char1,f_char2,f_charbig FROM t0_template
@@ -18772,6 +18835,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19236,6 +19300,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19698,6 +19763,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20171,6 +20237,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20638,6 +20705,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21105,6 +21173,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21581,6 +21650,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22059,6 +22129,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22525,6 +22596,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22986,6 +23058,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23448,6 +23521,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23921,6 +23995,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24388,6 +24463,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24855,6 +24931,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25331,6 +25408,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25809,6 +25887,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26275,6 +26354,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26736,6 +26816,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27198,6 +27279,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27671,6 +27753,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28138,6 +28221,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28605,6 +28689,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -29081,6 +29166,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -29559,6 +29645,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30025,6 +30112,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30486,6 +30574,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30948,6 +31037,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -31421,6 +31511,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -31888,6 +31979,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -32355,6 +32447,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -32831,6 +32924,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -33309,6 +33403,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -33775,6 +33870,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -34236,6 +34332,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -34698,6 +34795,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -35171,6 +35269,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -35638,6 +35737,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -36105,6 +36205,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -36581,6 +36682,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -37059,6 +37161,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -37525,6 +37628,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -37990,6 +38094,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -38453,6 +38558,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -38927,6 +39033,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -39395,6 +39502,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -39863,6 +39971,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -40340,6 +40449,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -40819,6 +40929,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -41286,6 +41397,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -41748,6 +41860,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -42211,6 +42324,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -42685,6 +42799,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -43153,6 +43268,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -43621,6 +43737,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -44098,6 +44215,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -44577,6 +44695,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -45044,6 +45163,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -45505,6 +45625,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -45967,6 +46088,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -46440,6 +46562,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -46907,6 +47030,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -47374,6 +47498,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -47850,6 +47975,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -48328,6 +48454,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -48794,6 +48921,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -49255,6 +49383,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -49717,6 +49846,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -50190,6 +50320,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -50657,6 +50788,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -51124,6 +51256,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -51600,6 +51733,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -52078,6 +52212,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -52544,6 +52679,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -53006,6 +53142,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -53469,6 +53606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -53943,6 +54081,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -54411,6 +54550,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -54879,6 +55019,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -55356,6 +55497,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -55835,6 +55977,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -56302,6 +56445,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -56764,6 +56908,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -57224,6 +57369,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -57695,6 +57841,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -58160,6 +58307,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -58625,6 +58773,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -59099,6 +59248,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -59575,6 +59725,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -60039,6 +60190,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -60498,6 +60650,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -60958,6 +61111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -61429,6 +61583,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -61894,6 +62049,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -62359,6 +62515,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -62833,6 +62990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -63309,6 +63467,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -63773,6 +63932,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -64552,6 +64712,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -65012,6 +65173,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -65483,6 +65645,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -65948,6 +66111,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -66413,6 +66577,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -66887,6 +67052,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -67363,6 +67529,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -67827,6 +67994,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -68291,6 +68459,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -68753,6 +68922,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -69226,6 +69396,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -69693,6 +69864,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -70160,6 +70332,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -70636,6 +70809,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -71114,6 +71288,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -71580,6 +71755,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -72041,6 +72217,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -72503,6 +72680,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -72976,6 +73154,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -73443,6 +73622,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -73910,6 +74090,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -74386,6 +74567,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -74864,6 +75046,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -75330,6 +75513,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -75791,6 +75975,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -76253,6 +76438,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -76726,6 +76912,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -77193,6 +77380,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -77660,6 +77848,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -78136,6 +78325,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -78614,6 +78804,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -79080,6 +79271,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -79541,6 +79733,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -80003,6 +80196,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -80476,6 +80670,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -80943,6 +81138,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -81410,6 +81606,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -81886,6 +82083,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -82364,6 +82562,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -82830,6 +83029,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -83291,6 +83491,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -83753,6 +83954,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -84226,6 +84428,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -84693,6 +84896,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -85160,6 +85364,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -85636,6 +85841,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -86114,6 +86320,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -86580,6 +86787,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -87039,6 +87247,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -87493,6 +87702,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -87955,6 +88165,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -88415,6 +88626,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -88873,6 +89085,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -89335,6 +89548,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -89797,6 +90011,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -90255,6 +90470,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_basic_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_basic_tokudb.result
index ae20097fdda..8c19f82b9b6 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_basic_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_basic_tokudb.result
@@ -484,6 +484,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -939,6 +940,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1409,6 +1411,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1873,6 +1876,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2337,6 +2341,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2810,6 +2815,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3289,6 +3295,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3752,6 +3759,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4209,6 +4217,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4664,6 +4673,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5134,6 +5144,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5598,6 +5609,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6060,6 +6072,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -6533,6 +6546,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7008,6 +7022,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7471,6 +7486,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -7969,6 +7985,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8461,6 +8478,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -8968,6 +8986,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9469,6 +9488,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -9970,6 +9990,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10480,6 +10501,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -10996,6 +11018,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11496,6 +11519,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -11989,6 +12013,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12481,6 +12506,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -12988,6 +13014,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13489,6 +13516,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -13990,6 +14018,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -14500,6 +14529,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15016,6 +15046,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -15516,6 +15547,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16025,6 +16057,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -16533,6 +16566,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17056,6 +17090,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -17573,6 +17608,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18090,6 +18126,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -18616,6 +18653,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19148,6 +19186,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -19664,6 +19703,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20162,6 +20202,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -20654,6 +20695,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21161,6 +21203,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -21662,6 +21705,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22161,6 +22205,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -22671,6 +22716,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23183,6 +23229,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -23683,6 +23730,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24176,6 +24224,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -24668,6 +24717,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25175,6 +25225,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -25676,6 +25727,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26175,6 +26227,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -26685,6 +26738,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27197,6 +27251,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -27697,6 +27752,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28206,6 +28262,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -28714,6 +28771,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -29237,6 +29295,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -29754,6 +29813,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30269,6 +30329,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -30795,6 +30856,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -31323,6 +31385,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -31839,6 +31902,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result
index a921ba0f56d..028809cd36b 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_engine_tokudb.result
@@ -475,6 +475,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -933,6 +934,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1395,6 +1397,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -1920,6 +1923,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2421,6 +2425,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -2883,6 +2888,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3342,6 +3348,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -3804,6 +3811,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4269,6 +4277,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -4723,6 +4732,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
@@ -5178,6 +5188,7 @@ AND f_int2 <> CAST(f_char1 AS SIGNED INT)
AND f_charbig = '####updated per insert trigger####';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
+test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
CHECK TABLE t1 EXTENDED;
Table Op Msg_type Msg_text
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result
index 4c30d47f526..558c3cbdff4 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc0_tokudb.result
@@ -1020,6 +1020,7 @@ a b
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
+MySQL_Test_DB.t1 analyze status Engine-independent statistics collected
MySQL_Test_DB.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result
index 6ccd9afefab..1c2f23a277b 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc10_tokudb.result
@@ -949,6 +949,7 @@ a b
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
+MySQL_Test_DB.t1 analyze status Engine-independent statistics collected
MySQL_Test_DB.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result
index fce0d496032..76418679582 100644
--- a/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result
+++ b/storage/tokudb/mysql-test/tokudb_parts/r/partition_mgm_lc1_tokudb.result
@@ -987,6 +987,7 @@ a b
2001 Second in MAX
ALTER TABLE t1 ANALYZE PARTITION MAX;
Table Op Msg_type Msg_text
+mysql_test_db.t1 analyze status Engine-independent statistics collected
mysql_test_db.t1 analyze status OK
# Truncate without FLUSH
ALTER TABLE t1 TRUNCATE PARTITION MAX;
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result b/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result
index d4532eec4e2..d79e7e59aa4 100644
--- a/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result
+++ b/storage/tokudb/mysql-test/tokudb_rpl/r/mdev12179.result
@@ -2,6 +2,7 @@ include/master-slave.inc
[connection master]
connection server_2;
include/stop_slave.inc
+SET GLOBAL gtid_cleanup_batch_size = 999999999;
CHANGE MASTER TO master_use_gtid=slave_pos;
SET sql_log_bin=0;
CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos;
@@ -41,6 +42,8 @@ a
1
SELECT * FROM mysql.gtid_slave_pos ORDER BY sub_id;
domain_id sub_id server_id seq_no
+0 1 1 1
+0 2 1 2
0 3 1 3
0 4 1 4
SELECT * FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
@@ -121,6 +124,21 @@ Transactions_multi_engine 6
DELETE FROM t1 WHERE a >= 100;
DELETE FROM t2 WHERE a >= 100;
DELETE FROM t3 WHERE a >= 100;
+connection server_1;
+include/save_master_gtid.inc
+connection server_2;
+include/sync_with_master_gtid.inc
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos;
+COUNT(*)>=10
+1
+SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
+UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select;
+COUNT(*)>=10
+1
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_tokudb;
+COUNT(*)>=10
+1
+SET GLOBAL gtid_cleanup_batch_size = 3;
connection server_2;
include/stop_slave.inc
SET sql_log_bin=0;
diff --git a/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test b/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test
index ceb119cd0dc..1d19a25889e 100644
--- a/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test
+++ b/storage/tokudb/mysql-test/tokudb_rpl/t/mdev12179.test
@@ -4,6 +4,12 @@
--connection server_2
--source include/stop_slave.inc
+
+# Set GTID cleanup limit high enough that cleanup will not run and we
+# can rely on consistent table output in .result.
+--let $old_gtid_cleanup_batch_size=`SELECT @@GLOBAL.gtid_cleanup_batch_size`
+SET GLOBAL gtid_cleanup_batch_size = 999999999;
+
CHANGE MASTER TO master_use_gtid=slave_pos;
SET sql_log_bin=0;
CREATE TABLE mysql.gtid_slave_pos_innodb LIKE mysql.gtid_slave_pos;
@@ -89,6 +95,82 @@ DELETE FROM t2 WHERE a >= 100;
DELETE FROM t3 WHERE a >= 100;
+# Create a bunch more GTIDs in mysql.gtid_slave_pos* tables to test with.
+--connection server_1
+--disable_query_log
+let $i=10;
+while ($i) {
+ eval INSERT INTO t1 VALUES (300+$i);
+ eval INSERT INTO t2 VALUES (300+$i);
+ eval INSERT INTO t3 VALUES (300+$i);
+ dec $i;
+}
+--enable_query_log
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+# Check that we have many rows in mysql.gtid_slave_pos now (since
+# @@gtid_cleanup_batch_size was set to a huge value). No need to check
+# for an exact number, since that will require changing .result if
+# anything changes prior to this point, and we just need to know that
+# we have still have some data in the tables to make the following
+# test effective.
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos;
+SELECT COUNT(*)>=10 FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
+ UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select;
+SELECT COUNT(*)>=10 FROM mysql.gtid_slave_pos_tokudb;
+
+# Check that old GTID rows will be deleted when batch delete size is
+# set reasonably. Old row deletion is not 100% deterministic (by design), so
+# we must wait for it to occur, but it should occur eventually.
+SET GLOBAL gtid_cleanup_batch_size = 3;
+let $i=40;
+--disable_query_log
+--let $keep_include_silent=1
+while ($i) {
+ let N=`SELECT 1+($i MOD 3)`;
+ --connection server_1
+ eval UPDATE t$N SET a=a+1 WHERE a=(SELECT MAX(a) FROM t$N);
+ --source include/save_master_gtid.inc
+ --connection server_2
+ --source include/sync_with_master_gtid.inc
+ let $j=50;
+ while ($j) {
+ let $is_done=`SELECT SUM(a)=1 FROM (
+ SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos
+ UNION ALL
+ SELECT COUNT(*) AS a FROM ( SELECT * FROM mysql.gtid_slave_pos_innodb
+ UNION ALL SELECT * FROM mysql.gtid_slave_pos_innodb_redundant) inner_select
+ UNION ALL
+ SELECT COUNT(*) AS a FROM mysql.gtid_slave_pos_tokudb) outer_select`;
+ if ($is_done) {
+ let $j=0;
+ }
+ if (!$is_done) {
+ real_sleep 0.1;
+ dec $j;
+ }
+ }
+ dec $i;
+ if ($is_done) {
+ let $i=0;
+ }
+}
+--enable_query_log
+--let $keep_include_silent=0
+if (!$is_done) {
+ --echo Timed out waiting for mysql.gtid_slave_pos* tables to be cleaned up
+}
+
+--disable_query_log
+DELETE FROM t1 WHERE a >= 100;
+DELETE FROM t2 WHERE a >= 100;
+DELETE FROM t3 WHERE a >= 100;
+--enable_query_log
+
+
# Test status variables Rpl_transactions_multi_engine and Transactions_gtid_foreign_engine.
# Have mysql.gtid_slave_pos* for myisam and innodb but not tokudb.
--connection server_2
@@ -223,6 +305,9 @@ SHOW STATUS LIKE "%transactions%engine";
SET sql_log_bin=0;
DROP TABLE mysql.gtid_slave_pos_innodb;
SET sql_log_bin=1;
+--disable_query_log
+eval SET GLOBAL gtid_cleanup_batch_size = $old_gtid_cleanup_batch_size;
+--enable_query_log
--connection server_1
DROP TABLE t1;
diff --git a/storage/tokudb/tokudb_dir_cmd.cc b/storage/tokudb/tokudb_dir_cmd.cc
index 5431cbab7aa..d0da92eab27 100644
--- a/storage/tokudb/tokudb_dir_cmd.cc
+++ b/storage/tokudb/tokudb_dir_cmd.cc
@@ -50,11 +50,11 @@ static int MDL_and_TDC(THD *thd,
table_arg.str = const_cast<char *>(table);
table_arg.length = strlen(table);
Table_ident table_ident(thd, &db_arg, &table_arg, true);;
- thd->lex->select_lex.add_table_to_list(
+ thd->lex->first_select_lex()->add_table_to_list(
thd, &table_ident, NULL, 1, TL_UNLOCK, MDL_EXCLUSIVE, 0, 0, 0);
/* The lock will be released at the end of mysq_execute_command() */
error = lock_table_names(thd,
- thd->lex->select_lex.table_list.first,
+ thd->lex->first_select_lex()->table_list.first,
NULL,
thd->variables.lock_wait_timeout,
0);
diff --git a/storage/tokudb/tokudb_sysvars.cc b/storage/tokudb/tokudb_sysvars.cc
index c9f72f6a34d..684a952750f 100644
--- a/storage/tokudb/tokudb_sysvars.cc
+++ b/storage/tokudb/tokudb_sysvars.cc
@@ -901,7 +901,7 @@ static MYSQL_THDVAR_BOOL(
NULL,
false);
-static MYSQL_THDVAR_BOOL(
+ static MYSQL_THDVAR_BOOL(
enable_fast_upsert,
PLUGIN_VAR_THDLOCAL,
"disable slow upsert",